diff --git a/src/Core/Validation/InputValidator.php b/src/Core/Validation/InputValidator.php index 203715a5..33bbc94d 100644 --- a/src/Core/Validation/InputValidator.php +++ b/src/Core/Validation/InputValidator.php @@ -180,13 +180,15 @@ class InputValidator { * Filter array to only positive integer IDs * * @param array $ids Input array of IDs - * @return array Filtered array with only positive integer IDs + * @return int[] The positive integer IDs. Callers implode these into SQL + * `IN (...)` lists, so the integer is returned, never the input + * string (`'1) OR (1=1'` passes an intval() > 0 test). */ public static function confirmIDs(array $ids) { $result = []; foreach ($ids as $id) { if (intval($id) > 0) { - $result[] = $id; + $result[] = intval($id); } } return $result; diff --git a/tests/Unit/InputValidatorTest.php b/tests/Unit/InputValidatorTest.php index fb01220e..fe8bc68b 100644 --- a/tests/Unit/InputValidatorTest.php +++ b/tests/Unit/InputValidatorTest.php @@ -28,4 +28,14 @@ final class InputValidatorTest extends TestCase { $result = InputValidator::validateOrFail('processProvider', array('ip' => '127.0.0.1')); $this->assertSame(STATUS_INVALID_INPUT, $result['status']); } + + /** + * Callers implode the result straight into `IN (...)`, so what comes back + * must be the integers, not the strings that merely start with one. + */ + public function testConfirmIdsReturnsIntegers() { + $this->assertSame([5, 12], InputValidator::confirmIDs(['5', '0', '-3', 'abc', '12'])); + $this->assertSame([1], InputValidator::confirmIDs(['1) OR (1=1'])); + $this->assertSame([7], InputValidator::confirmIDs([7])); + } }