-
-
Notifications
You must be signed in to change notification settings - Fork 33.1k
Closed
Labels
3.14bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-JITtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
Crash report
**
is weird in that the type of the result depends on the values of the inputs. The logic for int
/float
power is:
def type_of_pow(lhs: float, rhs: float) -> type[complex]:
if isinstance(lhs, int) and isinstance(rhs, int) and rhs >= 0:
return int
if lhs < 0 and not rhs.is_integer():
return complex
return float
However, our optimizer wrongly assumes:
def type_of_pow(lhs: float, rhs: float) -> type[float]:
if isinstance(lhs, int) and isinstance(rhs, int):
return int
return float
This means that tons of different poorly-chosen values can cause JIT code to crash:
import _testinternalcapi
import itertools
def f(a, b):
for _ in range(_testinternalcapi.TIER2_THRESHOLD):
a + b # Remove guards...
a ** b + a # ...BOOM!
for la, ra, lb, rb in itertools.product([1, -1, 1.0, -1.0, 0.5, -0.5], repeat=4):
f(la, ra)
f(lb, rb)
Normally we could just ignore the problem and produce an unknown type during abstract interpretation, but a **
containing at least one constant value is actually reasonably common (think x ** 2
, 2 ** n
, or s ** 0.5
).
We should probably teach the optimizer how to handle these properly.
Linked PRs
OTheDev
Metadata
Metadata
Assignees
Labels
3.14bugs and security fixesbugs and security fixesinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)topic-JITtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump