This is used by Julia to raise an OutOfMemory exception rather than having the Julia process itself abort.
Others on stackoverflow, etc, have experienced similar problems with undesired aborts(), so this patch would probably be useful to a variety of users. (see: https://github.com/JuliaLang/julia/issues/8286#issuecomment-323500953) More information is available here and in the linked issues and PRs: https://github.com/JuliaLang/julia/pull/31215 Thanks,
diff --git a/gmp-h.in b/gmp-h.in --- a/gmp-h.in +++ b/gmp-h.in @@ -479,6 +479,13 @@ using std::FILE; void *(**) (void *, size_t, size_t), void (**) (void *, size_t)) __GMP_NOTHROW; +#define mp_set_alloc_overflow_function __gmp_set_alloc_overflow_function +__GMP_DECLSPEC void mp_set_alloc_overflow_function (void (*) (void)) __GMP_NOTHROW; + +#define mp_get_alloc_overflow_function __gmp_get_alloc_overflow_function +__GMP_DECLSPEC void mp_get_alloc_overflow_function (void (**) (void)) __GMP_NOTHROW; + + #define mp_bits_per_limb __gmp_bits_per_limb __GMP_DECLSPEC extern const int mp_bits_per_limb; diff --git a/gmp-impl.h b/gmp-impl.h --- a/gmp-impl.h +++ b/gmp-impl.h @@ -696,10 +696,12 @@ struct tmp_debug_entry_t { __GMP_DECLSPEC extern void * (*__gmp_allocate_func) (size_t); __GMP_DECLSPEC extern void * (*__gmp_reallocate_func) (void *, size_t, size_t); __GMP_DECLSPEC extern void (*__gmp_free_func) (void *, size_t); +__GMP_DECLSPEC extern void (*__gmp_alloc_overflow_func)(void); __GMP_DECLSPEC void *__gmp_default_allocate (size_t); __GMP_DECLSPEC void *__gmp_default_reallocate (void *, size_t, size_t); __GMP_DECLSPEC void __gmp_default_free (void *, size_t); +__GMP_DECLSPEC void __gmp_default_alloc_overflow (void); #define __GMP_ALLOCATE_FUNC_TYPE(n,type) \ ((type *) (*__gmp_allocate_func) ((n) * sizeof (type))) @@ -727,6 +729,12 @@ struct tmp_debug_entry_t { (ptr, (oldsize) * sizeof (type), (newsize) * sizeof (type)); \ } while (0) +#define __GMP_ALLOC_OVERFLOW_FUNC() \ + do { \ + (*__gmp_alloc_overflow_func) (); \ + fprintf (stderr, "unexpected return from alloc_overflow\n"); \ + abort (); \ + } while (0) /* Dummy for non-gcc, code involving it will go dead. */ #if ! defined (__GNUC__) || __GNUC__ < 2 diff --git a/memory.c b/memory.c --- a/memory.c +++ b/memory.c @@ -38,6 +38,7 @@ see https://www.gnu.org/licenses/. */ void * (*__gmp_allocate_func) (size_t) = __gmp_default_allocate; void * (*__gmp_reallocate_func) (void *, size_t, size_t) = __gmp_default_reallocate; void (*__gmp_free_func) (void *, size_t) = __gmp_default_free; +void (*__gmp_alloc_overflow_func) (void) = __gmp_default_alloc_overflow; /* Default allocation functions. In case of failure to allocate/reallocate @@ -144,3 +145,10 @@ void #endif free (blk_ptr); } + +void +__gmp_default_alloc_overflow(void) +{ + fprintf (stderr, "gmp: overflow in mpz type\n"); + abort(); +} diff --git a/mp_get_fns.c b/mp_get_fns.c --- a/mp_get_fns.c +++ b/mp_get_fns.c @@ -46,3 +46,11 @@ mp_get_memory_functions (void *(**alloc_ if (free_func != NULL) *free_func = __gmp_free_func; } + +void +mp_get_alloc_overflow_function( + void (**alloc_overflow_func) (void)) __GMP_NOTHROW +{ + if (alloc_overflow_func != NULL) + *alloc_overflow_func = __gmp_alloc_overflow_func; +} diff --git a/mp_set_fns.c b/mp_set_fns.c --- a/mp_set_fns.c +++ b/mp_set_fns.c @@ -48,3 +48,12 @@ mp_set_memory_functions (void *(*alloc_f __gmp_reallocate_func = realloc_func; __gmp_free_func = free_func; } + +void +mp_set_alloc_overflow_function( + void (*alloc_overflow_func) (void)) __GMP_NOTHROW +{ + if (alloc_overflow_func == 0) + alloc_overflow_func = __gmp_default_alloc_overflow; + __gmp_alloc_overflow_func = alloc_overflow_func; +} diff --git a/mpz/init2.c b/mpz/init2.c --- a/mpz/init2.c +++ b/mpz/init2.c @@ -45,8 +45,7 @@ mpz_init2 (mpz_ptr x, mp_bitcnt_t bits) { if (UNLIKELY (new_alloc > INT_MAX)) { - fprintf (stderr, "gmp: overflow in mpz type\n"); - abort (); + __GMP_ALLOC_OVERFLOW_FUNC (); } } diff --git a/mpz/realloc.c b/mpz/realloc.c --- a/mpz/realloc.c +++ b/mpz/realloc.c @@ -45,16 +45,14 @@ void * { if (UNLIKELY (new_alloc > ULONG_MAX / GMP_NUMB_BITS)) { - fprintf (stderr, "gmp: overflow in mpz type\n"); - abort (); + __GMP_ALLOC_OVERFLOW_FUNC (); } } else { if (UNLIKELY (new_alloc > INT_MAX)) { - fprintf (stderr, "gmp: overflow in mpz type\n"); - abort (); + __GMP_ALLOC_OVERFLOW_FUNC (); } } diff --git a/mpz/realloc2.c b/mpz/realloc2.c --- a/mpz/realloc2.c +++ b/mpz/realloc2.c @@ -45,8 +45,7 @@ mpz_realloc2 (mpz_ptr m, mp_bitcnt_t bit { if (UNLIKELY (new_alloc > INT_MAX)) { - fprintf (stderr, "gmp: overflow in mpz type\n"); - abort (); + __GMP_ALLOC_OVERFLOW_FUNC (); } } diff --git a/tests/mpz/t-pow.c b/tests/mpz/t-pow.c --- a/tests/mpz/t-pow.c +++ b/tests/mpz/t-pow.c @@ -195,6 +195,34 @@ check_random (int reps) mpz_clear (want); } +jmp_buf env; + +void +alloc_overflow_handler (void) +{ + longjmp(env, 1); +} + +void +check_overflow (void) +{ + mpz_t x; + mpz_init (x); + int overflow_intercepted = 0; + if (setjmp (env) == 0) { + mp_set_alloc_overflow_function (&alloc_overflow_handler); + mpz_ui_pow_ui (x, 3, 7625597484987LL); + } else { + ++overflow_intercepted; + } + if (overflow_intercepted != 1) { + printf ("overflow not intercepted\n"); + abort (); + } + mpz_clear (x); +} + + int main (int argc, char **argv) { @@ -212,6 +240,7 @@ main (int argc, char **argv) check_various (); check_random (reps); + check_overflow (); tests_end (); exit (0);
_______________________________________________ gmp-bugs mailing list gmp-bugs@gmplib.org https://gmplib.org/mailman/listinfo/gmp-bugs