Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aggressively use actual function parameters in php_verror #12276

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

NattyNarwhal
Copy link
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?).

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, but at least this is user controllable.

See GH-12048. Test output will need a ton of rewriting, which I have not got to. CI will have a field day there...

@NattyNarwhal
Copy link
Member Author

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

Copy link
Member

@Girgias Girgias left a comment

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!

Zend/zend_exceptions.c Outdated Show resolved Hide resolved
@NattyNarwhal
Copy link
Member Author

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
Member

@NattyNarwhal run-tests.php --bless

@NattyNarwhal
Copy link
Member Author

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
Member

Girgias commented Sep 26, 2023

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
Member Author

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
Member

Girgias commented Sep 26, 2023

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
Member Author

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
Member Author

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
Member

Girgias commented Sep 27, 2023

Yeah not a fan about the INI setting :D

@NattyNarwhal
Copy link
Member Author

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.

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
- move build_dynamic_parameters to zend_exceptions, avoid the dependency
  on the BIF header in main.c
- (though i'm not sure if exceptions is best place for this function)
- add documentation comments to new API surface from this PR
With the change to php_verror, it now prints the arguments to the
function. The strings in an argument can have absolute paths, and
containing user-specific things like a home directory isn't very
good for unit tests. Try to cut that out as much as possible.
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.
@NattyNarwhal
Copy link
Member Author

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
Copy link
Member

bwoebi commented Dec 13, 2024

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
Member

bukka commented Dec 14, 2024

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
Member Author

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
Member

bukka commented Dec 14, 2024

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.

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.

5 participants