https://github.com/python/cpython/commit/bedaea05987738c4c6b958d19cec9621bec09f07
commit: bedaea05987738c4c6b958d19cec9621bec09f07
branch: main
author: Shamil <[email protected]>
committer: Fidget-Spinner <[email protected]>
date: 2025-10-19T00:20:04+01:00
summary:

gh-139269: Fix unaligned memory access in JIT code patching functions 
(GH-139271)

* Use memcpy for patching values instead of direct assignment


Co-authored-by: Bénédikt Tran <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2025-09-23-21-01-12.gh-issue-139269.1rIaxy.rst
M Python/jit.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2025-09-23-21-01-12.gh-issue-139269.1rIaxy.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-23-21-01-12.gh-issue-139269.1rIaxy.rst
new file mode 100644
index 00000000000000..e36be529d2a5b9
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2025-09-23-21-01-12.gh-issue-139269.1rIaxy.rst
@@ -0,0 +1 @@
+Fix undefined behavior when using unaligned store in JIT's ``patch_*`` 
functions.
diff --git a/Python/jit.c b/Python/jit.c
index ebd0d90385e002..c3f3d686013fe4 100644
--- a/Python/jit.c
+++ b/Python/jit.c
@@ -157,12 +157,18 @@ set_bits(uint32_t *loc, uint8_t loc_start, uint64_t 
value, uint8_t value_start,
          uint8_t width)
 {
     assert(loc_start + width <= 32);
+    uint32_t temp_val;
+    // Use memcpy to safely read the value, avoiding potential alignment
+    // issues and strict aliasing violations.
+    memcpy(&temp_val, loc, sizeof(temp_val));
     // Clear the bits we're about to patch:
-    *loc &= ~(((1ULL << width) - 1) << loc_start);
-    assert(get_bits(*loc, loc_start, width) == 0);
+    temp_val &= ~(((1ULL << width) - 1) << loc_start);
+    assert(get_bits(temp_val, loc_start, width) == 0);
     // Patch the bits:
-    *loc |= get_bits(value, value_start, width) << loc_start;
-    assert(get_bits(*loc, loc_start, width) == get_bits(value, value_start, 
width));
+    temp_val |= get_bits(value, value_start, width) << loc_start;
+    assert(get_bits(temp_val, loc_start, width) == get_bits(value, 
value_start, width));
+    // Safely write the modified value back to memory.
+    memcpy(loc, &temp_val, sizeof(temp_val));
 }
 
 // See 
https://developer.arm.com/documentation/ddi0602/2023-09/Base-Instructions
@@ -204,30 +210,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
@@ -410,7 +415,10 @@ 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))
     {

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to