From da936e9bfe4e04cdc2524180ab1c78f5294e408e Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Wed, 5 Oct 2011 23:31:34 +0000 Subject: [PATCH] (bug 31379) Don't use the $errcontext parameter of a PHP error handler to get information for error display, this introduces an unexpected, difficult-to-maintain data flow which leads to bugs like the referenced one above. --- AbuseFilter.parser.php | 51 ++++++++++++++++++++++++++++-------------- 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/AbuseFilter.parser.php b/AbuseFilter.parser.php index 22a285ed5..3263f3fef 100644 --- a/AbuseFilter.parser.php +++ b/AbuseFilter.parser.php @@ -216,12 +216,13 @@ class AFPData { $pattern .= 'i'; } + $handler = new AFPRegexErrorHandler( $pattern, $pos ); try { - set_error_handler( array( 'AbuseFilterParser', 'regexErrorHandler' ) ); + $handler->install(); $result = preg_match( $pattern, $str ); - restore_error_handler(); + $handler->restore(); } catch ( Exception $e ) { - restore_error_handler(); + $handler->restore(); throw $e; } return new AFPData( self::DBool, (bool)$result ); @@ -394,6 +395,32 @@ class AFPUserVisibleException extends AFPException { } } +class AFPRegexErrorHandler { + function __construct( $regex, $pos ) { + $this->regex = $regex; + $this->pos = $pos; + } + + function handleError( $errno, $errstr, $errfile, $errline, $context ) { + if ( error_reporting() == 0 ) { + return true; + } + throw new AFPUserVisibleException( + 'regexfailure', + $this->pos, + array( $errstr, $this->regex ) + ); + } + + function install() { + set_error_handler( array( $this, 'handleError' ) ); + } + + function restore() { + restore_error_handler(); + } +} + class AbuseFilterParser { var $mParams, $mVars, $mCode, $mTokens, $mPos, $mCur, $mShortCircuit, $mAllowShort; @@ -1477,12 +1504,13 @@ class AbuseFilterParser { $matches = array(); + $handler = new AFPRegexErrorHandler( $needle, $this->mCur->pos ); try { - set_error_handler( array( 'AbuseFilterParser', 'regexErrorHandler' ) ); + $handler->install(); $count = preg_match_all( $needle, $haystack, $matches ); - restore_error_handler(); + $handler->restore(); } catch ( Exception $e ) { - restore_error_handler(); + $handler->restore(); throw $e; } } @@ -1766,17 +1794,6 @@ class AbuseFilterParser { return AFPData::castTypes( $val, AFPData::DBool ); } - - public static function regexErrorHandler( $errno, $errstr, $errfile, $errline, $context ) { - if ( error_reporting() == 0 ) { - return true; - } - throw new AFPUserVisibleException( - 'regexfailure', - $context['pos'], - array( $errstr, $context['regex'] ) - ); - } } # Taken from http://au2.php.net/manual/en/function.fnmatch.php#71725