Skip to content
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

Avoid narrowing conversion in image_wrapper on 32-bit. #10736

Merged
merged 1 commit into from Mar 9, 2018

Conversation

anntzer
Copy link
Contributor

@anntzer anntzer commented Mar 9, 2018

PR Summary

@yurivict can you check whether that fixes #10698?

PR Checklist

  • Has Pytest style unit tests
  • Code is PEP 8 compliant
  • New features are documented, with examples if plot related
  • Documentation is sphinx and numpydoc compliant
  • Added an entry to doc/users/next_whats_new/ if major new feature (follow instructions in README.rst there)
  • Documented in doc/api/api_changes.rst if API changed in a backward-incompatible way

@yurivict
Copy link

yurivict commented Mar 9, 2018

Still fails:

src/_image_wrapper.cpp:422:24: error: non-constant-expression cannot be narrowed from type 'unsigned int' to 'npy_intp' (aka 'int') in initializer list [-Wc++11-narrowing]
    npy_intp dim[3] = {rows, cols, 4};
                       ^~~~

@anntzer
Copy link
Contributor Author

anntzer commented Mar 9, 2018

same fix applies there... pushed it

@yurivict
Copy link

yurivict commented Mar 9, 2018

Now it succeeds, thanks!

@tacaswell
Copy link
Member

Just to check, the issue here is that we are implicitly casting a uint -> int which chops off half of the range of the uint and we were probably using uint because the rows / columns should always be positive. Now we are doing the cast explicitly in the PyArg_ParseTuple.

If this was going to cause any issue with the maximum size image we could render, it already would be?

@tacaswell tacaswell added this to the v2.2.1 milestone Mar 9, 2018
@tacaswell
Copy link
Member

Candidate for backport to 2.2.x because this fixes a 'does not compile' bug.

@anntzer
Copy link
Contributor Author

anntzer commented Mar 9, 2018

No, the issue is that (at the npy_intp dim[3] = {rows, cols, 4} line) we were casting an unsigned int (rows) to a npy_intp (intptr_t), which goes from 64bit to 32bit on the OP's architecture (I know this because the ft2 PR had the same issue when I made it work on circleci...), and that's something a compiler is required by the standard to flag (at least with a warning).

Now rows is declared as a npy_intp so everything has the same size. As for PyArg_ParseTuple, the compiler has no knowledge of that function and will happily accept any pointers passed in, but you'll get a crash at runtime if the pointer sizes don't match the format spec. In fact there is indeed an conversion from Py_ssize_t (signed) to npy_intp (unsigned, but at least in practice sizeof(size_t) == sizeof(intptr_t) on all common architechtures nowadays) going on, but that's not something crashing the compiler.

Now that means that yes, if someone passes a negative value for rows, it will be silently wrapped around to a yuge positive value. But in fact the unsigned convertors in PyArg_ParseTuple don't do any overflow checking (https://bugs.python.org/issue33033) so that issue was already present before; the PR actually slightly improves the situation because at least the signed n convertor does overflow checking and we now error cleanly on wildly out-of-range input.

@jklymak jklymak merged commit 5b7a21e into matplotlib:master Mar 9, 2018
lumberbot-app bot pushed a commit that referenced this pull request Mar 9, 2018
@anntzer anntzer deleted the narrowing branch March 9, 2018 22:27
tacaswell added a commit that referenced this pull request Mar 10, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Build fails in clang i386
4 participants