summaryrefslogtreecommitdiff
path: root/py/mpz.h
diff options
context:
space:
mode:
authorAngus Gratton <angus@redyak.com.au>2023-11-29 11:23:16 +1100
committerDamien George <damien@micropython.org>2024-06-24 14:07:00 +1000
commit908ab1ceca15ee6fd0ef82ca4cba770a3ec41894 (patch)
tree94d7e1d9e191d277f9500a310d8247ca528cfc37 /py/mpz.h
parentd933210d960a6f9337e85753e9568619bbfd54ec (diff)
py/objint: Fix int.to_bytes() buffer size checks.
Fixes and improvements to `int.to_bytes()` are: - No longer overflows if byte size is 0 (closes #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>
Diffstat (limited to 'py/mpz.h')
-rw-r--r--py/mpz.h9
1 files changed, 5 insertions, 4 deletions
diff --git a/py/mpz.h b/py/mpz.h
index d27f57240..6f1ac930b 100644
--- a/py/mpz.h
+++ b/py/mpz.h
@@ -93,9 +93,9 @@ typedef int8_t mpz_dbl_dig_signed_t;
typedef struct _mpz_t {
// Zero has neg=0, len=0. Negative zero is not allowed.
size_t neg : 1;
- size_t fixed_dig : 1;
- size_t alloc : (8 * sizeof(size_t) - 2);
- size_t len;
+ size_t fixed_dig : 1; // flag, 'dig' buffer cannot be reallocated
+ size_t alloc : (8 * sizeof(size_t) - 2); // number of entries allocated in 'dig'
+ size_t len; // number of entries used in 'dig'
mpz_dig_t *dig;
} mpz_t;
@@ -145,7 +145,8 @@ static inline size_t mpz_max_num_bits(const mpz_t *z) {
mp_int_t mpz_hash(const mpz_t *z);
bool mpz_as_int_checked(const mpz_t *z, mp_int_t *value);
bool mpz_as_uint_checked(const mpz_t *z, mp_uint_t *value);
-void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf);
+// Returns true if 'z' fit into 'len' bytes of 'buf' without overflowing, 'buf' is truncated otherwise.
+bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf);
#if MICROPY_PY_BUILTINS_FLOAT
mp_float_t mpz_as_float(const mpz_t *z);
#endif