summaryrefslogtreecommitdiff
path: root/py/mpz.c
diff options
context:
space:
mode:
Diffstat (limited to 'py/mpz.c')
-rw-r--r--py/mpz.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/py/mpz.c b/py/mpz.c
index 502d4e1c1..750664ad9 100644
--- a/py/mpz.c
+++ b/py/mpz.c
@@ -1589,7 +1589,7 @@ bool mpz_as_uint_checked(const mpz_t *i, mp_uint_t *value) {
return true;
}
-void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) {
+bool mpz_as_bytes(const mpz_t *z, bool big_endian, bool as_signed, size_t len, byte *buf) {
byte *b = buf;
if (big_endian) {
b += len;
@@ -1598,6 +1598,8 @@ void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) {
int bits = 0;
mpz_dbl_dig_t d = 0;
mpz_dbl_dig_t carry = 1;
+ size_t olen = len; // bytes in output buffer
+ bool ok = true;
for (size_t zlen = z->len; zlen > 0; --zlen) {
bits += DIG_SIZE;
d = (d << DIG_SIZE) | *zdig++;
@@ -1607,28 +1609,32 @@ void mpz_as_bytes(const mpz_t *z, bool big_endian, size_t len, byte *buf) {
val = (~val & 0xff) + carry;
carry = val >> 8;
}
+
+ if (!olen) {
+ // Buffer is full, only OK if all remaining bytes are zeroes
+ ok = ok && ((byte)val == 0);
+ continue;
+ }
+
if (big_endian) {
*--b = val;
- if (b == buf) {
- return;
- }
} else {
*b++ = val;
- if (b == buf + len) {
- return;
- }
}
+ olen--;
}
}
- // fill remainder of buf with zero/sign extension of the integer
- if (big_endian) {
- len = b - buf;
+ if (as_signed && olen == 0 && len > 0) {
+ // If output exhausted then ensure there was enough space for the sign bit
+ byte most_sig = big_endian ? buf[0] : buf[len - 1];
+ ok = ok && (bool)(most_sig & 0x80) == (bool)z->neg;
} else {
- len = buf + len - b;
- buf = b;
+ // fill remainder of buf with zero/sign extension of the integer
+ memset(big_endian ? buf : b, z->neg ? 0xff : 0x00, olen);
}
- memset(buf, z->neg ? 0xff : 0x00, len);
+
+ return ok;
}
#if MICROPY_PY_BUILTINS_FLOAT