-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
BUG: Prevent passing of size 0 to array alloc C functions #13691
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
It might have been better to check the asserts fired by adding them first, and then making sure we have tests covering each of the cases where you checked for zero size. Then we could be reasonably sure our test suite exercises the new code paths. Coverage points to a few code paths as untested with the 0 condition. (Assuming you know this: when you want to check c-level |
Thanks, I wasn't aware of I removed my size 0 checks and kept only the assertions. But I couldn't find a way to trace the exception or find the generated report.
But pdb didn't work for me with runtests combined with C assert. |
@oribro that is perfect, the Aborted means you hit the |
ok, I made some progress and found the untested code paths that @mattip mentioned.
And I'm not sure how to make the tests work with it.
What am I missing here? |
Well, if that is all, then it sounds pretty harmless, since it just does not find |
Thanks, so here is a summary for what I found so far:
In general, I found the size 0 problem to be related to flexible data types such as np.dtype('V') or more specific to
Which other examples of data types with size 0 can be tested? For the tests above, When I changed the datatype, the tested C function was not called for the new dt, or an error was raised stating the dt is not supported or that the conversion did not succeed, so it was quite confusing.
such that
and since So yeah, I put some effort to try and tackle this issue, but I feel I reached a dead end with no clear strategy to continue. |
|
d9ed18a
to
8dfbc81
Compare
Ok, so for now I've kept the checks that were covered by the existing tests, and updated the PR. |
numpy/core/src/multiarray/methods.c
Outdated
if (PyArray_DATA(self) == NULL) { | ||
fa->nd = 0; | ||
fa->data = PyDataMem_NEW(PyArray_DESCR(self)->elsize); | ||
fa->data = PyDataMem_NEW(elsize); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize this was here before your PR, but it seems strange. What is this supposed to do? We could not allocate num
bytes of memory, so now we allocate elsize
instead and raise an error?
Your code looks "correct" but the whole idea looks wrong. Maybe it is a separate issue, this code somehow slipped in during different refactorings?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree, this is quite odd.
I can add that this NULL check was not covered by the tests even before my changes and I found it difficult to reproduce.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
opened #13724 to clean up the code not related to this PR
LGTM. Anyone else want to take a look? |
8dfbc81
to
03052b7
Compare
@mattip Sure |
Coverage is all green now, in it goes. Thanks @oribro |
else { | ||
PyArray_DIMS(r)[0] = *nread; | ||
((PyArrayObject_fields *)r)->data = tmp; | ||
const size_t nsize = PyArray_MAX(*nread,1)*dtype->elsize; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this MAX
was actually a previous failed attempt to prevent this.
Hi,
So this is my first bug fix attempt with core code,
I tried the approach of ensuring that size 0 is not passed to
PyDataMem_NEW
andPyDataMem_RENEW
, both found incore/multiarray/alloc.c
.I looked up all the places in the code I could find that make calls to these functions and checked for size 0 explicitly, in that case the call to the alloc function will be skipped.
After that I used
assert(size != 0)
inside these functions to make any remaining calls fail.In
ctors.c
I found code that uses "pass size 1 approach and make the allocation succeed". For consistency I changed it to skip as well.I verified that the existing tests pass on my machine:
See #13645
I'll appreciate any reviews, thanks!