Repository navigation
gh-160708: Use the type size for resized ctypes simple objects - #160720
Conversation
After ctypes.resize(), a simple object's buffer is larger than its type. bool() and passing the object to a foreign function still used the buffer size, so bool() read past a 16-byte string literal and the call copied the whole buffer into the fixed-size PyCArgObject value, corrupting the heap. Use the type's size instead, like the value getter does since pythongh-159739. bool() now checks the value's bytes directly, which also covers simple types larger than 16 bytes such as c_longdouble_complex on x86-64.
|
Hi @JelleZijlstra, since you reviewed gh-159739 (#159767, reading resized ctypes scalars using their declared size): this PR is the follow-up for the two places that still use b_size after ctypes.resize(). Those are bool(), which reads past a 16-byte literal, and passing the object to a foreign function, which overflows PyCArgObject.value and corrupts the heap. Both now use info->size, like the value getter. CI is green. Would you have time to take a look? cc @ZeroIntensity |
Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
|
Thanks @iamsaugatpandey for the PR, and @ZeroIntensity for merging it 🌮🎉.. I'm working now to backport this PR to: 3.14, 3.15. |
|
Sorry, @iamsaugatpandey and @ZeroIntensity, I could not cleanly backport this to Please backport manually with cherry_picker, see the devguide for more information. |
|
Sorry, @iamsaugatpandey and @ZeroIntensity, I could not cleanly backport this to Please backport manually with cherry_picker, see the devguide for more information. |
After
ctypes.resize(), the buffer of a simple ctypes object is bigger than the type itself. Two places still used the buffer size (b_size) where they needed the type size:Simple_bool_impl()comparedb_sizebytes against a 16-byte zero string literal. For a resized object it reads past the literal, and it can also return the wrong answer (bool(c_int(0))isTrueif the extra space isn't zero).PyCSimpleType_paramfunc()copiedb_sizebytes intoPyCArgObject.value, which is a fixed-size union, so passing a resized object to a foreign function overwrote the heap.Both now use
info->size, the same as the value getter since gh-159739.bool()checks the value's bytes in a loop instead of comparing with the literal. This also covers simple types larger than 16 bytes, such asc_longdouble_complexon x86-64.Tests:
bool()on a resizedc_intwhose extra space is non-zero, a call totf_iwith a resizedc_int, andbool()on the complex types.