Skip to content

Commit 30a38ae

Browse files
committed
Take &mut ZendObject from cache instead of casting &T to &mut T
Rust deny-by-default lint flags the &T -> &mut T cast as UB even when the borrow is unused. Make the cache lookup borrow_mut up front and hand zval_from_object_addref a real &mut reference into the boxed entry. Same semantics, no UB lint.
1 parent 50189eb commit 30a38ae

1 file changed

Lines changed: 15 additions & 13 deletions

File tree

  • packages/php-ext-wp-mysql-parser/src

packages/php-ext-wp-mysql-parser/src/lib.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1229,16 +1229,14 @@ fn native_ast(native_ast: &Zval) -> PhpResult<&WpMySqlNativeAst> {
12291229
/// zval owns one strong reference, so we have to addref before publishing
12301230
/// the pointer; otherwise the object would be freed twice (once when this
12311231
/// zval drops, once when the cache drops).
1232-
fn zval_from_object_addref(obj: &ZendObject) -> Zval {
1233-
let ptr = obj as *const ZendObject as *mut ZendObject;
1232+
fn zval_from_object_addref(obj: &mut ZendObject) -> Zval {
1233+
// PHP convention: an object zval owns one strong reference, so bump
1234+
// the embedded zend_refcounted_h refcount before publishing the
1235+
// pointer; otherwise the object would be freed twice (once when this
1236+
// zval drops, once when the cache drops).
1237+
obj.gc.refcount += 1;
12341238
let mut zv = Zval::new();
1235-
unsafe {
1236-
// zend_object embeds a zend_refcounted_h whose first field is the
1237-
// 32-bit refcount; bump it to claim our share before exposing the
1238-
// pointer to PHP.
1239-
(*ptr).gc.refcount += 1;
1240-
zv.set_object(&mut *ptr);
1241-
}
1239+
zv.set_object(obj);
12421240
zv
12431241
}
12441242

@@ -1267,9 +1265,11 @@ impl WpMySqlNativeAst {
12671265
index: usize,
12681266
classes: &PhpClasses,
12691267
) -> PhpResult<Zval> {
1268+
let mut cache = self.node_cache.borrow_mut();
1269+
12701270
// Cache hit: skip allocation entirely and return a Zval pointing
12711271
// at the cached wrapper with refcount bumped.
1272-
if let Some(boxed) = self.node_cache.borrow().get(&index) {
1272+
if let Some(boxed) = cache.get_mut(&index) {
12731273
return Ok(zval_from_object_addref(boxed));
12741274
}
12751275

@@ -1311,9 +1311,11 @@ impl WpMySqlNativeAst {
13111311
idx_i64,
13121312
)?;
13131313

1314-
let returned = zval_from_object_addref(&object);
1315-
self.node_cache.borrow_mut().insert(index, object);
1316-
Ok(returned)
1314+
cache.insert(index, object);
1315+
let stored = cache
1316+
.get_mut(&index)
1317+
.expect("just-inserted node missing from cache");
1318+
Ok(zval_from_object_addref(stored))
13171319
}
13181320
}
13191321

0 commit comments

Comments
 (0)