Bug report
Bug description:
Found by the CI UBSan job, e.g. this run:
Python/generated_cases.c.h:8158:17: runtime error: applying non-zero offset 44 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Python/generated_cases.c.h:8158:17
Note this requires applying #152311 which seems to change the state ever so slightly uncovering the UB. Locally I get with clang:
$ ./python -m test test_monitoring
Using random seed: 1062411673
0:00:00 load avg: 1.00 mem: 41.2 MiB Run 1 test sequentially in a single process
0:00:00 load avg: 1.00 mem: 41.2 MiB [1/1] test_monitoring
Python/generated_cases.c.h:8158:17: runtime error: applying non-zero offset 44 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Python/generated_cases.c.h:8158:17
Python/generated_cases.c.h:8050:13: runtime error: applying non-zero offset 2 to null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Python/generated_cases.c.h:8050:13
Python/generated_cases.c.h:13861:59: runtime error: applying non-zero offset to non-null pointer 0x000000000002 produced null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Python/generated_cases.c.h:13861:59
Python/generated_cases.c.h:13881:57: runtime error: applying non-zero offset to non-null pointer 0x000000000002 produced null pointer
SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior Python/generated_cases.c.h:13881:57
0:00:00 load avg: 1.00 mem: 43.0 MiB [1/1] test_monitoring passed
== Tests result: SUCCESS ==
1 test OK.
Total duration: 357 ms
Total tests: run=98
Total test files: run=1/1
Result: SUCCESS
The UB is reported, e.g. at:
|
INSTRUMENTED_JUMP(this_instr, next_instr + oparg, PY_MONITORING_EVENT_BRANCH_RIGHT); |
Which calls INSTRUMENTED_JUMP:
|
// If a trace function sets a new f_lineno and |
|
// *then* raises, we use the destination when searching |
|
// for an exception handler, displaying the traceback, and so on |
|
#define INSTRUMENTED_JUMP(src, dest, event) \ |
|
do { \ |
|
if (tstate->tracing) {\ |
|
next_instr = dest; \ |
|
} else { \ |
|
_PyFrame_SetStackPointer(frame, stack_pointer); \ |
|
next_instr = _Py_call_instrumentation_jump(this_instr, tstate, event, frame, src, dest); \ |
|
stack_pointer = _PyFrame_GetStackPointer(frame); \ |
|
if (next_instr == NULL) { \ |
|
next_instr = (dest)+1; \ |
|
JUMP_TO_LABEL(error); \ |
|
} \ |
|
} \ |
|
} while (0); |
If _Py_call_instrumentation_jump raises it returns NULL (setting next_instr). But then on the error path, we do next_instr + oparg resulting in the UB.
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response
Linked PRs
Bug report
Bug description:
Found by the CI UBSan job, e.g. this run:
Note this requires applying #152311 which seems to change the state ever so slightly uncovering the UB. Locally I get with clang:
The UB is reported, e.g. at:
cpython/Python/generated_cases.c.h
Line 8158 in b3154aa
Which calls
INSTRUMENTED_JUMP:cpython/Python/ceval_macros.h
Lines 387 to 403 in b3154aa
If
_Py_call_instrumentation_jumpraises it returns NULL (setting next_instr). But then on the error path, we donext_instr + opargresulting in the UB.CPython versions tested on:
CPython main branch
Operating systems tested on:
No response
Linked PRs
INSTRUMENTED_JUMP#152376