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

Override PHP's default error and exception handler printing #5136

Open
wants to merge 8 commits into
base: trunk
Choose a base branch
from

Conversation

anomiex
Copy link

@anomiex anomiex commented Sep 4, 2023

WordPress relies on PHP's display_errors setting for error reporting. One unfortunate result of that is that errors containing HTML may be served to the browser unescaped.

WordPress/WordPress-Coding-Standards tries to help avoid this by having a sniff (WordPress.Security.EscapeOutput) that, among other things, asks that strings passed to trigger_error() and throw new SomeClass() be escaped. This is not a very good solution for a few reasons:

  • It doesn't do anything about errors or exceptions thrown by PHP itself.
  • It doesn't do anything about errors or exceptions thrown by libraries that might be bundled into themes or plugins or any custom code blog authors might inject.
  • It means that text-based log files, non-HTML emails, CLI output, and the like will contain HTML entities.

Instead we should follow the principle that values should be escaped close to the point of output, when we know what kind of escaping will be needed. Which, in the context of PHP, means using set_error_handler() and set_exception_handler() to handle the outputting.

But WordPress also relies on various other things that PHP's default handlers do, not all of which we can duplicate. But on the plus side since display_errors is not exactly a boolean (and PHP doesn't care anyway) we can have the handlers themselves set display_errors to a sentinel value that PHP will interpret as "off", do any necessary output, and then hand off to PHP's default handlers to do everything else.

Trac ticket: https://core.trac.wordpress.org/ticket/59282


This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.

Copy link
Member

@dingo-d dingo-d left a comment

Choose a reason for hiding this comment

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

Left some minor comments regarding code readability mostly.

I think the new functions should be covered by unit tests.

src/wp-error-handling.php Show resolved Hide resolved
src/wp-error-handling.php Outdated Show resolved Hide resolved
WordPress relies on PHP's `display_errors` setting for error reporting.
One unfortunate result of that is that errors containing HTML may be
served to the browser unescaped.

WordPress/WordPress-Coding-Standards tries to help avoid this by having
a sniff (WordPress.Security.EscapeOutput) that, among other things, asks
that strings passed to `trigger_error()` and `throw new SomeClass()` be
escaped. This is not a very good solution for a few reasons:

* It doesn't do anything about errors or exceptions thrown by PHP
  itself.
* It doesn't do anything about errors or exceptions thrown by libraries
  that might be bundled into themes or plugins or any custom code blog
  authors might inject.
* It means that text-based log files, non-HTML emails, CLI output, and
  the like will contain HTML entities.

Instead we should follow the principle that values should be escaped
close to the point of output, when we know what kind of escaping will be
needed. Which, in the context of PHP, means using `set_error_handler()`
and `set_exception_handler()` to handle the outputting.

But WordPress also relies on various other things that PHP's default
handlers do, not all of which we can duplicate. But on the plus side
since `display_errors` is not exactly a boolean (and PHP doesn't care
anyway) we can have the handlers themselves set `display_errors` to a
sentinel value that PHP will interpret as "off", do any necessary
output, and then hand off to PHP's default handlers to do everything
else.
And also don't bother replacing falsey values with "wp".
…config.

That also requires separating the "print" logic into a separate helper function.
Copy link

Test using WordPress Playground

The changes in this pull request can previewed and tested using a WordPress Playground instance.

WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser.

Some things to be aware of

  • The Plugin and Theme Directories cannot be accessed within Playground.
  • All changes will be lost when closing a tab with a Playground instance.
  • All changes will be lost when refreshing the page.
  • A fresh instance is created each time the link below is clicked.
  • Every time this pull request is updated, a new ZIP file containing all changes is created. If changes are not reflected in the Playground instance,
    it's possible that the most recent build failed, or has not completed. Check the list of workflow runs to be sure.

For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation.

Test this pull request with WordPress Playground.

This seems opposite to how we do anonymous functions, but 🤷.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
3 participants