Make WordPress Core

Changes between Initial Version and Version 7 of Ticket #52252

02/10/2021 12:25:45 AM (6 months ago)

Thanks for looking into it @johnbillion!

This notice was caused by a fuzzer hitting WordPress.org, 500+ query vars in a POST request against a news post, makes it hard to narrow down the cause, so sorry for the bad report.

There's a guard condition at the beginning of wp_resolve_numeric_slug_conflicts() that protects against accessing the year, monthnum, or day indexes of $query_vars.

The guard condition protects against the case of all 3 being not set, but not against situations where only one out of the expected vars is set.

Looking at the code, I can clearly see that on line 400 monthnum being set without year results in year being looked for as an index on line 413, It seems that this happens early enough that the normal plugins such as Query monitor & Debug Bar don't pick it up the notice.

Is anything else needed to trigger this notice? Is w.org running trunk?

It looks like to trigger it with year you need to have the permalink structure set to /%postname%/ and request https://example.com/?monthnum=1

It looks like to trigger it with monthnum you need to have the permalink structure set to /%year%/%postname%/ and request https://example.com/?day=1

I can't see that day is possible as a notice here, only year/monthnum. I'm guessing I either copy-paste wrong or caused the day case in testing.

I pared it back as much as possible, and here's some debugging output for the year case:

  • wp-includes/rewrite.php

    412412        // This is the potentially clashing slug.
    413413        $value = $query_vars[ $compare ];
     415var_dump( compact( 'query_vars', 'permastructs', 'postname_index', 'compare', 'value' ) ); die();
    415416        $post = get_page_by_path( $value, OBJECT, 'post' );
    416417        if ( ! ( $post instanceof WP_Post ) ) {
    417418                return $query_vars;

results in:

GET https://wordpress.org/?monthnum=1

( ! ) Notice: Undefined index: year in wp-includes/rewrite.php on line 413
Call Stack
#	Time	Memory	Function	Location
1	0.0002	369824	{main}( )	.../index.php:0
2	0.0002	372720	require( 'wp-blog-header.php )	.../index.php:26
3	0.2574	6280864	wp( $query_vars = ??? )	.../wp-blog-header.php:16
4	0.2574	6280896	WP->main( $query_args = '' )	.../functions.php:1291
5	0.2574	6280896	WP->parse_request( $extra_query_vars = '' )	.../class-wp.php:750
6	0.2579	6304120	wp_resolve_numeric_slug_conflicts( $query_vars = ['monthnum' => '1'] )	.../class-wp.php:360

array (size=5)
  'query_vars' => 
    array (size=1)
      'monthnum' => string '1' (length=1)
  'permastructs' => 
    array (size=1)
      0 => string '%postname%' (length=10)
  'postname_index' => int 0
  'compare' => string 'year' (length=4)
  'value' => null


  • Ticket #52252

    • Property Status changed from new to reviewing
    • Property Owner set to johnbillion
    • Property Version changed from to 4.3
    • Property Milestone changed from Awaiting Review to Future Release
    • Property Keywords has-patch added; needs-patch removed
  • Ticket #52252 – Description

    initial v7  
    1 `E_NOTICE: Undefined index: year in wp-includes/rewrite.php:413` / `E_NOTICE: Undefined index: day in wp-includes/rewrite.php:413`
     1`E_NOTICE: Undefined index: year in wp-includes/rewrite.php:413` / `E_NOTICE: Undefined index: monthnum in wp-includes/rewrite.php:413`
    33It looks like [32648] assumes the permalink structures will always include both `year` & `monthnum` or `monthnum` & `day` https://core.trac.wordpress.org/browser/trunk/src/wp-includes/rewrite.php?marks=400-403#L393