REST API: Restore is_array() check in rest_convert_error_to_response()#11307
REST API: Restore is_array() check in rest_convert_error_to_response()#11307nate-allen wants to merge 6 commits intoWordPress:trunkfrom
is_array() check in rest_convert_error_to_response()#11307Conversation
…se()`. The null coalescing conversion in [61429] removed the `is_array()` guard when accessing `$error_data['status']`. Since `WP_Error` data can be any type (including `stdClass`), this causes a PHP fatal error when non-array data is passed. This restores the type check while still using null coalescing for the array case. Props costdev, westonruter. Fixes #64901. See #63430.
|
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 Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Test using WordPress PlaygroundThe 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
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
is_array() check in rest_convert_error_to_response()
|
Thank you for addressing this. The prior change was indeed wrong because wordpress-develop/src/wp-includes/class-wp-error.php Lines 233 to 241 in 6607b4d I was curious why I wasn't seeing PHPStan flag this issue locally since where I have the PHPStan rule level 8 enforced. Only when I switched to rule level 9 did PHPStan catch the issue because it will:
Once I did that, it was caught:
|
src/wp-includes/rest-api.php
Outdated
| static function ( $status, $error_data ) { | ||
| return $error_data['status'] ?? $status; | ||
| // Note: $error_data may not be an array (e.g. stdClass), so is_array() check is intentional. | ||
| return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status; |
There was a problem hiding this comment.
There is an opportunity to further harden this, however. Namely, there is no guarantee that $error_data['status'] is an integer. If it is something else, then the $status will get passed to new WP_REST_Response( $data, $status ) which will then get passed into \WP_HTTP_Response::set_status() and ultmately passed here:
wordpress-develop/src/wp-includes/class-wp-http-response.php
Lines 115 to 117 in bd3f983
Passing a non-numeric value to absint() results in a value of 1 being set as the status. This is not a fatal error, but it is wrong. Therefore, this would be even safer:
| return is_array( $error_data ) && isset( $error_data['status'] ) ? $error_data['status'] : $status; | |
| if ( is_array( $error_data ) && isset( $error_data['status'] ) && is_numeric( $error_data['status'] ) ) { | |
| $status = (int) $error_data['status']; | |
| } | |
| return $status; |
There was a problem hiding this comment.
Thanks! Great suggestion. I've added the is_numeric() check and (int) cast, along with a test for non-numeric status values.
There was a problem hiding this comment.
@nate-allen Great! I also followed up with ea57364 to add explicit types, to use phpdoc instead of the inline comment, and I updated the test to account for the possibility that there could be more than one data item added that has status. Please take a look.
There was a problem hiding this comment.
Looks great! The type hints and expanded multi-status test are nice additions
…f non-array error data when obtaining `status`. While the error data is normally an array, this is not guaranteed. This issue would have been detected by PHPStan rule level 9, since `WP_Error::get_all_error_data()` returns `mixed[]`. Developed in #11307 Follow-up to r61429. Props nateallen, desrosj, jorbin, mukesh27, westonruter. See #63430. Fixes #64901. git-svn-id: https://develop.svn.wordpress.org/trunk@62107 602fd350-edb4-49c9-b593-d223f7449a82
…f non-array error data when obtaining `status`. While the error data is normally an array, this is not guaranteed. This issue would have been detected by PHPStan rule level 9, since `WP_Error::get_all_error_data()` returns `mixed[]`. Developed in WordPress/wordpress-develop#11307 Follow-up to r61429. Props nateallen, desrosj, jorbin, mukesh27, westonruter. See #63430. Fixes #64901. Built from https://develop.svn.wordpress.org/trunk@62107 git-svn-id: http://core.svn.wordpress.org/trunk@61389 1a063a9b-81f0-0310-95a4-ce76da25c4cd

61429 (part of the Code Modernization effort, #63430) replaced the
isset()ternary inrest_convert_error_to_response()with a null coalescing operator, removing theis_array()guard. SinceWP_Error::get_all_error_data()can return data of any type, this causes a PHP fatal error when error data is astdClassobject.This PR reverts the line to its original form and adds a test case for
stdClasserror data.Trac ticket: https://core.trac.wordpress.org/ticket/64901
Use of AI Tools
AI assistance: Yes
Tool(s): Claude Code
Model(s): Claude Opus 4.6
Used for: Identifying the regression by diffing 6.9.4 and 7.0-beta5, and writing the test case. The fix itself is a direct revert of the changed line. All code was reviewed by me.
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.