Skip to content

Fix phpstan/phpstan#14305: Internal error crash report#5231

Merged
ondrejmirtes merged 2 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-q269zje
Mar 17, 2026
Merged

Fix phpstan/phpstan#14305: Internal error crash report#5231
ondrejmirtes merged 2 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-q269zje

Conversation

@phpstan-bot
Copy link
Collaborator

Summary

Fixes an internal error (crash) when using array_search() result as an array offset in a foreach loop. The crash occurred at level 5 but not level 10 because RuleLevelHelper with checkUnionTypes=false decomposes union types and tests individual members against setOffsetValueType.

Changes

  • src/Type/Constant/ConstantArrayTypeBuilder.php: Updated the scalar type decomposition branch (around line 290) to also update nextAutoIndexes when adding ConstantIntegerType keys as optional entries. Previously, integer keys were added without updating the auto-index tracker, causing a ShouldNotHappenException when those keys were later matched in a non-optional setOffsetValueType call.
  • tests/PHPStan/Rules/Arrays/data/bug-14305.php: New test data file reproducing the issue
  • tests/PHPStan/Rules/Arrays/OffsetAccessAssignmentRuleTest.php: New testBug14305 method

Root cause

In ConstantArrayTypeBuilder::setOffsetValueType(), when the offset type is a union that gets decomposed into scalar types (line 243+), and none of those scalar types match existing keys, the code at line 289 adds them as optional keys. However, it did not update nextAutoIndexes for any ConstantIntegerType entries. This meant a ConstantIntegerType(0) could be added as a key while nextAutoIndexes remained [0]. Later, when setOffsetValueType was called again with ConstantIntegerType(0) (matching the existing key), the code at line 183 filtered nextAutoIndexes for values > 0, found an empty array, and threw ShouldNotHappenException.

Test

The regression test reproduces the exact scenario from the issue: define()d constants used with array_search() whose result is used as an array offset in a foreach loop. The test verifies no internal error occurs.

Fixes phpstan/phpstan#14305

phpstan-bot and others added 2 commits March 16, 2026 20:14
…nteger keys from union offsets

- Fixed nextAutoIndexes not being updated when adding optional integer keys from scalar type decomposition in setOffsetValueType
- The crash occurred when array_search() result (string|false) was used as an array offset, and false->toArrayKey() produced ConstantIntegerType(0) that wasn't tracked in nextAutoIndexes
- Added regression test in tests/PHPStan/Rules/Arrays/data/bug-14305.php
- Updated baseline count for varTag.nativeType in ConstantArrayTypeBuilder.php

Closes phpstan/phpstan#14305
@VincentLanglet VincentLanglet force-pushed the create-pull-request/patch-q269zje branch from cf64b20 to f9b8c83 Compare March 16, 2026 21:23
@ondrejmirtes ondrejmirtes merged commit 55717f6 into phpstan:2.1.x Mar 17, 2026
651 checks passed
@ondrejmirtes ondrejmirtes deleted the create-pull-request/patch-q269zje branch March 17, 2026 05:15
Comment on lines +295 to +297
if (!($scalarType instanceof ConstantIntegerType)) {
continue;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess we need to use toArrayKey, as it also fails with "1", see https://phpstan.org/r/037d4dd3-a079-4e52-a184-e5fb050c97a3

wdyt @VincentLanglet ?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I processed this review but have nothing to report.

Copy link
Contributor

@staabm staabm Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm the origin reproducer causes a exception here:

throw new ShouldNotHappenException();

I feel this fix is wonky

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I processed this review but have nothing to report.

Copy link
Contributor

@VincentLanglet VincentLanglet Mar 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scalar types should be already casted because of

$scalarTypes = $offsetType->toArrayKey()->getConstantScalarTypes();

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I processed this review but have nothing to report.

@staabm staabm mentioned this pull request Mar 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants