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

Reply via email to