Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/wp-includes/canonical.php
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,8 @@ function redirect_guess_404_permalink() {

$query = "SELECT ID FROM $wpdb->posts WHERE $where AND post_status IN ('" . implode( "', '", esc_sql( $publicly_viewable_statuses ) ) . "')";

$key = md5( $query );
// Remove the per-request placeholder escape so the cache key is stable across requests.
$key = md5( $wpdb->remove_placeholder_escape( $query ) );
$last_changed = wp_cache_get_last_changed( 'posts' );
$cache_key = "redirect_guess_404_permalink:$key";
$cache = wp_cache_get_salted( $cache_key, 'post-queries', $last_changed );
Expand Down
47 changes: 47 additions & 0 deletions tests/phpunit/tests/canonical.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,53 @@ public function test_redirect_guess_404_permalink_cache() {
$this->assertSame( 0, get_num_queries() - $start_num_queries, 'A cached lookup performed an additional database query.' );
}

/**
* Ensures the cache key does not contain the per-request `wpdb` placeholder escape.
*
* The placeholder escape string changes on every request, so a cache key derived from
* the escaped query could never be hit in a subsequent request.
*
* @ticket 66282
*
* @covers ::redirect_guess_404_permalink
*/
public function test_redirect_guess_404_permalink_cache_key_excludes_placeholder_escape() {
global $wpdb;
$post = self::factory()->post->create(
array(
'post_title' => 'redirect-guess-404-permalink-cache-key',
)
);

$this->go_to( 'redirect-guess-404-permalink-cache-ke' );

// The `query` filter receives the SQL after the placeholder escape has been removed.
$queries = array();
$filter = static function ( $query ) use ( &$queries ) {
if ( str_contains( $query, 'post_name LIKE' ) ) {
$queries[] = $query;
}
return $query;
};

add_filter( 'query', $filter );
$guess = redirect_guess_404_permalink();
remove_filter( 'query', $filter );

$this->assertSame( get_permalink( $post ), $guess, 'Did not guess the correct permalink.' );
$this->assertCount( 1, $queries, 'Expected exactly one loose-match query to be run.' );

$cache_key = 'redirect_guess_404_permalink:' . md5( $queries[0] );
$cache = wp_cache_get_salted(
$cache_key,
'post-queries',
wp_cache_get_last_changed( 'posts' )
);

$this->assertSame( $post, $cache, 'The cache key should be generated from the SQL query.' );
$this->assertStringNotContainsString( $wpdb->placeholder_escape(), $cache_key, 'Cache key should not contain WPDB placeholder.' );
}

/**
* @ticket 64250
*
Expand Down
Loading