Repository navigation
Address slot members by byte offset #8811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9a2a58a
dcb5f39
fc4f48d
487a920
516b3e7
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6291,7 +6291,7 @@ impl ExecutingFrame<'_> { | |
|
|
||
| if type_version != 0 && owner.class().tp_version_tag.load(Acquire) == type_version { | ||
| let slot_offset = | ||
| self.code.instructions.read_cache_u32(cache_base + 3) as usize; | ||
| self.code.instructions.read_cache_u32(cache_base + 3) as i32 as isize; | ||
| if let Some(value) = owner.get_slot(slot_offset) { | ||
| self.pop_stackref(); | ||
| if oparg.is_method() { | ||
|
|
@@ -6381,7 +6381,7 @@ impl ExecutingFrame<'_> { | |
|
|
||
| if version_match { | ||
| let slot_offset = | ||
| self.code.instructions.read_cache_u16(cache_base + 3) as usize; | ||
| self.code.instructions.read_cache_u16(cache_base + 3) as i16 as isize; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win 🔎 Supported by static analysis🏁 Script executed: #!/bin/bash
set -euo pipefail
# Inspect offset construction, cache encoding, layout bounds, and slot access.
rg -n -C 4 'slot_offset|write_cache_u16\(cache_base \+ 3, offset|fn set_slot|member_count|basicsize|basic_size' \
crates/vm/src/frame.rs \
crates/vm/src/builtins/descriptor.rs \
crates/vm/src/builtins/type.rs \
crates/vm/src/object/core.rs \
crates/capi/src/descrobject.rsRepository: RustPython/RustPython Length of output: 25993 🏁 Script executed: #!/bin/bash
set -euo pipefail
printf '%s\n' '--- frame cache setup ---'
sed -n '10190,10225p;11995,12030p' crates/vm/src/frame.rs
printf '%s\n' '--- slot access ---'
sed -n '2165,2205p' crates/vm/src/object/core.rs
printf '%s\n' '--- slot offset construction and member definitions ---'
rg -n -C 5 'slot_member_offset|PyMemberDef|MemberDef|offset:|member\.offset|offset as (u|i)|write_cache_u16' \
crates/vm/src/builtins/descriptor.rs \
crates/vm/src/builtins/type.rs \
crates/vm/src/object/core.rs \
crates/capi/src \
crates/vm/src/frame.rs
printf '%s\n' '--- relevant diff ---'
git diff --unified=8 3272bee78b608f9f713143080693cb27962fc300 dcb5f39f82bcb25f3548771f3ee17c6177bb4e6d -- crates/vm/src/frame.rs | sed -n '1,220p'Repository: RustPython/RustPython Length of output: 37702 Do not specialize stores with offsets outside the signed 16-bit range.
Suggested fix && let Some(offset) = member_descr
.slot_offset()
+ .filter(|offset| i16::try_from(*offset).is_ok())
.filter(|_| !member_descr.member.readonly())🤖 Prompt for AI Agents |
||
| let owner = self.pop_value(); | ||
| let value = self.pop_value(); | ||
| owner.set_slot(slot_offset, Some(value)); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 6985
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 42010
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 42154
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 19525
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 41466
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 14778
🏁 Script executed:
Repository: RustPython/RustPython
Length of output: 28174
Reject
PY_RELATIVE_OFFSETmembers until the slot layout supports them.PyMemberDef::buildconverts a relative offset to a positive offset and usesMemberAccess::Slot. The slot accessor adds that offset toPyInnerand casts the address toPyAtomicRef<PyObject>. Member cells are allocated and initialized only in the prefix beforePyInner. Therefore, a relative member withoffset = 0can readPyInnermemory as a pointer cell, and larger offsets can access memory outside the allocation. A setter can corrupt that memory.MemberKind::Boolalso reaches this pointer-cell path.T_INTandT_CHARcodes are rejected, butT_BOOLis accepted without an object-kind check.Suggested fix
let Some(kind) = MemberKind::from_i32(self.type_code) else { return Err(vm.new_system_error(format!( "PyDescr_NewMember does not support member type code {}", self.type_code ))); }; + if self.flags & PY_RELATIVE_OFFSET != 0 { + return Err( + vm.new_system_error("PyDescr_NewMember does not support Py_RELATIVE_OFFSET") + ); + } let mut offset = self.offset; let mut flags = self.flags; - if flags & PY_RELATIVE_OFFSET != 0 { - // type creation adds tp_basicsize and clears the flag before GetOne. - offset += (rustpython_vm::object::SIZEOF_PYOBJECT_HEAD + ty.slots.basicsize) as isize; - flags &= !PY_RELATIVE_OFFSET; - }🤖 Prompt for AI Agents