Ciao,
22 feb 2025, 11:18 da [email protected]:
> The bug likely exists because the source uses "int" to store sizes,
>
I do not agree. The behavior is a consequence of the file format.
> for example in this macro:
>
> #ifndef HTON_LIMB_STORE
> #define HTON_LIMB_STORE(dst, limb) \
>
[...]
> int __i; \
> for (__i = 0; __i < GMP_LIMB_BYTES; __i++) \
>
here the int variable is correctly used for numbers between 0 and
GMP_LIMB_BYTES (typically 4 or 8),
> There is also an "int bits;" on line 107.
>
where bits count the bits in a "limb", (typically 32 or 64).
No the issue is not triggered by the use of the type "int" in the code, but by
the (documented) file format "4 bytes of size information, and that many bytes
of limbs", plus the (not so well documented) fact the "4 bytes of size" also
have to store also the sign.
> From: "James Cumberbatch"
>
[...]
> Description of what is wrong: When using mpz_inp_raw to load a number
> which is at least 2^(2^34), a different value to the one which is
> written is loaded. Arithmetic works fine with these numbers and
> doesn't go wrong until larger numbers where gmp doesn't claim to work,
> only loading the number from a file goes wrong. (Or theoretically the
> error might be in mpz_out_raw, but doing a hexdump it looks like it's
>
Well, yes, I believe the bug is in the documentation, because we should
underline that the file format is only suitable for numbers which absolute
value is strictly smaller than 2^(8*(2^31-1)), and in mpz_out_raw, that should
rise an error (I mean return 0) if number can not be represented by the file
format.
Maybe we should at least correct mpz_out_raw, to return 0 when the number is
too large. I attach a possible patch.
Then, we might need a new in/out couple of functions with a larger file format.
Ĝis,mb
diff -r 1a2ad0e32507 mpz/out_raw.c
--- a/mpz/out_raw.c Mon Feb 03 17:52:54 2025 +0100
+++ b/mpz/out_raw.c Sat Mar 01 13:45:44 2025 +0100
@@ -68,7 +68,27 @@
xsize = SIZ(x);
abs_xsize = ABS (xsize);
+#if GMP_NUMB_BITS % 8 == 0
+ if (UNLIKELY (abs_xsize >= 0x80000000u / (GMP_NUMB_BITS >> 3)))
+ {
+ if (abs_xsize > 0x80000000u / (GMP_NUMB_BITS >> 3))
+ return 0;
+ /* else == 0x80000000u ... */
+ if (xsize > 0)
+ {
+ xlimb = PTR(x)[abs_xsize - 1];
+ count_leading_zeros (zeros, xlimb);
+ if (zeros < 8)
+ return 0;
+ }
+ }
+ bytes = abs_xsize * (GMP_NUMB_BITS >> 3);
+#else
+ /* FIXME: check for possible overflows */
+ if (UNLIKELY ((((abs_xsize - 1) * GMP_NUMB_BITS) / 8) >= 0x7FFFFFFF))
+ return 0;
bytes = (abs_xsize * GMP_NUMB_BITS + 7) / 8;
+#endif
tsize = ROUND_UP_MULTIPLE ((unsigned) 4, GMP_LIMB_BYTES) + bytes;
tp = __GMP_ALLOCATE_FUNC_TYPE (tsize, char);
@@ -147,6 +167,13 @@
}
}
+#if GMP_NUMB_BITS % 8 == 0
+ ASSERT (bytes >= 0 && bytes - (xsize < 0) <= 0x7FFFFFFF);
+#else
+ if (bytes < 0 || bytes - (xsize < 0) > 0x7FFFFFFF)
+ ssize = 0;
+ else
+#endif
/* total bytes to be written */
ssize = 4 + bytes;
_______________________________________________
gmp-bugs mailing list
[email protected]
https://gmplib.org/mailman/listinfo/gmp-bugs