Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions Include/internal/pycore_jit.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ extern "C" {

typedef _Py_CODEUNIT *(*jit_func)(_PyInterpreterFrame *frame, _PyStackRef *stack_pointer, PyThreadState *tstate);

// JIT code has no function type metadata for UBSan to check.
static inline _Py_CODEUNIT* _Py_NO_SANITIZE_UNDEFINED
_PyJIT_Entry(jit_func jitted, _PyInterpreterFrame *frame,
_PyStackRef *stack_pointer, PyThreadState *tstate)
{
return jitted(frame, stack_pointer, tstate);
Comment thread
ashm-dev marked this conversation as resolved.
Resolved
}

int _PyJIT_Compile(_PyExecutorObject *executor, const _PyUOpInstruction *trace, size_t length);
void _PyJIT_Free(_PyExecutorObject *executor);

Expand Down
15 changes: 15 additions & 0 deletions Lib/test/test_sys.py
Original file line number Diff line number Diff line change
Expand Up @@ -2423,6 +2423,21 @@ def test_jit_is_enabled(self):
assert_python_ok("-c", script.format(enabled=False), PYTHON_JIT="0")
assert_python_ok("-c", script.format(enabled=available), PYTHON_JIT="1")

@unittest.skipUnless(sys._jit.is_available(), "requires JIT")
def test_jit_compile_regex(self):
script = textwrap.dedent(r"""
import re

for _ in range(2):
re.purge()
pattern = re.compile(r"[\x00-\uffff]")
assert pattern.fullmatch("\x00") is not None
assert pattern.fullmatch("\uffff") is not None
assert pattern.fullmatch("\U00010000") is None
""")
_, _, err = assert_python_ok("-c", script, PYTHON_JIT="1")
self.assertEqual(err, b"")

def test_jit_is_active(self):
available = sys._jit.is_available()
script = textwrap.dedent(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix crashes when entering JIT-compiled code with UndefinedBehaviorSanitizer
Comment thread
ashm-dev marked this conversation as resolved.
Resolved
and unaligned memory accesses when patching JIT code.
Patch by Shamil Abdulaev.
2 changes: 1 addition & 1 deletion Python/ceval_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ do { \
jit_func jitted = _executor->jit_code; \
/* Keep the shim frame alive via the executor: */ \
Py_INCREF(_executor); \
next_instr = jitted(frame, stack_pointer, tstate); \
next_instr = _PyJIT_Entry(jitted, frame, stack_pointer, tstate); \
Py_DECREF(_executor); \
frame = tstate->current_frame; \
stack_pointer = _PyFrame_GetStackPointer(frame); \
Expand Down
15 changes: 8 additions & 7 deletions Python/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -202,30 +202,29 @@ set_bits(uint32_t *loc, uint8_t loc_start, uint64_t value, uint8_t value_start,
void
patch_32(unsigned char *location, uint64_t value)
{
uint32_t *loc32 = (uint32_t *)location;
// Check that we're not out of range of 32 unsigned bits:
assert(value < (1ULL << 32));
*loc32 = (uint32_t)value;
uint32_t final_value = (uint32_t)value;
memcpy(location, &final_value, sizeof(final_value));
}

// 32-bit relative address.
void
patch_32r(unsigned char *location, uint64_t value)
{
uint32_t *loc32 = (uint32_t *)location;
value -= (uintptr_t)location;
// Check that we're not out of range of 32 signed bits:
assert((int64_t)value >= -(1LL << 31));
assert((int64_t)value < (1LL << 31));
*loc32 = (uint32_t)value;
uint32_t final_value = (uint32_t)value;
memcpy(location, &final_value, sizeof(final_value));
}

// 64-bit absolute address.
void
patch_64(unsigned char *location, uint64_t value)
{
uint64_t *loc64 = (uint64_t *)location;
*loc64 = value;
memcpy(location, &value, sizeof(value));
}

// 12-bit low part of an absolute address. Pairs nicely with patch_aarch64_21r
Expand Down Expand Up @@ -329,7 +328,9 @@ patch_x86_64_32rx(unsigned char *location, uint64_t value)
{
uint8_t *loc8 = (uint8_t *)location;
// Try to relax the GOT load into an immediate value:
uint64_t relaxed = *(uint64_t *)(value + 4) - 4;
uint64_t relaxed;
memcpy(&relaxed, (void *)(value + 4), sizeof(relaxed));
relaxed -= 4;
if ((int64_t)relaxed - (int64_t)location >= -(1LL << 31) &&
(int64_t)relaxed - (int64_t)location + 1 < (1LL << 31))
{
Expand Down
Loading