Ciao John! È un piacere vederti da queste parti!

Il 2021-03-22 09:55 abb...@dima.unige.it ha scritto:
Does GMP offer a way to return/throw rather than simply aborting upon overflow?

No, it doesn't. Yet.

I could not see anything relevant in the documentation.

The theme emerges every now and then on the list.

And the problem is that it seems difficult, for the caller, to handle possible memory leaks, and coherence of the internal state to do anything better than to abort...

But I think that lazy allocation, we have it from GMP-6.2.0, can help.

I think it should be possible to write a function, using mpz_t or mpq_t only, that:

1) has a clear distinction between readable-only and writable-only parameters. 2) frees (mpz_clear) all the writable variables, and re-inits them (mpz_init, which is lazy now, and does not allocate anything). 3) sets (mp_set_memory_functions) memory functions that will keep track of any block allocated by GMP functions
4) sets the callback on error...
5) does the heavy work
6) resets callback and memory functions and returns "done".

If during the step 5 an error occours:
6) frees any memory block allocated after step 3;
7) re-inits all the writable variables (mpz_init, to set everything to a coherent state)
8) resets callback and memory functions and returns "fail".

Anyway, for internal coherence, I think that we should at least check that all the functions in the library that might "abort" do this using an "exception". For this, I propose the attached patch.

Then, we might think if we want to let the user install a hook on the __gmp_exception function.

Ĝis,
m
diff -r eac10a64bc99 errno.c
--- a/errno.c	Sun Jun 06 23:29:28 2021 +0200
+++ b/errno.c	Sat Jun 12 16:46:13 2021 +0200
@@ -70,3 +70,8 @@
 {
   __gmp_exception (GMP_ERROR_DIVISION_BY_ZERO);
 }
+void
+__gmp_overflow_in_mpz (void)
+{
+  __gmp_exception (GMP_ERROR_MPZ_OVERFLOW);
+}
diff -r eac10a64bc99 gmp-h.in
--- a/gmp-h.in	Sun Jun 06 23:29:28 2021 +0200
+++ b/gmp-h.in	Sat Jun 12 16:46:13 2021 +0200
@@ -2325,7 +2325,8 @@
   GMP_ERROR_UNSUPPORTED_ARGUMENT = 1,
   GMP_ERROR_DIVISION_BY_ZERO = 2,
   GMP_ERROR_SQRT_OF_NEGATIVE = 4,
-  GMP_ERROR_INVALID_ARGUMENT = 8
+  GMP_ERROR_INVALID_ARGUMENT = 8,
+  GMP_ERROR_MPZ_OVERFLOW = 16
 };
 
 /* Define CC and CFLAGS which were used to build this version of GMP */
diff -r eac10a64bc99 gmp-impl.h
--- a/gmp-impl.h	Sun Jun 06 23:29:28 2021 +0200
+++ b/gmp-impl.h	Sat Jun 12 16:46:13 2021 +0200
@@ -3924,10 +3924,12 @@
 __GMP_DECLSPEC void __gmp_exception (int) ATTRIBUTE_NORETURN;
 __GMP_DECLSPEC void __gmp_divide_by_zero (void) ATTRIBUTE_NORETURN;
 __GMP_DECLSPEC void __gmp_sqrt_of_negative (void) ATTRIBUTE_NORETURN;
+__GMP_DECLSPEC void __gmp_overflow_in_mpz (void) ATTRIBUTE_NORETURN;
 __GMP_DECLSPEC void __gmp_invalid_operation (void) ATTRIBUTE_NORETURN;
 #define GMP_ERROR(code)   __gmp_exception (code)
 #define DIVIDE_BY_ZERO    __gmp_divide_by_zero ()
 #define SQRT_OF_NEGATIVE  __gmp_sqrt_of_negative ()
+#define MPZ_OVERFLOW      __gmp_overflow_in_mpz ()
 
 #if defined _LONG_LONG_LIMB
 #define CNST_LIMB(C) ((mp_limb_t) C##LL)
diff -r eac10a64bc99 mpz/init2.c
--- a/mpz/init2.c	Sun Jun 06 23:29:28 2021 +0200
+++ b/mpz/init2.c	Sat Jun 12 16:46:13 2021 +0200
@@ -43,10 +43,7 @@
   if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */
     {
       if (UNLIKELY (new_alloc > INT_MAX))
-	{
-	  fprintf (stderr, "gmp: overflow in mpz type\n");
-	  abort ();
-	}
+	MPZ_OVERFLOW;
     }
 
   PTR(x) = __GMP_ALLOCATE_FUNC_LIMBS (new_alloc);
diff -r eac10a64bc99 mpz/realloc.c
--- a/mpz/realloc.c	Sun Jun 06 23:29:28 2021 +0200
+++ b/mpz/realloc.c	Sat Jun 12 16:46:13 2021 +0200
@@ -44,18 +44,12 @@
   if (sizeof (mp_size_t) == sizeof (int))
     {
       if (UNLIKELY (new_alloc > ULONG_MAX / GMP_NUMB_BITS))
-	{
-	  fprintf (stderr, "gmp: overflow in mpz type\n");
-	  abort ();
-	}
+	MPZ_OVERFLOW;
     }
   else
     {
       if (UNLIKELY (new_alloc > INT_MAX))
-	{
-	  fprintf (stderr, "gmp: overflow in mpz type\n");
-	  abort ();
-	}
+	MPZ_OVERFLOW;
     }
 
   if (ALLOC (m) == 0)
diff -r eac10a64bc99 mpz/realloc2.c
--- a/mpz/realloc2.c	Sun Jun 06 23:29:28 2021 +0200
+++ b/mpz/realloc2.c	Sat Jun 12 16:46:13 2021 +0200
@@ -43,10 +43,7 @@
   if (sizeof (unsigned long) > sizeof (int)) /* param vs _mp_size field */
     {
       if (UNLIKELY (new_alloc > INT_MAX))
-	{
-	  fprintf (stderr, "gmp: overflow in mpz type\n");
-	  abort ();
-	}
+	MPZ_OVERFLOW;
     }
 
   if (ALLOC (m) == 0)
_______________________________________________
gmp-devel mailing list
gmp-devel@gmplib.org
https://gmplib.org/mailman/listinfo/gmp-devel

Reply via email to