Ticket #4625 (closed defect (bug): fixed)

Opened 5 years ago

Last modified 2 years ago

apply_filters is broken

Reported by: Denis-de-Bernardy Owned by: anonymous
Priority: high Milestone: 2.3
Component: General Version: 2.2.1
Severity: normal Keywords: has-patch
Cc:

Description

should be:

	foreach ( $wp_filter[$tag] as $filter ) {
		foreach( (array) $filter as $the_ )
			if ( !is_null($the_['function']) ){
				$args[1] = $string;
				$string = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
			}
	}

because if you use remove_filter() at some point, you can end up with an empty array on $wp_filters[$tag]. using while ( next($wp_filters[$tag]) ) at that point ends up ignoring a whole batch of applicable filters.

Attachments

4625.diff Download (432 bytes) - added by Nazgul 5 years ago.

Change History

A simpler change to fix this would be to change the while ( next($wp_filters[$tag]) ) into: while ( next($wp_filters[$tag]) !== FALSE)

next() returns the next entry in $wp_filters[$tag], or false when there's no more there. While it's true that the empty array could fail the boolean evaluation, it cannot fail a !== FALSE check.

Nazgul5 years ago

  • Keywords has-patch added
  • Priority changed from highest omg bbq to high

Added a patch based on the suggestion by Otto42.

Shouldn't you also add it to the other? There are two in that file.

do { } while ( next($wp_filters[$tag]) );

The other one is in do_action, and yeah, in theory it could be susceptible to the same issue.

Holy cow! I was able to reproduce this and wow, that is messed up.

The patch works also. I'm going to test to see if the other one needs it also.

  • Milestone changed from 2.2.2 to 2.3 (trunk)

Is there any good reason to leave these as do...while loops? (other than making this fix a smaller patch, that is)

do...while loops have their place, but iterating through an array is not it.

Well, it could be faster having it as a while loop, but really, if all you need is to continue and iterate over all items, foreach might also work.

It is all the same. I think the do ... while was for making sure that the first item was iterated over. It is also perhaps safer to remove items while inside the array (perhaps, but would need testing for foreach).

while( ( $filter = next( $wp_filter[$tag] ) !== false)
{
    foreach( ... )
    {

    }
}

A good reason: Because it works and won't require more testing.

I like that reason. :-)

  • Status changed from new to closed
  • Resolution set to fixed

(In [5857]) explicitly check next() against FALSE when iterating through filters. Props Denis-de-Bernardy, Otto42, Nazgul, santosj (go team effort!). fixes #4625 for trunk

  • Status changed from closed to reopened
  • Resolution fixed deleted

the same problem occurs for do_action

the same problem occurs for do_action

The patch here only applied to apply_filters, but the SVN commit applied the patch to apply_filters and do_action.

Allthough i notice it wasnt applied to do_action_ref_array

  • Status changed from reopened to closed
  • Resolution set to fixed

(In [5958]) explicitly check next() against FALSE in do_action_ref_array(). Props Denis-de-Bernardy, Otto42, Nazgul, santosj, DD32. fixes #4625 for trunk

Note: See TracTickets for help on using tickets.