Merge "ApiBase: Always validate that 'limit' is numeric"
authorjenkins-bot <jenkins-bot@gerrit.wikimedia.org>
Wed, 4 Sep 2019 15:15:43 +0000 (15:15 +0000)
committerGerrit Code Review <gerrit@wikimedia.org>
Wed, 4 Sep 2019 15:15:43 +0000 (15:15 +0000)
1  2 
includes/api/ApiBase.php
tests/phpunit/includes/api/ApiBaseTest.php

diff --combined includes/api/ApiBase.php
@@@ -274,7 -274,7 +274,7 @@@ abstract class ApiBase extends ContextS
        /** @var array Maps extension paths to info arrays */
        private static $extensionInfo = null;
  
 -      /** @var int[][][] Cache for self::filterIDs() */
 +      /** @var stdClass[][] Cache for self::filterIDs() */
        private static $filterIDsCache = [];
  
        /** $var array Map of web UI block messages to corresponding API messages and codes */
                                                }
                                                break;
                                        case 'limit':
+                                               // Must be a number or 'max'
+                                               if ( $value !== 'max' ) {
+                                                       $value = (int)$value;
+                                               }
+                                               if ( $multi ) {
+                                                       self::dieDebug( __METHOD__, "Multi-values not supported for $encParamName" );
+                                               }
                                                if ( !$parseLimit ) {
-                                                       // Don't do any validation whatsoever
+                                                       // Don't do min/max validation and don't parse 'max'
                                                        break;
                                                }
                                                if ( !isset( $paramSettings[self::PARAM_MAX] )
                                                                "MAX1 or MAX2 are not defined for the limit $encParamName"
                                                        );
                                                }
-                                               if ( $multi ) {
-                                                       self::dieDebug( __METHOD__, "Multi-values not supported for $encParamName" );
-                                               }
-                                               $min = $paramSettings[self::PARAM_MIN] ?? 0;
-                                               if ( $value == 'max' ) {
+                                               if ( $value === 'max' ) {
                                                        $value = $this->getMain()->canApiHighLimits()
                                                                ? $paramSettings[self::PARAM_MAX2]
                                                                : $paramSettings[self::PARAM_MAX];
                                                        $this->getResult()->addParsedLimit( $this->getModuleName(), $value );
                                                } else {
-                                                       $value = (int)$value;
                                                        $this->validateLimit(
                                                                $paramName,
                                                                $value,
-                                                               $min,
+                                                               $paramSettings[self::PARAM_MIN] ?? 0,
                                                                $paramSettings[self::PARAM_MAX],
                                                                $paramSettings[self::PARAM_MAX2]
                                                        );
@@@ -889,10 -889,24 +889,24 @@@ class ApiBaseTest extends ApiTestCase 
                                [],
                                [ 'internalmode' => false ],
                        ],
-                       'Limit with parseLimits false' => [
+                       'Limit with parseLimits false (numeric)' => [
                                '100',
                                [ ApiBase::PARAM_TYPE => 'limit' ],
-                               '100',
+                               100,
+                               [],
+                               [ 'parseLimits' => false ],
+                       ],
+                       'Limit with parseLimits false (max)' => [
+                               'max',
+                               [ ApiBase::PARAM_TYPE => 'limit' ],
+                               'max',
+                               [],
+                               [ 'parseLimits' => false ],
+                       ],
+                       'Limit with parseLimits false (invalid)' => [
+                               'kitten',
+                               [ ApiBase::PARAM_TYPE => 'limit' ],
+                               0,
                                [],
                                [ 'parseLimits' => false ],
                        ],
                                [
                                        ApiBase::PARAM_TYPE => 'limit',
                                        ApiBase::PARAM_MAX2 => 10,
-                                       ApiBase::PARAM_ISMULTI => true,
                                ],
                                new MWException(
                                        'Internal error in ApiBase::getParameterFromSettings: ' .
                                [
                                        ApiBase::PARAM_TYPE => 'limit',
                                        ApiBase::PARAM_MAX => 10,
-                                       ApiBase::PARAM_ISMULTI => true,
                                ],
                                new MWException(
                                        'Internal error in ApiBase::getParameterFromSettings: ' .
                }
  
                $status = StatusValue::newGood();
 -              $status->setOk( false );
 +              $status->setOK( false );
                try {
                        $mock->dieStatus( $status );
                        $this->fail( 'Expected exception not thrown' );