1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-21 21:31:13 +01:00

Fix integer overflow in array keys

Fixes vimeo/psalm#9498
This commit is contained in:
Bruce Weirdan 2023-03-12 16:13:40 -04:00
parent 47c482188d
commit 103aa019da
No known key found for this signature in database
GPG Key ID: CFC3AAB181751B0D
3 changed files with 85 additions and 3 deletions

View File

@ -333,7 +333,9 @@ class ArrayAnalyzer
} elseif ($key_type->isSingleIntLiteral()) {
$item_key_value = $key_type->getSingleIntLiteral()->value;
if ($item_key_value >= $array_creation_info->int_offset) {
if ($item_key_value < PHP_INT_MAX
&& $item_key_value >= $array_creation_info->int_offset
) {
if ($item_key_value === $array_creation_info->int_offset) {
$item_is_list_item = true;
}

View File

@ -663,8 +663,22 @@ class TKeyedArray extends Atomic
*/
private function escapeAndQuote($name)
{
if (is_string($name) && ($name === '' || preg_match('/[^a-zA-Z0-9_]/', $name))) {
$name = '\'' . str_replace("\n", '\n', addslashes($name)) . '\'';
if (is_string($name)) {
$quote = false;
if ($name === '' || preg_match('/[^a-zA-Z0-9_]/', $name)) {
$quote = true;
}
if (preg_match('/^[1-9][0-9]*$/', $name)
&& (string)(int) $name !== $name // overflow occured
) {
$quote = true;
}
if ($quote) {
$name = '\'' . str_replace("\n", '\n', addslashes($name)) . '\'';
}
}
return $name;

66
tests/ExpressionTest.php Normal file
View File

@ -0,0 +1,66 @@
<?php
namespace Psalm\Tests;
use Psalm\Tests\Traits\InvalidCodeAnalysisTestTrait;
use Psalm\Tests\Traits\ValidCodeAnalysisTestTrait;
class ExpressionTest extends TestCase
{
use ValidCodeAnalysisTestTrait;
use InvalidCodeAnalysisTestTrait;
/**
* @return iterable<
* string,
* array{
* code: string,
* assertions?: array<string, string>,
* ignored_issues?: list<string>,
* php_version?: string,
* }
* >
*/
public function providerValidCodeParse(): iterable
{
yield 'maxIntegerInArrayKey' => [
'code' => <<<'PHP'
<?php
// PHP_INT_MAX
$s = ['9223372036854775807' => 1];
$i = [9223372036854775807 => 1];
// PHP_INT_MAX + 1
$so = ['9223372036854775808' => 1];
PHP,
'assertions' => [
'$s===' => 'array{9223372036854775807: 1}',
'$i===' => 'array{9223372036854775807: 1}',
'$so===' => "array{'9223372036854775808': 1}",
],
];
}
/**
* @return iterable<
* string,
* array{
* code: string,
* error_message: string,
* ignored_issues?: list<string>,
* php_version?: string,
* }
* >
*/
public function providerInvalidCodeParse(): iterable
{
yield 'integerOverflowInArrayKey' => [
'code' => <<<'PHP'
<?php
// PHP_INT_MAX + 1
[9223372036854775808 => 1];
PHP,
'error_message' => 'InvalidArrayOffset',
];
}
}