Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
2f49286
Use memcpy for patching values instead of direct assignment
ashm-dev Sep 23, 2025
f6765ba
Add news entry for JIT unaligned store fix in patch_* functions
ashm-dev Sep 23, 2025
b036772
Merge branch 'main' into gh-139269
ashm-dev Sep 23, 2025
c45d0cc
Remove unused local variables from patch functions
ashm-dev Sep 23, 2025
cf3c01b
Merge remote-tracking branch 'upstream/main' into gh-139269
ashm-dev Sep 23, 2025
827aa7e
Merge branch 'main' into gh-139269
ashm-dev Sep 24, 2025
684ff40
Fix UB in JIT patch_* functions with unaligned store
ashm-dev Sep 24, 2025
2c1339b
Merge remote-tracking branch 'upstream/main' into gh-139269
ashm-dev Sep 24, 2025
b5a8686
Update Misc/NEWS.d/next/Core_and_Builtins/2025-09-23-21-01-12.gh-issu…
ashm-dev Sep 24, 2025
d266ac0
Merge remote-tracking branch 'upstream/main' into gh-139269
ashm-dev Sep 24, 2025
f075c91
Merge branch 'main' into gh-139269
ashm-dev Sep 28, 2025
d19cf62
Use memcpy in set_bits to avoid alignment issues
ashm-dev Sep 28, 2025
c2cf365
Merge remote-tracking branch 'upstream/main' into gh-139269
ashm-dev Sep 28, 2025
c36c2b7
Merge branch 'main' into gh-139269
ashm-dev Sep 29, 2025
1e35b61
Track global and builtins dependencies for LOAD_GLOBAL
ashm-dev Sep 29, 2025
3f327a5
Merge branch 'main' into gh-139269
ashm-dev Sep 29, 2025
39bcc4c
Remove comments marking proposed fix in LOAD_GLOBAL case
ashm-dev Sep 29, 2025
5e6670e
Merge remote-tracking branch 'upstream/main' into gh-139269
ashm-dev Oct 8, 2025
44e9cf7
remove LOAD_GLOBAL
ashm-dev Oct 8, 2025
3ddbcf2
Merge remote-tracking branch 'upstream/main' into gh-139270
ashm-dev Oct 9, 2025
71ea00a
Merge remote-tracking branch 'upstream/main' into gh-139269
ashm-dev Oct 10, 2025
3b819af
Merge remote-tracking branch 'upstream/main' into gh-139271
ashm-dev Oct 10, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix undefined behavior when using unaligned store in JIT's ``patch_*`` functions.
30 changes: 19 additions & 11 deletions Python/jit.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -202,30 +208,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 @@ -393,7 +398,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))
{
Expand Down
Loading