Make WordPress Core

Opened 13 days ago

Last modified 3 hours ago

#65044 assigned defect (bug)

get_post_custom_values() missing array check, inconsistent with get_post_custom_keys()

Reported by: saratheonline's profile saratheonline Owned by: saratheonline's profile saratheonline
Milestone: 7.1 Priority: normal
Severity: normal Version: trunk
Component: Posts, Post Types Keywords: has-patch needs-testing needs-unit-tests
Focuses: Cc:

Description

Explain that get_post_custom() can return false or "", and that the sibling function

get_post_custom_keys() guards against this but get_post_custom_values() does not, causing a PHP 8+ warning.

Attachments (1)

65044_ajax_test.png (22.7 KB) - added by liaison 14 hours ago.

Download all attachments as: .zip

Change History (7)

#1 @saratheonline
13 days ago

  • Keywords has-patch needs-testing added
Last edited 12 days ago by saratheonline (previous) (diff)

This ticket was mentioned in PR #11496 on WordPress/wordpress-develop by @saratheonline.


12 days ago
#2

Trac ticket: Core-65044

Posts, Post Types: Fix missing array check in get_post_custom_values().

get_post_custom() can return false for an invalid post ID or an empty
string for a non-existing post. get_post_custom_values() accessed the
result as an array without first verifying it is one, triggering a PHP
warning on PHP 8+.


Adds an is_array() guard consistent with the sibling function
get_post_custom_keys(), which already handles this case correctly.

Fixes #65044

Posts, Post Types: Fix missing array check in get_post_custom_values().

get_post_custom() can return false for an invalid post ID or an empty
string for a non-existing post. get_post_custom_values() accessed the
result as an array without first verifying it is one, triggering a PHP
warning on PHP 8+.


Adds an is_array() guard consistent with the sibling function
get_post_custom_keys(), which already handles this case correctly.

## Use of AI Tools

@westonruter commented on PR #11496:


25 hours ago
#3

Could you add a test case for this change that the new code is covered?

#4 @westonruter
25 hours ago

  • Keywords needs-unit-tests added
  • Milestone changed from Awaiting Review to 7.1

#5 @liaison
14 hours ago

The sibling function get_post_custom_keys() already implements an is_array() check. Adding the same check to get_post_custom_values() prevents this invalid operation at the logic level rather than relying on PHP's error suppression.

Testing on PHP 8.2.12 with E_ALL shows that while the function returns null without crashing (thanks to the null coalescing operator), it still performs an invalid offset access on a boolean when get_post_custom() fails. This is a silent failure that violates defensive coding standards.

<?php
add_action( 'wp_ajax_test_65044', function() {
    $id = 999999;
    $values = get_post_custom_values( 'some_key', $id );
        var_dump(error_reporting());
    wp_send_json_success( array( 'result' => $values ) );
});


#6 @darshitrajyaguru97
3 hours ago

Additional Testing & Validation

I’ve tested this behavior on PHP 8.2 with E_ALL enabled and can confirm the inconsistency described in this ticket.

While get_post_custom_values() does not produce a fatal error and ultimately returns null, it still attempts to access an array offset on a non-array value when get_post_custom() fails.

Example test:

add_action( 'wp_ajax_test_65044', function() {
    $id = 999999; // Non-existent post ID
    $values = get_post_custom_values( 'some_key', $id );

    var_dump( error_reporting() );

    wp_send_json_success( array( 'result' => $values ) );
});

In this case, get_post_custom() returns false (or an empty string), and get_post_custom_values() proceeds with:

$custom[ $key ]

This results in an invalid offset access on a boolean/string value. Although PHP 8+ may not always surface it visibly (depending on error handling), it still constitutes a silent failure and violates defensive coding practices.

Consistency with Sibling Function

The related function get_post_custom_keys() already includes a safeguard:

if ( ! is_array( $custom ) ) {
    return;
}

Adding the same is_array() check in get_post_custom_values() would:

  • Prevent invalid offset access at the logic level
  • Align behavior with its sibling function
  • Avoid silent failures under stricter error reporting environments

Recommendation

Introduce a defensive check before accessing the array:

$custom = get_post_custom( $post_id );

if ( ! is_array( $custom ) ) {
    return null;
}

return isset( $custom[ $key ] ) ? $custom[ $key ] : null;

This is a minimal, backward-compatible fix that improves robustness and consistency across the API.

Note: See TracTickets for help on using tickets.