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

Reply via email to