Skip to content

Improve return type of base64_decode() - #4492

Merged
ondrejmirtes merged 1 commit into
phpstan:2.3.xfrom
jlherren:jlherren-base64
Nov 1, 2026
Merged

ondrejmirtes merged 1 commit into
phpstan:2.3.xfrom
jlherren:jlherren-base64

Conversation

@jlherren

Copy link
Copy Markdown
Contributor

Fix handling of non-bools as $strict parameter and omit false from return type when $string is valid base64.

This is useful when constant binary strings are required in code, e.g.:

$emptyZipFile = base64_decode('UEsFBgAAAAAAAAAAAAAAAAAAAAAAAA==', true);

Related to phpstan/phpstan#7866

@ondrejmirtes

Copy link
Copy Markdown
Member

This improves things a bit too much as it breaks analysis of PHPStan itself 😀 The base64 call inside the codebase meant to obfuscate a string so that we don't need to baseline related errors. But now we can un-obfuscate it and actually baseline the errors.

$isValidBase64 = TrinaryLogic::lazyExtremeIdentity(
$constantStrings,
static function (ConstantStringType $constantString): TrinaryLogic {
$isValid = base64_decode($constantString->getValue(), true) !== false;

@staabm staabm Jan 27, 2026 •

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

base64-decoding any string from within the codebase could skyrocket memory needed by phpstan analysis.

e.g. some codebases contain multi-megabyte base64 representations of images

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yeah, I'm inclining not doing this at all.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Would a length-limit help?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm really not sure why would we want to decode literal strings passed to this method at all.

- Detect when the result cannot be false
- Correctly treat non-boolean $strict parameter
@ondrejmirtes
ondrejmirtes changed the base branch from 2.1.x to 2.3.x October 31, 2026 13:20
@ondrejmirtes
ondrejmirtes merged commit 567bb79 into phpstan:2.3.x Nov 1, 2026
1033 of 1316 checks passed
@ondrejmirtes

Copy link
Copy Markdown
Member

Thank you!

@staabm

staabm commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

@ondrejmirtes in the discussion above we concluded we likely don't want base64-decode at static analysis time because it can require lots of memory. now the PR got merged.

did you change your opinion or was it merged by mistake?

@ondrejmirtes

Copy link
Copy Markdown
Member

I understood it's not literal input to literal output, just more precise return type than we had before. Was I wrong?

@staabm

staabm commented Nov 2, 2026

Copy link
Copy Markdown
Contributor

I just double checked. PHPStan analyzing a file like https://gist.github.com/staabm/01151e74a45d36d30f5a2d5ad4776f5c (with a 50.000 words long b64-encoded inline literal) takes 2 MB more RAM after this PR

its not as bad as I though initially.

given php-src might get more efficient with base64 in the future it might be good enough.

depends on how big the base64 literal-strings are, which people put into their source files

@jlherren

jlherren commented Nov 2, 2026

Copy link
Copy Markdown
Contributor Author

My two cents: If this remains a concern, perhaps doing preg_match() instead of actually decoding the string will avoid the memory cost. However, that might take more CPU cycles, so it's a trade-off. Another option is still the max length, beyond which no precise analysis is done.

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.

4 participants