@@ -595,54 +595,6 @@ jobs:
595595 print('patched CreateTrigger to preserve original SQL text')
596596 PY_TRIGGER_SQL
597597
598- # Clear stale FUNC_SLOTS on sqlite3_close. Existing patches keep
599- # slots populated across PDO close (avoiding p_app UAF during
600- # PHP GC), but leftover stale `db` pointers persist process-wide
601- # and may explain mid-suite state-dependent failures (the
602- # 3 remaining tests pass in fresh-PDO probes).
603- python3 - <<'PY_CLOSE_SLOTS'
604- p = 'sqlite3/src/lib.rs'
605- s = open(p).read()
606- old = (
607- "#[no_mangle]\n"
608- "pub unsafe extern \"C\" fn sqlite3_close(db: *mut sqlite3) -> ffi::c_int {\n"
609- " trace!(\"sqlite3_close\");\n"
610- " if db.is_null() {\n"
611- " return SQLITE_OK;\n"
612- " }\n"
613- " let _ = Box::from_raw(db);\n"
614- " SQLITE_OK\n"
615- "}\n"
616- )
617- new = (
618- "#[no_mangle]\n"
619- "pub unsafe extern \"C\" fn sqlite3_close(db: *mut sqlite3) -> ffi::c_int {\n"
620- " trace!(\"sqlite3_close\");\n"
621- " if db.is_null() {\n"
622- " return SQLITE_OK;\n"
623- " }\n"
624- " // Clear any FUNC_SLOTS that still reference this db so the\n"
625- " // process-global table doesn't accumulate stale entries.\n"
626- " {\n"
627- " let db_addr = db as usize;\n"
628- " let mut slots = func_slots().lock().unwrap();\n"
629- " for slot in slots.iter_mut() {\n"
630- " if let Some(s) = slot.as_ref() {\n"
631- " if s.db == db_addr {\n"
632- " *slot = None;\n"
633- " }\n"
634- " }\n"
635- " }\n"
636- " }\n"
637- " let _ = Box::from_raw(db);\n"
638- " SQLITE_OK\n"
639- "}\n"
640- )
641- assert old in s, 'sqlite3_close block not found'
642- open(p, 'w').write(s.replace(old, new, 1))
643- print('patched sqlite3_close to clear stale FUNC_SLOTS for closing db')
644- PY_CLOSE_SLOTS
645-
646598 echo '--- Patched stub! macro ---'
647599 sed -n '/macro_rules! stub/,/^}$/p' sqlite3/src/lib.rs
648600
0 commit comments