[wp-trac] [WordPress Trac] #30875: address non-integer add_filter priority

WordPress Trac noreply at wordpress.org
Fri Oct 25 21:43:41 UTC 2024


#30875: address non-integer add_filter priority
-----------------------------+-------------------------
 Reporter:  drrobotnik       |       Owner:  (none)
     Type:  defect (bug)     |      Status:  closed
 Priority:  normal           |   Milestone:
Component:  Plugins          |     Version:  4.1
 Severity:  normal           |  Resolution:  maybelater
 Keywords:  has-patch close  |     Focuses:
-----------------------------+-------------------------

Comment (by kkmuffme):

 @hellofromTonya I'd like to reopen this, since this can have unexpected
 security consequences.

 - by default PHP will internally cast int-like strings to int when used as
 array key https://3v4l.org/gsojJ so there is some type-casting happening
 already anyway

 - given that the docs state the priority must be int, I see various
 (mostly security) plugins use code like:

 {{{#!php
 add_filter( 'some_hook', 'must_run_last', PHP_INT_MAX );


 or the paranoid ones:
 function one_before_last() {
     add_filter( 'some_hook', 'must_run_last', PHP_INT_MAX );
 }
 add_filter( 'some_hook', 'one_before_last', PHP_INT_MAX - 1, 0 );
 }}}

 But since WP core accepts any type for the priority - unlike documented -
 you can just do this:

 {{{#!php
 add_filter( 'some_hook', 'actually_i_will_run_last', (string) PHP_INT_MAX
 . 0, 0 );
 }}}

 (example see: https://3v4l.org/7SBeg)

 and circumvent this (naturally also works in reverse with "run first")

 Then additionally, with PHP<8 (since those issues are fixed in 8.0.0) it
 can lead to really inconsistent results where the order the callbacks are
 executed is different depending on the PHP version (this issue also partly
 exists with "int" in PHP<8 but it's much more consistent). e.g.

 {{{#!php
 $array = array( PHP_INT_MAX => 'MAX', PHP_INT_MIN => 'MIN',
 "-9223372036854775809" => "SMALLER THAN MIN" );

 ksort( $array, SORT_NUMERIC );
 var_dump( $array );
 }}}

 Results in different output in PHP 7.4 and PHP 8+

 - another issue is when you want to conditionally run stuff after an
 existing filter.

 {{{#!php
 add_filter( 'foo', 'bar', '1O' );

 $priority = has_filter( 'foo', 'bar' );
 add_filter( 'foo', 'run_after_bar', $priority + 1 );
 }}}

 In PHP7.1+ it will result in "A non well formed numeric value encountered"
 and from 8 onwards in "Warning: A non-numeric value encountered"

 Now if you try the same but with:

 {{{#!php
 add_filter( 'foo', 'bar', 'SOME TEXT' );
 }}}

 It will result in a fatal error from PHP 8+
 Fatal error: Uncaught TypeError: Unsupported operand types: string + int


 - PHP - expect the unexpected :-) Would you expect 3 do be negative?

 {{{#!php
 $priority_1 = '9223372036854775806';
 $priority_2 = $priority_1 + 1;
 $priority_3 = $priority_2 + 1;

 var_dump(
         array(
                 $priority_1 => 'first',
                 $priority_2 => 'second',
                 $priority_3 => 'third',
         )
 );
 }}}




 >If data type strictness is truly needed for the priority (for example, to
 ensure its compatible with a future PHP version that will impact it), then
 an intentional slow campaign is warranted. For example, first inform
 through deprecation or notice with a long runway before raising the error
 level to enforce the integer data type and take action (such as bailing
 out or setting a default priority value).

 This has long happened. PHP < 8.1 does not even receive security patches
 anymore, and WP still has "compatibility with exceptions" support for it.
 In php-src there has long been a push for stricter types and static
 analysis, but WP somehow slept on that. It's been 4 years since PHP 8
 release.

 Adding a "doing_it_wrong" for cases where !is_int( $priority ) is simple
 enough and not breaking and should have shipped ages ago.

 If you merge it, I will create a PR so it can be shipped with WP 6.9 at
 least.

-- 
Ticket URL: <https://core.trac.wordpress.org/ticket/30875#comment:20>
WordPress Trac <https://core.trac.wordpress.org/>
WordPress publishing platform


More information about the wp-trac mailing list