Skip to content

saturate overflowing numeric string casts - #84

Merged
nvms merged 1 commit into
nvms:mainfrom
vapebw:fix/parse-leading-int-clamp
Sep 15, 2026
Merged

nvms merged 1 commit into
nvms:mainfrom
vapebw:fix/parse-leading-int-clamp

Conversation

@vapebw

@vapebw vapebw commented Sep 15, 2026

Copy link
Copy Markdown
Contributor

In php 8.x, casting a numeric string in float or scientific notation that exceeds the 64-bit integer range to (int) (or via intval()) saturates to PHP_INT_MAX (9223372036854775807) for positive overflow and PHP_INT_MIN (-9223372036854775808) for negative overflow

Previously, Value.parseLeadingInt() in src/runtime/value.zig returned 0 when float strings overflowed max_f, causing incorrect int conversions such as:

  • (int)"1e100" returning 0 instead of 9223372036854775807
  • (int)"-1e100" returning 0 instead of -9223372036854775808
  • (int)"1e19" returning 0 instead of 9223372036854775807
  • (int)"9.9e18" returning 0 instead of 9223372036854775807

While pure integer digit strings (such as (int)"99999999999999999999") already saturated correctly to maxInt(i64) / minInt(i64), the float/exponent path was missing this behavior and returning 0

Solution

  • Clamp positive float overflow (f >= max_f) to std.math.maxInt(i64) in Value.parseLeadingInt
  • Clamp negative float overflow (f <= -max_f) to std.math.minInt(i64) in Value.parseLeadingInt

Tests

  • Added unit tests in src/runtime/value.zig covering positive overflow, negative overflow, boundary values, and in-range float conversions
  • Added parity test in tests/numeric_string_int_saturation.php matching native PHP 8.x behavior

@nvms
nvms merged commit c7296da into nvms:main Sep 15, 2026
20 checks passed
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.

2 participants