[php-src] PR #23483: Fix fseek() accepting $whence values that do not fit in an int

From: Date: Thu, 27 Aug 2026 20:19:55 +0000
Subject: [php-src] PR #23483: Fix fseek() accepting $whence values that do not fit in an int
Groups: php.git-pulls 
Request: Send a blank email to git-pulls+get-38174@lists.php.net to get a copy of this message
Pull Request: https://github.com/php/php-src/pull/23483 Author: lacatoire fseek() parses $whence as a zend_long, but casts it to a C int when calling php_stream_seek(). Values whose low 32 bits alias onto a valid seek constant are accepted and acted upon. On a 64-bit build, with a 10-byte file and the cursor at 4: ``` fseek($h, 3, SEEK_CUR + 2**32) => 0 position 7 (treated as SEEK_CUR) fseek($h, 3, PHP_INT_MIN) => 0 position 3 (treated as SEEK_SET) fseek($h, 3, SEEK_END + 2**32) => 0 position 13 (treated as SEEK_END) ``` A return value of 0 means success, so the call reports that a seek nobody asked for went through. The fix rejects values outside the int range before the cast: ```c if (whence < INT_MIN || whence > INT_MAX) { RETURN_LONG(-1); } ``` -1 is not a new convention: it is already what fseek() returns for an invalid $whence that happens to fit in an int, and the position is left untouched in both cases. ``` fseek($h, 3, 99) => -1 position unchanged ``` Platform constants such as SEEK_DATA (3) and SEEK_HOLE (4) fit in an int and are unaffected. ext/standard/tests/file/fseek_whence_overflow.phpt covers the three aliasing forms and a plain SEEK_CUR as a regression guard. It skips on 32-bit builds, where no zend_long can exceed an int. Tested on a 64-bit Linux build: the new test passes, and ext/standard/tests/file, ext/standard/tests/streams and ext/standard/tests/filters show no regression.

« previous php.git-pulls (#38174) next »