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]