Skip to content

Aggressively use actual function parameters in php_verror - #12276

Merged
NattyNarwhal merged 8 commits into
php:masterfrom
NattyNarwhal:verror-consistent-params
Jun 1, 2026
Merged

Aggressively use actual function parameters in php_verror#12276
NattyNarwhal merged 8 commits into
php:masterfrom
NattyNarwhal:verror-consistent-params

Conversation

@NattyNarwhal

@NattyNarwhalNattyNarwhal commented Sep 22, 2023

Copy link
Copy Markdown
Member

PHP errors used to not show parameter info consistently. Make it so that it uses a backtrace to get function info, similar to how exceptions work.

This makes the docref error functions' parameter argument mostly vestigal, being used only if allocation fails basically. The parameter argument may be useful in the case it is more verbose than the actual function args (is there a case?).

This is an INI option, so that this behaviour can be turned off. We do so for tests, as to avoid rewriting most EXPECTF sections. This can be changed, of course.

See GH-12048. (Updated in 2026-03-04.)

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

The new hotness:

calvin@anika php-src % sapi/cli/php ~/src/chmod.php
Warning: unlink('/tmp'): Operation not permitted in /Users/calvin/src/chmod.php on line 3
Warning: chown('/', 'calvin'): Operation not permitted in /Users/calvin/src/chmod.php on line 4
Warning: chmod('/', 511): Operation not permitted in /Users/calvin/src/chmod.php on line 5

Versus the old busted stuff:

calvin@anika php-src % /opt/calvin/php/bin//php ~/src/chmod.php
Warning: unlink(/tmp): Operation not permitted in /Users/calvin/src/chmod.php on line 3
Warning: chown(): Operation not permitted in /Users/calvin/src/chmod.php on line 4
Warning: chmod(): Operation not permitted in /Users/calvin/src/chmod.php on line 5

@GirgiasGirgias left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for looking into this!

Comment threadZend/zend_exceptions.c Outdated
@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

The big awful annoyance is going to be rewriting pretty much every test file. I know there's been other wide sweeping commits that changed a lot of stuff before though. Were they doing anything automated to clean those up?

@iluuu1994

Copy link
Copy Markdown
Member

@NattyNarwhalrun-tests.php --bless

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

That works, although paths are kinda annoying - all the absolute paths are there, and truncated, i.e. Warning: symlink('/Users/calvin/s...', '../bad/./symlin...'):. At least it fixed the resource IDs. I'm considering changing bless to make this easier to deal with.

@Girgias

Copy link
Copy Markdown
Member

That works, although paths are kinda annoying - all the absolute paths are there, and truncated, i.e. Warning: symlink('/Users/calvin/s...', '../bad/./symlin...'):. At least it fixed the resource IDs. I'm considering changing bless to make this easier to deal with.

Changing bless probably makes sense as part of this PR yes, ideally it should replace those with %s

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

So my change to bless as below:

diff --git a/scripts/dev/bless_tests.php b/scripts/dev/bless_tests.php
index fa49647fcf..2422512880 100755
--- a/scripts/dev/bless_tests.php+++ b/scripts/dev/bless_tests.php@@ -72,6 +72,8 @@ function normalizeOutput(string $out): string {
'Resource ID#%d used as offset, casting to integer (%d)',
$out);
$out = preg_replace('/string\(\d+\) "([^"]*%d)/', 'string(%d) "$1', $out);
+ // Replace absolute paths, particularly those truncated; they're likely to have your homedir in it+ $out = preg_replace("/'\\/.*\.\\.\\.'/", "'%s'", $out);
$out = str_replace("\0", '%0', $out);
return $out;
}

...does work, like so:

-Warning: fileperms(): stat failed for /no/such/file/dir in %s on line %d+Warning: fileperms('%s'): stat failed for /no/such/file/dir in %s on line %d

Of course, bless is also a little insensitive, so you do have to manually postprocess these (unless there's a better way to do it?)

-Warning: chmod(): %s in %s on line %d+Warning: chmod('/etc/passwd', 511): Operation not permitted in %s on line %d

To speak nothing of the tests I can't run because i.e. Windows.

@Girgias

Copy link
Copy Markdown
Member

One thing that I just thought about is that if the parameter is going to be displayed it should be suppressed if the SensitiveParam attribute is used.

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

One thing that I just thought about is that if the parameter is going to be displayed it should be suppressed if the SensitiveParam attribute is used.

The code that prints the arguments in errors is shared with code that prints backtraces i.e. on exceptions. Both cases are handled, so you'll get Warning: odbc_connect('bogusdsn', 'user', Object(SensitiveParameterValue)): SQL error: [unixODBC][Driver Manager]Data source name not found and no default driver specified, SQL state IM002 in SQLConnect and Stack trace: #0 /Users/calvin/src/chmod.php(10): sensitive(Object(SensitiveParameterValue)).

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

One thing that came to mind was turning this into an INI option, and it could be off for just the test suite or by default in general if the new output is intrusive. That said, I don't think configurability is a good idea (in terms of making the option used, and the PHP stance on introducing new options in general), but bringing it up anyways.

@Girgias

Copy link
Copy Markdown
Member

Yeah not a fan about the INI setting :D

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

I've pushed changes to ext/standard/tests/file, mostly because it would likely have a ton of absolute paths in the new parameters, and a small enough set to check bless output without getting overwhelmed. Unfortunately, I still had to change a lot of the test outputs back (or further manually) in cases where bless was overzealous, ignorant (still a lot of absolute paths in error messages), or a bit naive (i.e. fscanf test putting format strings like %d in paramters, which confuses EXPECTF). The question is if there's a better way to scale this up to all the other tests.

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

I've rebased this onto master and added an INI option to gate this behind. I don't like adding INI options, but it might be a lesser evil than touching every PHPT file.

@bwoebi

bwoebi commented Dec 13, 2024

Copy link
Copy Markdown
Member

I don't think we should do this. Like, adding configs, just because it avoids updating some tests. What we were talking about over in the other PR is displaying the stacktrace, which anyway already has an ini.

@bukka

Copy link
Copy Markdown
Member

I thought about this and the INI actually makes sense here. The reason is that this is more an operational thing. It's really just not about avoiding the tests updates. The thing is that for some legacy projects where warnings happening quite often (I saw quite a few such projects in past), this can lead not only to a significant increase of the log space but to the potential compliance issues. An example of that might be a function receiving email addresses and compliance with GDPR or similar. I realise that there is such potential with stack traces already but those are usually less common than warnings in the logs. So for some users it might be convenient to disable logging of parameters so having such INI seems reasonable to me.

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

I'm not sure if you're talking about GH-17056, this PR, or both. Sorry for any confusion by mentioning that PR on a commit here; the discussion in that PR was motivating me to revive this PR I had.

@bukka

Copy link
Copy Markdown
Member

I was talking about this PR but it could apply to both. But this one can especially increase the log size as fatal errors are not that common. However if you have lots regular warning in logs and they suddenly get all params logged, then it can increase the size and cost. So having an option to disable is a good think IMHO.

@DanielEScherzer

Copy link
Copy Markdown
Member

@NattyNarwhal happy to review this once rebased

@NattyNarwhal
NattyNarwhalforce-pushed the verror-consistent-params branch from 90ec7b5 to 7434069CompareMarch 3, 2026 16:07

@DanielEScherzerDanielEScherzer left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please

  • add some tests to show the new behavior when this is enabled
  • update the example INI files php.ini-development and php.ini-production

Comment threadZend/zend_exceptions.c Outdated
Comment threadmain/main.c Outdated
@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

Made the suggested changes. I'm also going to write to internals@ soonish and almost certainly prepare an RFC. When I originally wrote this, I knew much less about the process (and the v2 backtrace RFC wasn't around yet).

Comment threadmain/main.c Outdated
Comment threadmain/main.c Outdated
@@ -100,7 +100,8 @@ class ServerClientTestCase
$ini = php_ini_loaded_file();
$cmd = sprintf(
'%s %s "%s" %s',
PHP_BINARY, $ini ? "-n -c $ini" : "",
// XXX: TEST_PHP_EXTRA_ARGS for run-test values won't work here?
PHP_BINARY, $ini ? "-n -c $ini -d error_ignore_args=1" : "",

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this expected to emit errors during regular operation? Otherwise I would find it okay to leave out that option here and fix a (small) number of tests.

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One test (sapi/cli/tests/gh18582.phpt) does so. I set it here to make them consistent across all tests in case more are added; if not appropriate, it can be moved to that test with the cmd_args parameter on the server function.

@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

test failures unrelated, having the same on master

@NattyNarwhal
NattyNarwhalforce-pushed the verror-consistent-params branch from b289770 to 3c58215CompareMay 12, 2026 21:29
@NattyNarwhal

Copy link
Copy Markdown
MemberAuthor

RFC was approved; INI subvote indicates it should be set to 0 in the default INIs and in tests.

@NattyNarwhal
NattyNarwhal marked this pull request as ready for review May 16, 2026 03:15
Comment threadscripts/dev/bless_tests.php
Comment threadphp.ini-production Outdated
Comment threadphp.ini-development Outdated
Comment threadZend/tests/display_error_function_args.phpt Outdated
Comment threadZend/tests/display_error_function_args.phpt Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment on lines +634 to +635
smart_str_0(&str);
return str.s ? str.s : ZSTR_EMPTY_ALLOC();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
smart_str_0(&str);
returnstr.s ? str.s : ZSTR_EMPTY_ALLOC();
returnsmart_str_extract(&str);

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea; I cribbed the pattern from other functions in this file, so probably should file a PR to fix those up too...

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cleaning up the other functions would be nice indeed!

Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated

@TimWollaTimWolla left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. We're almost there. You missed switching EXPECTED to UNEXPECTED when inverting the condition and the loop can be simplified.

Comment threadZend/zend_exceptions.c Outdated
Comment threadZend/zend_exceptions.c Outdated
/* get a backtrace to snarf function args */
zval backtrace;
zend_fetch_debug_backtrace(&backtrace, /* skip_last */ 0, /* options */ 0, /* limit */ 1);
/* can fail esp if low memory condition */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

which call is failing? Is this that the zval type might not be an array on failure? Can you add a test case with memory exhaustion?

@NattyNarwhalNattyNarwhalMay 25, 2026

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think backtrace may not return an array if under memory exhaustion. I'm not sure how best to test memory exhaustion cases though.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure either, nevermind then

Comment threadphp.ini-development
; function upon an error. If this is off (or there was an error fetching the
; arguments), the function providing the error may optionally provide some
; additional information after the problem function's name.
;error_include_args = Off

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend that the default be On for development, even if off for production

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In retrospect, I should have done separate production vs. development INI value votes for the RFC. I'm not sure if I can do this after the vote?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point - let's go with Off for now in development too, and then if you want to send a separate PR to change the development suggested default to On we can see if there are any objections on the mailing list

NattyNarwhaland others added 8 commits June 1, 2026 12:58
PHP errors used to not show parameter info consistently.
Make it so that it uses a backtrace to get function info, similar to how
exceptions work.
This makes the docref error functions' parameter argument mostly
vestigal, being used only if allocation fails basically.
Several tests will fail from the fact we include function params.
One annoyance is that _build_trace_args truncates strings according to
exception_string_param_max_len.
See phpGH-12048
Co-authored-by: Tim Düsterhus <tim@bastelstu.be>
This is a useful feature, but enabling it by default requires rewriting
every PHPT file's output section. Since that would be a hellish diff to
make and to review, I think the best option is unfortunately, another
INI option. We can enable this for prod/dev recommended INIs, but make
sure it's disabled for the test runner.
This takes some inspiration from the discussion in phpGH-17056, which has
similar problems to this PR.
If this is not enabled by default for tests (like the fatal error
backtrace RFC), then at least test for it.
Per feedback from Tim on the RFC. Also rationalize the default vs.
recommended INI settings.
This does invert the semantics for the option; the if is changed
accordingly.
Almost certainly a better way to do this...
Avoid a negative which is harder to reason about; matches RFC change
RFC is going towards adding this, but disabling it by default.
@NattyNarwhal
NattyNarwhalforce-pushed the verror-consistent-params branch from a3084cf to dcc8065CompareJune 1, 2026 15:59
@NattyNarwhal
NattyNarwhal merged commit a22c56c into php:masterJun 1, 2026
18 checks passed
NattyNarwhal added a commit to NattyNarwhal/php-src that referenced this pull request Jun 1, 2026
User-specific absolute paths should be avoided in tests, since they
aren't portable. Change bless to detect common places where this occurs
and make it use %s in EXPECTF if so.
This was originally developed as part of phpGH-12276. While the approved
RFC doesn't enable function parameters to be printed for tests, the
functionality is generally useful.
NattyNarwhal added a commit that referenced this pull request Jul 7, 2026
User-specific absolute paths should be avoided in tests, since they
aren't portable. Change bless to detect common places where this occurs
and make it use %s in EXPECTF if so.
This was originally developed as part of GH-12276. While the approved
RFC doesn't enable function parameters to be printed for tests, the
functionality is generally useful.
@jrfnl

Copy link
Copy Markdown
Contributor

Looks like this is missing entries in UPGRADING and NEWS....

Sign up for freeto 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.

9 participants

@NattyNarwhal@iluuu1994@Girgias@bwoebi@bukka@DanielEScherzer@jrfnl@TimWolla@chschneider