python-flint icon indicating copy to clipboard operation
python-flint copied to clipboard

Memory management routines of flint can crash interpreter

Open skirpichev opened this issue 1 year ago • 4 comments

Consider:

$ ulimit -v $((1024*64))
$ python
Python 3.11.9+ (heads/3.11:795f2597a4, Aug 29 2024, 14:29:51) [GCC 12.2.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import flint
>>> a = flint.fmpz(200)<<1000000000
GNU MP: Cannot reallocate memory (old_size=16 new_size=125000008)
Aborted
$ 

Unfortunately, https://flintlib.org/doc/memory.html page lacks notes like the GMP manual, "13. Custom allocation": "There’s currently no defined way for the allocation functions to recover from an error such as out of memory, they must terminate program execution."

Or this is a flint bug, not a docs issue? It seems, despite fmpz_t is a re-implemented (using low-level mpn_* functions) mpz_t - it shares same memory-management behaviour. In this case it could be possible to carefully propagate memory errors.

skirpichev avatar Nov 23 '24 09:11 skirpichev

"There’s currently no defined way for the allocation functions to recover from an error such as out of memory, they must terminate program execution."

You can try to recover from a memory error in GMP or FLINT by intercepting the abort signal, it's just risky. You'll be fine most of the time but you risk leaking memory and occasionally corrupting data.

Sage does this for FLINT so it should be possible to do the same thing in python-flint:

sage: ZZ["x"].gen() ^ 1000000000000
Exception (FLINT memory_manager). Unable to allocate memory (8).
...
RuntimeError: Aborted

fredrik-johansson avatar Nov 23 '24 10:11 fredrik-johansson

On Sat, Nov 23, 2024 at 02:06:52AM -0800, Fredrik Johansson wrote:

You can try to recover from a memory error in GMP or FLINT by intercepting the abort signal, it's just risky. You'll be fine most of the time but you risk leaking memory and occasionally corrupting data.

I'm not sure why you guess about "most of time". IMO, this is worse than plain abort() - essentially you left program (e.g. Python interpreter) in some undefined state, from which you can't recover (or save your data). Perhaps, this may work sometimes, e.g. in my or your examples: when you in one shot trying to allocate too much memory. But this looks rather an artificial case.

GMP seems to be correct here: "Getting a different fatal error action is a good use for custom allocation functions" (c). E.g. https://github.com/aleaxit/gmpy/pull/513

skirpichev avatar Nov 23 '24 10:11 skirpichev

Would flint_set_abort handle this or is that not applicable to a memory error like this?

I had been considering whether python-flint should use cysignals. There is some discussion on the sage mailing list about making cysignals work on Windows.

oscarbenjamin avatar Nov 23 '24 12:11 oscarbenjamin

Would flint_set_abort handle this

From sources it looks so. But I don't think it's a good idea.

See e.g. the mpdecimal - it's possible to propagate memory errors to the caller. Sadly, but that probably will require API changes for flint. So, perhaps, it's not an option. BTW, I'm working on a "safe" GMP wrapper, that can be an alternative to gmpy2 for mpmath or diofant.

Edit: https://github.com/diofant/python-gmp/ - here it's.

skirpichev avatar Nov 28 '24 03:11 skirpichev