-
-
Notifications
You must be signed in to change notification settings - Fork 30.5k
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
Possible undefined behavior division by zero in complex's _Py_c_pow()
#113841
Comments
Why not use multiplication instead of division? |
The complex object code has been this way since it was added 28 years ago. f9fca92 😅 and may have come from @khinsen. For floating point things, it is often worth figuring out how error accumulates along the way in the computation to minimize loss. I haven't given the algorithm here any thought or looked up alternatives. My proposal is a mere edit that'd keep it the same with an added check in the middle. |
Also of note since complexobject.c was written... C99 added a |
which may be less trivial to use because visual studio support appears to be partial? https://developercommunity.visualstudio.com/t/support-for-c99-complex-numbers/1409049 |
Yes, that was me who contributed the complex object to CPython. All the algorithms were taken from C code snippets floating around in my environment - version control hadn't arrived in computational science yet! Since then, not only the C language has evolved, but also the optimization habits of C compilers. I wouldn't waste much effort figuring out why |
I think that the result should be NaN if Also, should not |
cc @mdickinson |
For me, it looks you example indeed trigger exp=0 condition for code x, y = 9j, 33j
x**y**3 # here at*b.imag is -0x1.b9036a4a06cfcp+15 The C standard says for division, that "if the value of the second operand is zero, the behavior is undefined". On another hand, with Annex F - you got ERANGE from exp() and +inf (in given example). So, you will correctly get OverflowError. The
Annex G is still optional. And e.g. M$ CRT implements complex math differently, though I'm not sure about quality of implementations. But e.g. the glibc versions of complex math functions - pass the CPython's cmath_testcases.txt.
It seems, glibc just do Same I see for generic case e.g. in the numpy. |
…7211) `x**y == 1/x**-y ` thus changing `/=` to `*=` by negating the exponent.
…ythonGH-127211) `x**y == 1/x**-y ` thus changing `/=` to `*=` by negating the exponent. (cherry picked from commit f7bb658) Co-authored-by: Sergey B Kirpichev <[email protected]>
I don't think it's a security issue (at least - very low priority, perhaps on some exotic platform), hence removing the 3.11 label. But backports should be easy. We can do this for 3.12. Not sure if it worth, however. |
Bug report
Bug description:
https://github.com/python/cpython/blob/main/Objects/complexobject.c#L150
_Py_c_pow()
contains:An oss-fuzz pycompiler fuzzer identified a problem compiling the code "
9J**33J**3
" within the optimizer folding the constant by doing the math in place. We haven't been able to reproduce this ourselves - but code inspection reveals a potential problem:C
exp(x)
can return 0 in a couple of cases. Which would lead to the /= executing an undefined division by zero operation.I believe the correct
_Py_c_pow()
code should look something like:CPython versions tested on:
CPython main branch
Operating systems tested on:
Linux
Linked PRs
The text was updated successfully, but these errors were encountered: