From 4dad3e0dbd92e3571948646f17df90328c236eeb Mon Sep 17 00:00:00 2001 From: "Jeong, YunWon" Date: Mon, 9 Feb 2026 01:06:03 +0900 Subject: [PATCH] Replace unsafe pointer cast with AtomicPtr in PyCode Add `source_path: AtomicPtr` field to `PyCode` for interior mutability, replacing the UB-inducing `#[allow(invalid_reference_casting)]` + `write_volatile` pattern in `update_code_filenames`. Use atomic load/store instead of a mutex since the operation is a simple pointer swap on a 'static reference. Update all read sites to use `source_path()` accessor. --- crates/vm/src/builtins/code.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/crates/vm/src/builtins/code.rs b/crates/vm/src/builtins/code.rs index bf6cf7071cc..790f3fd8695 100644 --- a/crates/vm/src/builtins/code.rs +++ b/crates/vm/src/builtins/code.rs @@ -12,10 +12,13 @@ use crate::{ types::{Constructor, Representable}, }; use alloc::fmt; -use core::{borrow::Borrow, ops::Deref}; +use core::{ + borrow::Borrow, + ops::Deref, + sync::atomic::{AtomicPtr, Ordering}, +}; use malachite_bigint::BigInt; use num_traits::Zero; -use rustpython_common::lock::PyMutex; use rustpython_compiler_core::{OneIndexed, bytecode::CodeUnits, bytecode::PyCodeLocationInfoKind}; /// State for iterating through code address ranges @@ -324,7 +327,7 @@ impl> IntoCodeObject for frozen::FrozenCodeObject { #[pyclass(module = false, name = "code")] pub struct PyCode { pub code: CodeObject, - source_path: PyMutex<&'static PyStrInterned>, + source_path: AtomicPtr, } impl Deref for PyCode { @@ -336,19 +339,23 @@ impl Deref for PyCode { impl PyCode { pub fn new(code: CodeObject) -> Self { - let sp = code.source_path; + let sp = code.source_path as *const PyStrInterned as *mut PyStrInterned; Self { code, - source_path: PyMutex::new(sp), + source_path: AtomicPtr::new(sp), } } pub fn source_path(&self) -> &'static PyStrInterned { - *self.source_path.lock() + // SAFETY: always points to a valid &'static PyStrInterned (interned strings are never deallocated) + unsafe { &*self.source_path.load(Ordering::Relaxed) } } pub fn set_source_path(&self, new: &'static PyStrInterned) { - *self.source_path.lock() = new; + self.source_path.store( + new as *const PyStrInterned as *mut PyStrInterned, + Ordering::Relaxed, + ); } pub fn from_pyc_path(path: &std::path::Path, vm: &VirtualMachine) -> PyResult> { let name = match path.file_stem() {