Fix avoid file_exists() on oversized strings in File detection to prevent PHP warnings - #267
the-hercules wants to merge 2 commits into
Conversation
…rresponding unit test
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## trunk #267 +/- ##
============================================
+ Coverage 86.49% 86.58% +0.08%
- Complexity 1327 1384 +57
============================================
Files 68 69 +1
Lines 4295 4449 +154
============================================
+ Hits 3715 3852 +137
- Misses 580 597 +17
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
felixarntz
left a comment
There was a problem hiding this comment.
@the-hercules Great catch! I think we may be able to find a cleaner solution though.
| // Check if it's a local file path (before base64 check). | ||
| // The length guard avoids calling file_exists() on over-length strings (e.g. base64 data), | ||
| // which would emit a warning containing the entire string. | ||
| if (strlen($file) <= PHP_MAXPATHLEN && file_exists($file) && is_file($file)) { |
There was a problem hiding this comment.
not sure this is the adequate check - can't we instead perform a check for whether the string is possibly a file path? maybe check if it starts with / (since it always needs to be an absolute path in practice)
Not entirely. I came across this because on nginx (Apache untested), with Query Monitor active, image generation fails with: According to Claude Code, this is because Query Monitor takes the full warning text and puts it in an add_filter( 'qm/dispatch/rest', '__return_false' )
// or more specifically
add_filter( 'qm/outputter/headers', fn( $o ) => array_diff_key( $o, [ 'php_errors' => 1 ] ), 999 ); // untested |
|
Hi @felixarntz The warning is triggered purely by the length, the length guard is the part that actually prevents the warning here. I feel this is the standard fix for this specific PHP behavior. Adding a leading-slash requirement might also unnecessarily drop support for relative local paths. @tyrann0us Yes it might be more than a log issue at this point. |
Infinite-Null
left a comment
There was a problem hiding this comment.
Hi @the-hercules, thank you for the PR 🙌
I was wondering if it would make sense to suppress the warning from the filesystem probe as well?
if (strlen($file) < PHP_MAXPATHLEN && @file_exists($file) && @is_file($file)) {I also think the test should cover the exact PHP_MAXPATHLEN boundary and a smaller Base64 payload, so we know both cases are covered.
One small thing to keep in mind: the current test's custom error handler will still capture warnings even when @file_exists() is used, so the test may need to account for the suppressed warning as well.
What do you think?
|
Hey @Infinite-Null, thanks for the review! 🙌 These are good suggestions, I agree with the points:
|
|
Hey @Infinite-Null, all three are in 🙌
Added boundary and smaller-payload tests. All tests pass across the supported PHP versions. One caveat: the warning tests only reproduce with open_basedir enabled, so they don’t fail against the old code in the default CI environment. Making them enforce the behavior would require running them in a separate process with open_basedir configured. |
Closes #258
Summary
File::detectAndProcessFile()callsfile_exists()while determining whether aninput string is a local path, before the plain-base64 branch is reached. When the
input is a large base64 payload (e.g. an image returned by a provider via
bytesBase64Encoded), the string exceeds the platform's maximum path length andPHP emits:
The warning message embeds the entire input string, so each occurrence writes
~1 MB to the error log. In practice this produced multi-megabyte error logs from
only a handful of image-generation calls. Base64-encoded JPEG data begins with
/9j/, which resembles an absolute path, so the string reachesfile_exists()before detection falls through to the base64 handling that processes it correctly.
Functionally the input was always handled correctly — this is a log-noise issue,
not a data-correctness one.
Change
Guard the filesystem check with a length comparison:
AI Disclosure
Claude Opus 4.8 was used for identification and then verification of correctness of the solution.