Skip to content

Fix GH-20964, GH-20927: fseek() stream seek with PHP_INT_MIN causes undefined behavior - #21433

Merged
iliaal merged 1 commit into
php:masterfrom
iliaal:fix/gh-20964-fseek-ubsan
Jun 20, 2026
Merged

Fix GH-20964, GH-20927: fseek() stream seek with PHP_INT_MIN causes undefined behavior#21433
iliaal merged 1 commit into
php:masterfrom
iliaal:fix/gh-20964-fseek-ubsan

Conversation

@iliaal

Copy link
Copy Markdown
Contributor

Summary

Stream seek functions in memory, pdo_sqlite, and sqlite3 compute the absolute value of a negative offset using (size_t)(-offset). When offset == ZEND_LONG_MIN, the signed negation overflows -- undefined behavior caught by UBSAN.

The fix swaps the cast order: -(size_t)offset casts to unsigned first (well-defined), then negates (well-defined unsigned arithmetic). Same result for all values, no behavioral change.

Files changed

  • main/streams/memory.c -- php://memory and php://temp stream seek
  • ext/pdo_sqlite/pdo_sqlite.c -- PDO SQLite blob stream seek
  • ext/sqlite3/sqlite3.c -- SQLite3 blob stream seek

Existing PRs

This patch covers all three affected files.

Fixes#20964
Fixes#20927

…fined behavior
Negate after casting to unsigned instead of before, avoiding signed
integer overflow when offset is ZEND_LONG_MIN. The same pattern existed
in the pdo_sqlite and sqlite3 stream seek handlers.
ClosesphpGH-20964ClosesphpGH-20927
@Girgias

Copy link
Copy Markdown
Member

I think this is fine, but @ndossche you also know the confusing rules around UB a bit better than I do.

@iliaal
iliaal merged commit 5ce795b into php:masterJun 20, 2026
19 checks passed
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

3 participants

@iliaal@Girgias@ndossche