Skip to content

Fix use of freed argv in atexit handlers on macOS - #25203

Open
GromNaN wants to merge 1 commit into
php:PHP-8.4from
GromNaN:fix/cli-argv-atexit
Open

GromNaN wants to merge 1 commit into
php:PHP-8.4from
GromNaN:fix/cli-argv-atexit

Conversation

@GromNaN

@GromNaN GromNaN commented Nov 5, 2026 •

Copy link
Copy Markdown
Member

ext-mongodb 2.5.x crashes on macOS at process shutdown, in about half of the CLI runs, with this stack:

sasl_client_done() -> digestmd5_common_mech_free()
-> _sasl_log() -> _sasl_syslog() -> asl_open() -> strrchr()

The extension calls sasl_client_done() from an atexit() handler. On macOS, Apple's Cyrus SASL logs through ASL, and asl_open() reads the process arguments through _NSGetArgv().

The root cause is in PHP. save_ps_args() installs a copy of argv in _NSGetArgv(), and cleanup_ps_args() frees that copy just before exit() without restoring the pointer. Any atexit() handler that reads _NSGetArgv() after that point reads freed memory. This is not specific to ext-mongodb: another library that logs through ASL from an atexit() handler can hit the same crash. See mongodb/mongo-php-driver#2213, where the extension works around it.

Restore the original argv pointer before freeing the copy, as is already done for environ.

The test adds a zend_test hook that registers an atexit() handler reading _NSGetArgv(), and checks that it no longer sees the freed copy and that argv[0] is readable. ZEND_DONT_UNLOAD_MODULES=1 keeps the extension loaded so the handler runs at process exit, and the test also covers a process title set with cli_set_process_title().

Verified on PHP 8.4 with zend_test built statically: the test passes with the fix, fails without it, and passes with run-tests.php --repeat 2.

This targets PHP 8.4, the oldest branch in active support.

cleanup_ps_args() frees the argv copy installed by save_ps_args() in _NSGetArgv() and restores environ only. Handlers registered with atexit() run after it, so any of them that reads the process arguments gets freed memory. On macOS this crashes ext-mongodb shutdown, because Apple's Cyrus SASL logs through ASL and asl_open() reads _NSGetArgv().

Restore the original argv pointer before freeing the copy, as is already done for environ. Add a zend_test hook and a test for the atexit() handler case.
@GromNaN
GromNaN force-pushed the fix/cli-argv-atexit branch from 33d46b3 to c3a24e5 Compare November 5, 2026 14:33
@GromNaN
GromNaN marked this pull request as ready for review November 5, 2026 14:42
@GromNaN
GromNaN requested a review from kocsismate as a code owner November 5, 2026 14:42
@kocsismate
kocsismate requested review from TimWolla and bukka November 8, 2026 21:16
@TimWolla
TimWolla removed their request for review November 9, 2026 07:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant