-
-
Notifications
You must be signed in to change notification settings - Fork 8.2k
py/objint: Fix int.to_bytes() buffer size checks. #13087
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
7473451
to
8e7dcac
Compare
Code size report:
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #13087 +/- ##
=======================================
Coverage 98.42% 98.42%
=======================================
Files 161 161
Lines 21234 21248 +14
=======================================
+ Hits 20900 20914 +14
Misses 334 334 ☔ View full report in Codecov by Sentry. |
d509c0b
to
c97d353
Compare
262a9ab
to
fe533a8
Compare
dc8c049
to
ed3a113
Compare
int slen = MP_INT_REPR_LEN(val, val < 0); | ||
memset(data, val < 0 ? 0xFF : 0x00, dlen); | ||
if (slen <= dlen) { | ||
mp_binary_set_int(slen, big_endian, data + (big_endian ? (dlen - slen) : 0), val); |
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.
For later consideration (not this PR): can mp_binary_set_val and this function be combined to save size?
} else { | ||
return mp_clzll(x); | ||
} | ||
} |
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 don't really like this approach but it seems the least bad that works across all configurations and isn't too intrusive.
The other way I thought to do it was to only define mp_clz32()
and mp_clz64()
and then have each port define MP_SIZEOF_INT
or a similar macro.
@dpgeorge Finally found a combination that works across all ports, I think! |
We need to go with the fixes here, even though they are relatively large in size. Otherwise there are subtle bugs in the integer/byte conversion. |
Signed-off-by: Angus Gratton <angus@redyak.com.au>
Fixes and improvements to `int.to_bytes()` are: - No longer overflows if byte size is 0 (closes micropython#13041). - Raises OverflowError in any case where number won't fit into byte length (now matches CPython, previously MicroPython would return a truncated bytes object). - Document that `micropython int.to_bytes()` doesn't implement the optional signed kwarg, but will behave as if `signed=True` when the integer is negative (this is the current behaviour). Add tests for this also. Requires changes for small ints, MPZ large ints, and "long long" large ints. Adds a new set of unit tests for ints between 32 and 64 bits to increase coverage of "long long" large ints, which are otherwise untested. Tested on unix port (64 bit small ints, MPZ long ints) and Zephyr STM32WB board (32 bit small ints, long long large ints). This work was funded through GitHub Sponsors. Signed-off-by: Angus Gratton <angus@redyak.com.au>
ed3a113
to
908ab1c
Compare
This "little fix" ended up growing and growing, so this might be too much code size impact. In which case this should be closed. There's a much smaller patch which only fixes the first point from the list below.
int.to_bytes()
doesn't implement the optionalsigned
kwarg, but will behave as ifsigned=True
when the integer is negative (this is the current behaviour). Add tests for this also.Changes are implemented for small ints, MPZ large ints, and "long long" large ints.
Adds a new set of unit tests for ints between 32 and 64 bits to increase coverage of "long long" large ints, which are otherwise untested.
Tested on unix port (64 bit small ints, MPZ long ints) and Zephyr STM32WB board (32 bit small ints, long long large ints).
Untested on a port whose native format is big endian (don't have one at hand).
This work was funded through GitHub Sponsors.