Fixes #16#19
Conversation
There was a problem hiding this comment.
Pull request overview
This PR addresses an Apache restart segfault caused by the date extension retaining a tzdb pointer that references memory inside the timezonedb shared object after it has been unloaded.
Changes:
- Registers the module’s
PHP_MSHUTDOWN_FUNCTIONin thezend_module_entry. - Resets the date extension tzdb pointer back to PHP’s builtin timezone database during module shutdown.
- Exposes the
PHP_MSHUTDOWN_FUNCTION(timezonedb)declaration in the public header.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| timezonedb.c | Hooks MSHUTDOWN and restores tzdb pointer to builtin DB before unload to prevent stale-pointer crashes. |
| php_timezonedb.h | Adds the PHP_MSHUTDOWN_FUNCTION(timezonedb) prototype to match the module entry wiring. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
derickr
left a comment
There was a problem hiding this comment.
This seems to break the Windows builds?
It is because
timelib_tzdb *php_date_global_timezone_db;
int php_date_global_timezone_db_enabled;An extension such as pecl/timezonedb sets it via The bug
PHP_MINIT_FUNCTION(date)
{
REGISTER_INI_ENTRIES(); /* may validate date.timezone against the tzdb */
date_register_classes();
register_php_date_symbols(module_number);
php_date_global_timezone_db = NULL; /* reset happens too late */
php_date_global_timezone_db_enabled = 0;
...
}
Crash scenario (mod_php / embedded SAPIs)
Whether step 3 crashes depends on where the SO would be remapped (ASLR), so reproduction is intermittent. Reported against pecl/timezonedb as issue #16 (observed on PHP 8.2.18). FixClear the globals before anything can read them:
Either placement removes every dereference of the stale pointer. The reset has sat after Related limitation
if (php_version_compare(tzdb->version, builtin->version) > 0) { ... }so an extension cannot restore the builtin db itself (same version compares equal), and |
The
timezonedbextension callsphp_date_set_tzdb(&timezonedb_external)during MINIT, pointing the date extension's global tzdb pointer at data inside the timezonedb shared object. When Apache restarts, the timezonedb SO gets unloaded but the date extension still holds the now-stale pointer. On re-initialization, the date extension starts before timezonedb (due to the dependency order) and tries to validate the "UTC" timezone against the invalid pointer, causing a segfault inseek_to_tz_position.The fix registers the existing
PHP_MSHUTDOWN_FUNCTIONin the module entry and resets the tzdb pointer back to PHP's builtin timezone database before the SO is unloaded.