mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/Scribunto
synced 2024-12-18 02:41:09 +00:00
Add handling for PCRE errors in ustringGsub
Bug: T130823 Change-Id: I6fab71c82ddab92daf6b369cb9857d9892f2d246
This commit is contained in:
parent
35b3cdcb72
commit
ba19a82c06
|
@ -695,6 +695,52 @@ class Scribunto_LuaUstringLibrary extends Scribunto_LuaLibraryBase {
|
||||||
|
|
||||||
$count = 0;
|
$count = 0;
|
||||||
$s2 = preg_replace_callback( $re, $cb, $s, $n, $count );
|
$s2 = preg_replace_callback( $re, $cb, $s, $n, $count );
|
||||||
|
if ( $s2 === null ) {
|
||||||
|
self::handlePCREError( preg_last_error(), $pattern );
|
||||||
|
}
|
||||||
return array( $s2, $count );
|
return array( $s2, $count );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle a PCRE error
|
||||||
|
* @param int $error From preg_last_error()
|
||||||
|
* @param string $pattern Pattern being matched
|
||||||
|
* @throws Scribunto_LuaError
|
||||||
|
*/
|
||||||
|
private function handlePCREError( $error, $pattern ) {
|
||||||
|
$PREG_JIT_STACKLIMIT_ERROR = defined( 'PREG_JIT_STACKLIMIT_ERROR' )
|
||||||
|
? PREG_JIT_STACKLIMIT_ERROR
|
||||||
|
: 'PREG_JIT_STACKLIMIT_ERROR';
|
||||||
|
|
||||||
|
$error = preg_last_error();
|
||||||
|
switch ( $error ) {
|
||||||
|
case PREG_NO_ERROR:
|
||||||
|
// Huh?
|
||||||
|
break;
|
||||||
|
case PREG_INTERNAL_ERROR:
|
||||||
|
throw new Scribunto_LuaError( "PCRE internal error" );
|
||||||
|
case PREG_BACKTRACK_LIMIT_ERROR:
|
||||||
|
throw new Scribunto_LuaError(
|
||||||
|
"PCRE backtrack limit reached while matching pattern '$pattern'"
|
||||||
|
);
|
||||||
|
case PREG_RECURSION_LIMIT_ERROR:
|
||||||
|
throw new Scribunto_LuaError(
|
||||||
|
"PCRE recursion limit reached while matching pattern '$pattern'"
|
||||||
|
);
|
||||||
|
case PREG_BAD_UTF8_ERROR:
|
||||||
|
// Should have alreay been caught, but just in case
|
||||||
|
throw new Scribunto_LuaError( "PCRE bad UTF-8 error" );
|
||||||
|
case PREG_BAD_UTF8_OFFSET_ERROR:
|
||||||
|
// Shouldn't happen, but just in case
|
||||||
|
throw new Scribunto_LuaError( "PCRE bad UTF-8 offset error" );
|
||||||
|
case $PREG_JIT_STACKLIMIT_ERROR:
|
||||||
|
throw new Scribunto_LuaError(
|
||||||
|
"PCRE JIT stack limit reached while matching pattern '$pattern'"
|
||||||
|
);
|
||||||
|
default:
|
||||||
|
throw new Scribunto_LuaError(
|
||||||
|
"PCRE error code $error while matching pattern '$pattern'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,4 +18,18 @@ class Scribunto_LuaUstringLibraryPureLuaTests extends Scribunto_LuaUstringLibrar
|
||||||
', 'fortest' )
|
', 'fortest' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providePCREErrors
|
||||||
|
*/
|
||||||
|
public function testPCREErrors( $ini, $args, $error ) {
|
||||||
|
// Not applicable
|
||||||
|
$this->assertTrue( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function providePCREErrors() {
|
||||||
|
return array(
|
||||||
|
array( array(), array(), null ),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,6 +60,43 @@ class Scribunto_LuaUstringLibraryTests extends Scribunto_LuaEngineTestBase {
|
||||||
$this->assertSame( $expected, $actual );
|
$this->assertSame( $expected, $actual );
|
||||||
$this->luaTestName = null;
|
$this->luaTestName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider providePCREErrors
|
||||||
|
*/
|
||||||
|
public function testPCREErrors( $ini, $args, $error ) {
|
||||||
|
$reset = array();
|
||||||
|
foreach ( $ini as $key => $value ) {
|
||||||
|
$old = ini_set( $key, $value );
|
||||||
|
if ( $old === false ) {
|
||||||
|
$this->markTestSkipped( "Failed to set ini setting $key = $value" );
|
||||||
|
}
|
||||||
|
$reset[] = new ScopedCallback( 'ini_set', array( $key, $old ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
$interpreter = $this->getEngine()->getInterpreter();
|
||||||
|
$func = $interpreter->loadString( 'return mw.ustring.gsub( ... )', 'fortest' );
|
||||||
|
try {
|
||||||
|
call_user_func_array(
|
||||||
|
array( $interpreter, 'callFunction' ),
|
||||||
|
array_merge( array( $func ), $args )
|
||||||
|
);
|
||||||
|
$this->fail( 'Expected exception not thrown' );
|
||||||
|
} catch ( Scribunto_LuaError $e ) {
|
||||||
|
$this->assertSame( $error, $e->getMessage() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function providePCREErrors() {
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
array( 'pcre.backtrack_limit' => 10 ),
|
||||||
|
array( 'zzzzzzzzzzzzzzzzzzzz', '^(.-)[abc]*$', '%1' ),
|
||||||
|
'Lua error: PCRE backtrack limit reached while matching pattern \'^(.-)[abc]*$\'.'
|
||||||
|
),
|
||||||
|
// @TODO: Figure out patterns that hit other PCRE limits
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UstringLibraryNormalizationTestProvider extends Scribunto_LuaDataProvider {
|
class UstringLibraryNormalizationTestProvider extends Scribunto_LuaDataProvider {
|
||||||
|
|
Loading…
Reference in a new issue