Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: numpy.format_float_positional causes Segmentaion Fault when accepting a large pad_left #28068

Open
EgodPrime opened this issue Dec 27, 2024 · 2 comments

Comments

@EgodPrime
Copy link

EgodPrime commented Dec 27, 2024

Describe the issue:

I was working on plfuzz, an automatic Python library testing tool, and the tool found that if we pass a large pad_left to numpy.format_float_positional, NumPy crashes with Segmentation Fault.

The documentation says:

pad_left: non-negative integer, optional
Pad the left side of the string with whitespace until at least that many characters are to the left of the decimal point.

It's seams that a large pad_left meets the requirement of "non-negative integer", but the numpy.format_float_positional crashes.
I think this is not a serious bug, but it might be a good idea to fix it so that it is more user-friendly in the event of a user error.

Reproduce the code example:

args= [1.0471, 2, True, True, "k", 2048, int(1e5), 0, 0]
import numpy as np
np.format_float_positional(*args)

Error message:

(py313) root@a475b702ecc0:~/plfuzz# gdb python
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.2) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from python...
(gdb) set args bugs/bug5_pendding.py 
(gdb) r
Starting program: /root/miniconda3/envs/py313/bin/python bugs/bug5_pendding.py 
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7f9250fff640 (LWP 98733)]
[New Thread 0x7f92507fe640 (LWP 98734)]
[New Thread 0x7f924fffd640 (LWP 98735)]
[New Thread 0x7f924f7fc640 (LWP 98736)]
[New Thread 0x7f924effb640 (LWP 98737)]
[New Thread 0x7f924e7fa640 (LWP 98738)]
[New Thread 0x7f924dff9640 (LWP 98739)]
[New Thread 0x7f924d7f8640 (LWP 98740)]
[New Thread 0x7f924cff7640 (LWP 98741)]
[New Thread 0x7f924c7f6640 (LWP 98742)]
[New Thread 0x7f924bff5640 (LWP 98743)]
[New Thread 0x7f924b7f4640 (LWP 98744)]
[New Thread 0x7f924aff3640 (LWP 98745)]
[New Thread 0x7f924a7f2640 (LWP 98746)]
[New Thread 0x7f9249ff1640 (LWP 98747)]
[New Thread 0x7f92497f0640 (LWP 98748)]
[New Thread 0x7f9248fef640 (LWP 98749)]
[New Thread 0x7f92487ee640 (LWP 98750)]
[New Thread 0x7f9247fed640 (LWP 98751)]
[New Thread 0x7f92477ec640 (LWP 98752)]
[New Thread 0x7f9246feb640 (LWP 98753)]
[New Thread 0x7f92467ea640 (LWP 98754)]
[New Thread 0x7f9245fe9640 (LWP 98755)]
[New Thread 0x7f92457e8640 (LWP 98756)]
[New Thread 0x7f9244fe7640 (LWP 98757)]
[New Thread 0x7f92447e6640 (LWP 98758)]
[New Thread 0x7f9243fe5640 (LWP 98759)]
[New Thread 0x7f92437e4640 (LWP 98760)]
[New Thread 0x7f9242fe3640 (LWP 98761)]
[New Thread 0x7f92427e2640 (LWP 98762)]
[New Thread 0x7f9241fe1640 (LWP 98763)]
[New Thread 0x7f92417e0640 (LWP 98764)]
[New Thread 0x7f9240fdf640 (LWP 98765)]
[New Thread 0x7f92407de640 (LWP 98766)]
[New Thread 0x7f923ffdd640 (LWP 98767)]
[New Thread 0x7f923f7dc640 (LWP 98768)]
[New Thread 0x7f923efdb640 (LWP 98769)]
[New Thread 0x7f923e7da640 (LWP 98770)]
[New Thread 0x7f923dfd9640 (LWP 98771)]
[New Thread 0x7f923d7d8640 (LWP 98772)]
[New Thread 0x7f923cfd7640 (LWP 98773)]
[New Thread 0x7f923c7d6640 (LWP 98774)]
[New Thread 0x7f923bfd5640 (LWP 98775)]
[New Thread 0x7f923b7d4640 (LWP 98776)]
[New Thread 0x7f923afd3640 (LWP 98777)]
[New Thread 0x7f923a7d2640 (LWP 98778)]
[New Thread 0x7f9239fd1640 (LWP 98779)]
[New Thread 0x7f92397d0640 (LWP 98780)]
[New Thread 0x7f9238fcf640 (LWP 98781)]
[New Thread 0x7f92387ce640 (LWP 98782)]
[New Thread 0x7f9237fcd640 (LWP 98783)]
[New Thread 0x7f92377cc640 (LWP 98784)]
[New Thread 0x7f9236fcb640 (LWP 98785)]
[New Thread 0x7f92367ca640 (LWP 98786)]
[New Thread 0x7f9235fc9640 (LWP 98787)]
[New Thread 0x7f92357c8640 (LWP 98788)]
[New Thread 0x7f9234fc7640 (LWP 98789)]
[New Thread 0x7f92347c6640 (LWP 98790)]
[New Thread 0x7f9233fc5640 (LWP 98791)]
[New Thread 0x7f92337c4640 (LWP 98792)]
[New Thread 0x7f9232fc3640 (LWP 98793)]
[New Thread 0x7f92327c2640 (LWP 98794)]
[New Thread 0x7f9231fc1640 (LWP 98795)]
before call

Thread 1 "python" received signal SIGSEGV, Segmentation fault.
__memset_evex_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:250
250     ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S: No such file or directory.
(gdb) bt
#0  __memset_evex_unaligned_erms () at ../sysdeps/x86_64/multiarch/memset-vec-unaligned-erms.S:250
#1  0x00007f92d32e2090 in Format_floatbits.constprop.0.isra.0 () from /root/miniconda3/envs/py313/lib/python3.13/site-packages/numpy/_core/_multiarray_umath.cpython-313-x86_64-linux-gnu.so
#2  0x00007f92d32e5d42 in Dragon4_Positional () from /root/miniconda3/envs/py313/lib/python3.13/site-packages/numpy/_core/_multiarray_umath.cpython-313-x86_64-linux-gnu.so
#3  0x00007f92d331020a in dragon4_positional () from /root/miniconda3/envs/py313/lib/python3.13/site-packages/numpy/_core/_multiarray_umath.cpython-313-x86_64-linux-gnu.so
#4  0x0000000000563395 in cfunction_vectorcall_FASTCALL_KEYWORDS (func=0x7f92d3b57010, args=0x7f92d4200120, nargsf=<optimized out>, kwnames=0x7f92d199b0d0) at /usr/local/src/conda/python-3.13.0/Include/cpython/methodobject.h:50
#5  0x0000000000537aa1 in _PyObject_VectorcallTstate (kwnames=0x7f92d199b0d0, nargsf=9223372036854775809, args=0x7f92d4200120, callable=0x7f92d3b57010, tstate=0x8eac80 <_PyRuntime+282976>) at /usr/local/src/conda/python-3.13.0/Include/internal/pycore_call.h:168
#6  PyObject_Vectorcall (callable=0x7f92d3b57010, args=0x7f92d4200120, nargsf=9223372036854775809, kwnames=0x7f92d199b0d0) at /usr/local/src/conda/python-3.13.0/Objects/call.c:327
#7  0x000000000055292b in _PyEval_EvalFrameDefault (tstate=<optimized out>, frame=<optimized out>, throwflag=<optimized out>) at /usr/local/src/conda/python-3.13.0/Python/generated_cases.c.h:1502
#8  0x000000000060902e in PyEval_EvalCode (co=<optimized out>, globals=0x7f92d3c4bac0, locals=<optimized out>) at /usr/local/src/conda/python-3.13.0/Python/ceval.c:596
#9  0x000000000062eedd in run_eval_code_obj (tstate=0x8eac80 <_PyRuntime+282976>, co=0x7f92d3de6af0, globals=0x7f92d3c4bac0, locals=0x7f92d3c4bac0) at /usr/local/src/conda/python-3.13.0/Python/pythonrun.c:1323
#10 0x0000000000629d9d in run_mod (mod=<optimized out>, filename=<optimized out>, globals=0x7f92d3c4bac0, locals=0x7f92d3c4bac0, flags=<optimized out>, arena=<optimized out>, interactive_src=0x0, generate_new_source=0) at /usr/local/src/conda/python-3.13.0/Python/pythonrun.c:1408
#11 0x0000000000648890 in pyrun_file (fp=0x20ce2e0, filename=0x7f92d3ca2100, start=<optimized out>, globals=0x7f92d3c4bac0, locals=0x7f92d3c4bac0, closeit=1, flags=0x7fff78fa0d48) at /usr/local/src/conda/python-3.13.0/Python/pythonrun.c:1241
#12 0x00000000006473fb in _PyRun_SimpleFileObject (fp=0x20ce2e0, filename=0x7f92d3ca2100, closeit=1, flags=0x7fff78fa0d48) at /usr/local/src/conda/python-3.13.0/Python/pythonrun.c:490
#13 0x000000000064711b in _PyRun_AnyFileObject (fp=0x20ce2e0, filename=0x7f92d3ca2100, closeit=1, flags=0x7fff78fa0d48) at /usr/local/src/conda/python-3.13.0/Python/pythonrun.c:77
#14 0x0000000000640b67 in pymain_run_file_obj (skip_source_first_line=0, filename=0x7f92d3ca2100, program_name=0x7f92d3cb8080) at /usr/local/src/conda/python-3.13.0/Modules/main.c:409
#15 pymain_run_file (config=0x8bd378 <_PyRuntime+96344>) at /usr/local/src/conda/python-3.13.0/Modules/main.c:428
#16 pymain_run_python (exitcode=0x7fff78fa0d3c) at /usr/local/src/conda/python-3.13.0/Modules/main.c:696
#17 Py_RunMain () at /usr/local/src/conda/python-3.13.0/Modules/main.c:775
#18 0x00000000005f9509 in Py_BytesMain (argc=<optimized out>, argv=<optimized out>) at /usr/local/src/conda/python-3.13.0/Modules/main.c:829
#19 0x00007f92d3f0ad90 in __libc_start_call_main (main=main@entry=0x5f9440 <main>, argc=argc@entry=2, argv=argv@entry=0x7fff78fa0f98) at ../sysdeps/nptl/libc_start_call_main.h:58
#20 0x00007f92d3f0ae40 in __libc_start_main_impl (main=0x5f9440 <main>, argc=2, argv=0x7fff78fa0f98, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff78fa0f88) at ../csu/libc-start.c:392
#21 0x00000000005f885d in _start ()
(gdb)

Python and NumPy Versions:

2.2.1
3.13.0 | packaged by Anaconda, Inc. | (main, Oct 7 2024, 21:29:38) [GCC 11.2.0]

Runtime Environment:

[{'numpy_version': '2.2.1',
'python': '3.13.0 | packaged by Anaconda, Inc. | (main, Oct 7 2024, '
'21:29:38) [GCC 11.2.0]',
'uname': uname_result(system='Linux', node='a475b702ecc0', release='5.4.0-150-generic', version='#167~18.04.1-Ubuntu SMP Wed May 24 00:51:42 UTC 2023', machine='x86_64')},
{'simd_extensions': {'baseline': ['SSE', 'SSE2', 'SSE3'],
'found': ['SSSE3',
'SSE41',
'POPCNT',
'SSE42',
'AVX',
'F16C',
'FMA3',
'AVX2',
'AVX512F',
'AVX512CD',
'AVX512_SKX',
'AVX512_CLX'],
'not_found': ['AVX512_KNL',
'AVX512_KNM',
'AVX512_CNL',
'AVX512_ICL']}},
{'architecture': 'SkylakeX',
'filepath': '/root/miniconda3/envs/py313/lib/python3.13/site-packages/numpy.libs/libscipy_openblas64_-6bb31eeb.so',
'internal_api': 'openblas',
'num_threads': 64,
'prefix': 'libscipy_openblas',
'threading_layer': 'pthreads',
'user_api': 'blas',
'version': '0.3.28'}]

Context for the issue:

No response

@eendebakpt
Copy link
Contributor

@EgodPrime Thanks for reporting this, I can confirm the issue with np.format_float_positional(x=1.047, precision=2, pad_left=int(1e5))

The crash might be a buffer overflow caused here:

* Use a very large string buffer in case anyone tries to output a large number.
* 16384 should be enough to exactly print the integer part of any float128,
* which goes up to about 10^4932. The Dragon4_scratch struct provides a string
* buffer of this size.

@seberg
Copy link
Member

seberg commented Dec 30, 2024

Thanks for opening the issue! Ping @ahaldane maybe you have time to look into it. It is pretty easy to add a hot-fix for this, but it seems to me what we really need is a slightly more invasive refactor to add an error return to this (and all possible similar) paths.

I.e. we shouldn't just avoid failing, we should ensure the return is a proper Python error (or success, but I don't think that is worth the trouble).

@seberg seberg added this to the 2.2.2 release milestone Dec 30, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants