From 23cb0c97b72eb32d109818a64b469fb60beab9c6 Mon Sep 17 00:00:00 2001 From: Richard van Velzen Date: Mon, 20 Jun 2022 13:35:47 +0200 Subject: [PATCH] Prevent crashing for negative bit shifts --- phpstan-baseline.neon | 4 ++-- src/Reflection/InitializerExprTypeResolver.php | 8 ++++++++ tests/PHPStan/Analyser/NodeScopeResolverTest.php | 1 + tests/PHPStan/Analyser/data/bug-7490.php | 10 ++++++++++ 4 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 tests/PHPStan/Analyser/data/bug-7490.php diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 86d1b12543..e433cfdcb6 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -245,12 +245,12 @@ parameters: path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\<\\<\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: "#^Binary operation \"\\<\\<\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\<0, max\\>\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php - - message: "#^Binary operation \"\\>\\>\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\|string\\|null results in an error\\.$#" + message: "#^Binary operation \"\\>\\>\" between bool\\|float\\|int\\|string\\|null and bool\\|float\\|int\\<0, max\\>\\|string\\|null results in an error\\.$#" count: 1 path: src/Reflection/InitializerExprTypeResolver.php diff --git a/src/Reflection/InitializerExprTypeResolver.php b/src/Reflection/InitializerExprTypeResolver.php index 5e2507924d..5067a669cb 100644 --- a/src/Reflection/InitializerExprTypeResolver.php +++ b/src/Reflection/InitializerExprTypeResolver.php @@ -1097,6 +1097,10 @@ public function getShiftLeftType(Expr $left, Expr $right, callable $getTypeCallb throw new ShouldNotHappenException(); } + if ($rightNumberType->getValue() < 0) { + return new ErrorType(); + } + $resultType = $this->getTypeFromValue($leftNumberType->getValue() << $rightNumberType->getValue()); if ($generalize) { $resultType = $resultType->generalize(GeneralizePrecision::lessSpecific()); @@ -1146,6 +1150,10 @@ public function getShiftRightType(Expr $left, Expr $right, callable $getTypeCall throw new ShouldNotHappenException(); } + if ($rightNumberType->getValue() < 0) { + return new ErrorType(); + } + $resultType = $this->getTypeFromValue($leftNumberType->getValue() >> $rightNumberType->getValue()); if ($generalize) { $resultType = $resultType->generalize(GeneralizePrecision::lessSpecific()); diff --git a/tests/PHPStan/Analyser/NodeScopeResolverTest.php b/tests/PHPStan/Analyser/NodeScopeResolverTest.php index 2ad1ac4f6c..c307d19936 100644 --- a/tests/PHPStan/Analyser/NodeScopeResolverTest.php +++ b/tests/PHPStan/Analyser/NodeScopeResolverTest.php @@ -916,6 +916,7 @@ public function dataFileAsserts(): iterable yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7153.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/in-array-non-empty.php'); yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-4117.php'); + yield from $this->gatherAssertTypes(__DIR__ . '/data/bug-7490.php'); } /** diff --git a/tests/PHPStan/Analyser/data/bug-7490.php b/tests/PHPStan/Analyser/data/bug-7490.php new file mode 100644 index 0000000000..db94bd831f --- /dev/null +++ b/tests/PHPStan/Analyser/data/bug-7490.php @@ -0,0 +1,10 @@ +> -1); +};