Skip to content

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

Closed
iliaal wants to merge 10000 commits intomasterfrom
fix/gh-20964-fseek-ubsan
Closed

Fix GH-20964: fseek() stream seek with PHP_INT_MIN causes undefined behavior#1
iliaal wants to merge 10000 commits intomasterfrom
fix/gh-20964-fseek-ubsan

Conversation

@iliaal
Copy link
Owner

@iliaal iliaal commented Mar 13, 2026

Summary

php_stream_memory_seek() (and equivalent functions in 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 PR

PR php#20965 takes a different approach (rejects ZEND_LONG_MIN with a ValueError). This patch is simpler -- it fixes the UB without changing behavior.

Fixes php#20964

Loading
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.

UBSAN: fseek() on php://memory with PHP_INT_MIN causes undefined behavior