On 09/04/2025 03:00, Andrew Lyons wrote:
Hi everyone,

I've been working on a new RFC which proposes changing the default value for the zend.exception_ignore_args INI setting from Off to On.

The intent of this change is to make PHP installations safer by default and prevent the accidental release of sensitive information in stack traces.

* RFC: https://wiki.php.net/rfc/exception_ignore_args_default_value
* Implementation: https://github.com/php/php-src/pull/18215


This discussion seems to have overlooked that the setting doesn't just restrict the *display* of arguments, it restricts the *collection* of those arguments into the Exception object, which has visible effects on the behaviour and performance of the program.

Because of PHP's reference counting memory model, programmers can usually rely on memory being freed and destructors being called when a local variable goes out of scope. Without zend.exception_ignore_args=1, the lifetime of any zval which happened to be involved in a parameter anywhere on the stack, is extended to last until the Exception object is destructed. That can mean holding onto large amounts of memory, holding open file handles and network connections, or firing "RAII" destructors in an unexpected order.

Note that this is tied to the lifetime of the exception object, not when it is thrown and caught; and it is recursive - an array containing an object with a property pointing to another object keeps all those arrays and objects alive, just in case you want to inspect them in the error trace.

Another edge case I encountered a few years ago is when I wrote some code that serialized an exception (to propagate it from a worker process to its parent): the exception itself was serializable, but a completely unrelated change caused an unserialized object to show up as a parameter somewhere on the call stack, causing the whole exception to become unserializable.


On the other side, PHP is not a Functional Programming language, so knowing the arguments that were passed into a function is rarely enough to reconstruct the state that led to the exception. Manual backtraces can also collect a copy of $this for method calls, with the DEBUG_BACKTRACE_PROVIDE_OBJECT option, but the exception constructor never passes that. Nor does it collect a snapshot of static and global variables, or the state of opaque objects and resources like file/stream handles.

Collecting arguments seems like a special case which could be handled by debug or APM extensions, rather than something that most users will ever need.


--
Rowan Tommins
[IMSoP]

Reply via email to