Skip to content
Closed
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
45 changes: 45 additions & 0 deletions tests/phpunit/tests/canonical.php
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,51 @@ 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
* @ticket 64250
*
* @covers ::redirect_guess_404_permalink
*/
public function test_redirect_guess_404_permalink_cache_key_excludes_placeholder_escape() {
$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 = wp_cache_get_salted(
'redirect_guess_404_permalink:' . md5( $queries[0] ),
'post-queries',
wp_cache_get_last_changed( 'posts' )
);

$this->assertSame( $post, $cache, 'The cache key should be generated from the query without the placeholder escape.' );
}

/**
* @ticket 64250
*
Expand Down
Loading