[wp-trac] [WordPress Trac] #52252: PHP Notice when `monthnum` query var is set without the `year` QV

WordPress Trac noreply at wordpress.org
Wed Feb 10 00:25:45 UTC 2021


#52252: PHP Notice when `monthnum` query var is set without the `year` QV
--------------------------+-----------------------------
 Reporter:  dd32          |       Owner:  johnbillion
     Type:  defect (bug)  |      Status:  reviewing
 Priority:  normal        |   Milestone:  Future Release
Component:  Query         |     Version:  4.3
 Severity:  normal        |  Resolution:
 Keywords:  has-patch     |     Focuses:
--------------------------+-----------------------------
Changes (by dd32):

 * keywords:  has-patch reporter-feedback => has-patch


Old description:

> `E_NOTICE: Undefined index: year in wp-includes/rewrite.php:413` /
> `E_NOTICE: Undefined index: day in wp-includes/rewrite.php:413`
>
> It 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
>
> But a request such as `?monthnum=1` will cause it to check for the `year`
> query var which might be unset.
>
> (Props to the pentester hitting WordPress.org with many junk requests for
> bringing this to light)

New description:

 `E_NOTICE: Undefined index: year in wp-includes/rewrite.php:413` /
 `E_NOTICE: Undefined index: monthnum in wp-includes/rewrite.php:413`

 It 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

 But a request such as `?monthnum=1` will cause it to check for the `year`
 query var which might be unset.

 (Props to the pentester hitting WordPress.org with many junk requests for
 bringing this to light)

--

Comment:

 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:
 {{{
 #!diff
 Index: wp-includes/rewrite.php
 ===================================================================
 --- wp-includes/rewrite.php     (revision 49926)
 +++ wp-includes/rewrite.php     (working copy)
 @@ -412,6 +412,7 @@
         // This is the potentially clashing slug.
         $value = $query_vars[ $compare ];

 +var_dump( compact( 'query_vars', 'permastructs', 'postname_index',
 'compare', 'value' ) ); die();
         $post = get_page_by_path( $value, OBJECT, 'post' );
         if ( ! ( $post instanceof WP_Post ) ) {
                 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

 wp-includes/rewrite.php:415:
 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 URL: <https://core.trac.wordpress.org/ticket/52252#comment:7>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list