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

[email protected] (lacatoire)
Newsgroups php.git-pulls
Message-ID <[email protected]>
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.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.