Category
Regression: · php-src-strict · profile / advertisement gate (re-#17106 / re-#19047)
Problem
Default-profile VM advertises extension_loaded('sqlite3') === true and class_exists('SQLite3Exception') === true while class_exists('SQLite3') === false (supportsSqlite3() is 8.4-only). Zend 8.2 without ext/sqlite3: all three false. Zend 8.2 with ext/sqlite3: SQLite3 true and SQLite3Exception false (exception class is PHP 8.3+). Current split is not php-src-shaped on either axis.
| Repro |
Zend 8.2.32 (no ext/sqlite3) |
VM (2026-07-24, 0ae5aba, default) |
extension_loaded('sqlite3') |
false |
true |
class_exists('SQLite3') |
false |
false |
class_exists('SQLite3Exception') |
false |
true |
Sqlite3ExtensionPolicy::advertisesExtensionLoaded() / advertisesExceptionClass() always return true; only advertisesExtension() follows CompilerVersion::supportsSqlite3().
php-src reference
PHP implementation target
ext/sqlite3/Sqlite3ExtensionPolicy.php — pair extension_loaded('sqlite3') with supportsSqlite3() (or host-parity policy); gate SQLite3Exception on profile ≥ 8.3 and extension advertisement
ext/standard/ThrowableManifest.php / ext/sqlite3/BuiltinClasses.php — stop registering the exception when the extension surface is withheld
- No new C; PHP-in-PHP advertisement only
Repro
./script/docker-exec.sh -- bash -lc 'cat > /tmp/sqlite3_phantom.php <<\"PHP\"
<?php
echo \"PROFILE=\", getenv(\"PHP_COMPILER_PROFILE\") ?: \"(default)\", PHP_EOL;
echo \"extension_loaded=\", extension_loaded(\"sqlite3\") ? \"yes\" : \"no\", PHP_EOL;
echo \"SQLite3=\", class_exists(\"SQLite3\") ? \"yes\" : \"no\", PHP_EOL;
echo \"SQLite3Exception=\", class_exists(\"SQLite3Exception\") ? \"yes\" : \"no\", PHP_EOL;
PHP
php /tmp/sqlite3_phantom.php; echo EXIT_ZEND:$?
php bin/vm.php /tmp/sqlite3_phantom.php; echo EXIT_VM:$?
PHP_COMPILER_PROFILE=8.4 php bin/vm.php /tmp/sqlite3_phantom.php; echo EXIT_VM84:$?'
Done when
Category
Regression:· php-src-strict · profile / advertisement gate (re-#17106 / re-#19047)Problem
Default-profile VM advertises
extension_loaded('sqlite3') === trueandclass_exists('SQLite3Exception') === truewhileclass_exists('SQLite3') === false(supportsSqlite3()is 8.4-only). Zend 8.2 withoutext/sqlite3: all three false. Zend 8.2 withext/sqlite3:SQLite3true andSQLite3Exceptionfalse (exception class is PHP 8.3+). Current split is not php-src-shaped on either axis.extension_loaded('sqlite3')falsetrueclass_exists('SQLite3')falsefalseclass_exists('SQLite3Exception')falsetrueSqlite3ExtensionPolicy::advertisesExtensionLoaded()/advertisesExceptionClass()always return true; onlyadvertisesExtension()followsCompilerVersion::supportsSqlite3().php-src reference
ext/sqlite3/sqlite3.stub.php—SQLite3/SQLite3Exceptionext/sqlite3/php_sqlite3.c—SQLite3Exceptionregistration (8.3+)PHP implementation target
ext/sqlite3/Sqlite3ExtensionPolicy.php— pairextension_loaded('sqlite3')withsupportsSqlite3()(or host-parity policy); gateSQLite3Exceptionon profile ≥ 8.3 and extension advertisementext/standard/ThrowableManifest.php/ext/sqlite3/BuiltinClasses.php— stop registering the exception when the extension surface is withheldRepro
Done when
extension_loaded('sqlite3')/SQLite3/SQLite3Exceptionmatch Zend 8.2 reference (all false on hosts without the ext; no exception-without-class split)SQLite3+SQLite3Exception+extension_loadedconsistent when the in-tree module is enabled