Anomie has uploaded a new change for review. https://gerrit.wikimedia.org/r/279377
Change subject: Add handling for PCRE errors in ustringGsub ...................................................................... Add handling for PCRE errors in ustringGsub Bug: T130823 Change-Id: I6fab71c82ddab92daf6b369cb9857d9892f2d246 --- M engines/LuaCommon/UstringLibrary.php M tests/engines/LuaCommon/UstringLibraryPureLuaTest.php M tests/engines/LuaCommon/UstringLibraryTest.php 3 files changed, 97 insertions(+), 0 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/Scribunto refs/changes/77/279377/1 diff --git a/engines/LuaCommon/UstringLibrary.php b/engines/LuaCommon/UstringLibrary.php index bef0761..ec845d8 100644 --- a/engines/LuaCommon/UstringLibrary.php +++ b/engines/LuaCommon/UstringLibrary.php @@ -672,6 +672,52 @@ $count = 0; $s2 = preg_replace_callback( $re, $cb, $s, $n, $count ); + if ( $s2 === null ) { + self::handlePCREError( preg_last_error(), $pattern ); + } 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'" + ); + } + } } diff --git a/tests/engines/LuaCommon/UstringLibraryPureLuaTest.php b/tests/engines/LuaCommon/UstringLibraryPureLuaTest.php index 141996d..f1109f8 100644 --- a/tests/engines/LuaCommon/UstringLibraryPureLuaTest.php +++ b/tests/engines/LuaCommon/UstringLibraryPureLuaTest.php @@ -17,4 +17,18 @@ ', 'fortest' ) ); } + + /** + * @dataProvider providePCREErrors + */ + public function testPCREErrors($ini, $args, $error) { + // Not applicable + $this->assertTrue( true ); + } + + public static function providePCREErrors() { + return array( + array( array(), array(), null ), + ); + } } diff --git a/tests/engines/LuaCommon/UstringLibraryTest.php b/tests/engines/LuaCommon/UstringLibraryTest.php index 3e24a5d..99576a0 100644 --- a/tests/engines/LuaCommon/UstringLibraryTest.php +++ b/tests/engines/LuaCommon/UstringLibraryTest.php @@ -53,6 +53,43 @@ $this->assertSame( $expected, $actual ); $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 { -- To view, visit https://gerrit.wikimedia.org/r/279377 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I6fab71c82ddab92daf6b369cb9857d9892f2d246 Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/extensions/Scribunto Gerrit-Branch: master Gerrit-Owner: Anomie <bjor...@wikimedia.org> _______________________________________________ MediaWiki-commits mailing list MediaWiki-commits@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits