Upstream patch to remove abort() that occur during memory overflow

Marco Bodrato bodrato at mail.dm.unipi.it
Sat Jun 12 13:34:59 UTC 2021


Il 2020-09-13 11:38 tg at gmplib.org ha scritto:
> Marco Bodrato <bodrato at mail.dm.unipi.it> writes:
> 
>   With ABI=64 I get:
>   16777216 ^ 768614336404564651 = 256
> 
>   With ABI=32 I get:
>   16777216 ^ 178956971 = 256
> 
>   Not a signal, nor an abort, simply an incorrect result :-)
> 
> That's undesirable.
> 
> I thought we cought overflows also in this difficult a^b case by
> (indirectly means of allocation errors).

Yet another...

$ cat provo.c
#include <stdio.h>
#include "gmp.h"

int
main ()
{
   unsigned long b, e;
   mpz_t p;
   mpz_t bz;

   mpz_init (p);
   mpz_init (bz);

   b = 24 * GMP_NUMB_BITS;
   mpz_setbit (bz, b);
   e = ~0UL / 24 + 1;
   mpz_pow_ui (p, bz, e);
   gmp_printf ("(2 ^ %lu) ^ %lu = %Zd\n", b, e, p);

   mpz_clear (bz);
   mpz_clear (p);
}

$ gcc provo.c -lgmp -o provo&& ./provo
(2 ^ 1536) ^ 768614336404564651 = 
13407807929942597099574024998205846127479365820592393377723561443721764030073546976801874298166903427690031858186486050853753882811946569946433649006084096

And here is a possible patch (for the 6.2 branch):

$ hg diff mpz
diff -r e1fd9db13b47 mpz/n_pow_ui.c
--- a/mpz/n_pow_ui.c    Tue Dec 22 23:49:51 2020 +0100
+++ b/mpz/n_pow_ui.c    Sat Jun 12 15:24:36 2021 +0200
@@ -206,11 +206,33 @@

    /* Strip low zero limbs from b. */
    rtwos_limbs = 0;
+#if 1
    for (blimb = *bp; blimb == 0; blimb = *++bp)
      {
        rtwos_limbs += e;
+      if (UNLIKELY (rtwos_limbs < e))
+       {
+         fprintf (stderr, "gmp: overflow in mpz type\n");
+         abort ();
+       }
        bsize--; ASSERT (bsize >= 1);
      }
+#else
+  blimb = *bp;
+  if (blimb == 0)
+    {
+      do
+       ++rtwos_limbs;
+      while ((blimb = *++bp) == 0);
+      bsize -= rtwos_limbs; ASSERT (bsize >= 1);
+      umul_ppmm (ovfl, rtwos_limbs, e, rtwos_limbs);
+      if (ovfl)
+       {
+         fprintf (stderr, "gmp: overflow in mpz type\n");
+         abort ();
+       }
+    }
+#endif
    TRACE (printf ("trailing zero rtwos_limbs=%ld\n", rtwos_limbs));

    /* Strip low zero bits from b. */

As you can see, I tried two different patches. One adds a (well 
predicted?) branch in the (on average O(1)) loop. The other uses a 
multiplication.

But we should probably consider to add a piece of code, at the beginning 
of the function, estimating the total size of the result, to avoid so 
many spurious checks...

Ĝis,
m


More information about the gmp-bugs mailing list