Skip to content

avoid crash and print better error message when gmp calls abort() #34492

Open
@DaveWitteMorris

Description

gmp sometimes calls abort(). (For example,this StackOverflow post says "whenever you try to create or calculate a number with more than 231 - 1 limbs (or machine words), GMP will abort.") This can crash sage or result in cryptic error messages.

Unfortunately, it seems that gmp does not provide a good way to trap these errors to provide helpful OverFlow error messages. (See the discussions here and here.) So this may need an upstream fix. Jeroen Demeyer suggested an approach that could fix this in 2017 on the gmp-discuss mailing list, but it seems that nothing came of it.

Even if we cannot improve the error messages, can we eliminate the crashes by using sig_on() / sig_off()?

This ticket came from a sage-devel discussion that includes the following two examples.

This crashes sage:

sage: def binnk3u(n,k):  return (n/k)**(k))
sage: n1=(2*10**3)
sage: d0=29004853178239
sage: n0=SR(log(n1))
sage: tt=binnk3u(n0+d0-1,(d0))
gmp: overflow in mpz type
------------------------------------------------------------------------
(no backtrace available)
------------------------------------------------------------------------
Unhandled SIGABRT: An abort() occurred.
This probably occurred because a *compiled* module has a bug
in it and is not properly wrapped with sig_on(), sig_off().
Python will now terminate.
------------------------------------------------------------------------
~/development/sage94/src/bin/sage-python: line 2: 55217 Abort trap: 6           sage -python "$@"

This should give a better error message:

sage: 2^(2^62)
gmp: overflow in mpz type
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
Input In [1], in <cell line: 1>()
----> 1 Integer(2)**(Integer(2)**Integer(62))

File ~/development/sage94/src/sage/rings/integer.pyx:2191, in sage.rings.integer.Integer.__pow__()
   2189 
   2190         if type(left) is type(right):
-> 2191             return (<Integer>left)._pow_(right)
   2192         elif isinstance(left, Element):
   2193             return coercion_model.bin_op(left, right, operator.pow)

File ~/development/sage94/src/sage/rings/integer.pyx:2255, in sage.rings.integer.Integer._pow_()
   2253 
   2254         if mpz_fits_slong_p(exp):
-> 2255             return self._pow_long(mpz_get_si(exp))
   2256 
   2257         # Raising to an exponent which doesn't fit in a long overflows

File ~/development/sage94/src/sage/rings/integer.pyx:2287, in sage.rings.integer.Integer._pow_long()
   2285 if n > 0:
   2286     x = PY_NEW(Integer)
-> 2287     sig_on()
   2288     mpz_pow_ui(x.value, self.value, n)
   2289     sig_off()

RuntimeError: Aborted

The message "gmp: overflow in mpz type" is printed to stderr, so some users might not see it, which would make the error messages even more cryptic.

CC: @slel @zimmermann6

Component: basic arithmetic

Keywords: crash, gmp

Issue created by migration from https://trac.sagemath.org/ticket/34492

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions