Skip to content

Commit 1f7ce2a

Browse files
committed
Re-enable trace zval construction with the in-place handler patch
1 parent 85081fd commit 1f7ce2a

1 file changed

Lines changed: 32 additions & 5 deletions

File tree

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

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

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,16 +1265,43 @@ static mut WP_MYSQL_NATIVE_AST_HANDLERS_PATCHED: bool = false;
12651265
/// or change refcounts, so we deliberately do *not* call `set_object`
12661266
/// (which addrefs); we set the union directly.
12671267
unsafe extern "C" fn ast_get_gc(
1268-
_object: *mut zend_object,
1268+
object: *mut zend_object,
12691269
table: *mut *mut zval,
12701270
n: *mut std::os::raw::c_int,
12711271
) -> *mut HashTable {
1272-
// DEBUG: report no outgoing references at all. If this prevents the
1273-
// PHPUnit segfault, the bug lives in the trace-zval construction
1274-
// below; if the segfault persists, the bug is in installing the
1275-
// handler itself (e.g., handlers struct in read-only memory).
12761272
*table = std::ptr::null_mut();
12771273
*n = 0;
1274+
1275+
let Some(ast) = ext_php_rs::types::ZendClassObject::<WpMySqlNativeAst>::from_zend_obj(&*object)
1276+
.and_then(|z| z.obj.as_ref())
1277+
else {
1278+
return std::ptr::null_mut();
1279+
};
1280+
1281+
let Ok(cache) = ast.node_cache.try_borrow() else {
1282+
return std::ptr::null_mut();
1283+
};
1284+
let Ok(mut trace) = ast.gc_trace.try_borrow_mut() else {
1285+
return std::ptr::null_mut();
1286+
};
1287+
1288+
trace.clear();
1289+
trace.reserve(cache.len());
1290+
for boxed in cache.values() {
1291+
// Build a zval pointing at the cached wrapper without bumping
1292+
// refcount — the GC scan just enumerates outgoing references;
1293+
// mutating refcounts here would un-balance the collector's
1294+
// accounting. Using `Zval::new` + manual field writes (rather
1295+
// than `Zval::set_object` which would addref) keeps the trace
1296+
// entries refcount-neutral.
1297+
let mut zv: zval = std::mem::zeroed();
1298+
zv.value.obj = (&**boxed) as *const ZendObject as *mut _;
1299+
zv.u1.type_info = PHP_IS_OBJECT_EX;
1300+
trace.push(zv);
1301+
}
1302+
1303+
*table = trace.as_mut_ptr();
1304+
*n = trace.len() as std::os::raw::c_int;
12781305
std::ptr::null_mut()
12791306
}
12801307

0 commit comments

Comments
 (0)