Skip to content

Commit eaec347

Browse files
Fix GH-19942: avoid infinite loop when using iterator_count() on an empty SplFileObject
1 parent 68d5ddb commit eaec347

File tree

3 files changed

+35
-0
lines changed

3 files changed

+35
-0
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ PHP NEWS
2727
of the curl_copy_handle() function to clone a CurlHandle. (timwolla)
2828
. Fix curl build failure on macOS+curl 8.16. (nielsdos)
2929

30+
- SPL:
31+
. Fixed bug GH-19942 (iterator_count() on an empty SplFileObject looping
32+
infinitely). (alexandre-daubois)
33+
3034
- Soap:
3135
. Fixed bug GH-19784 (SoapServer memory leak). (nielsdos)
3236

ext/spl/spl_directory.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,21 @@ PHP_METHOD(SplFileObject, valid)
21662166
if (!intern->u.file.stream) {
21672167
RETURN_FALSE;
21682168
}
2169+
2170+
/* For empty files, php_stream_eof() might not return TRUE until after a read attempt.
2171+
* If we're at the beginning and haven't read anything, check EOF directly after ensuring
2172+
* a read has been attempted. */
2173+
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval) &&
2174+
intern->u.file.current_line_num == 0) {
2175+
2176+
zend_off_t pos = php_stream_tell(intern->u.file.stream);
2177+
if (php_stream_getc(intern->u.file.stream) == EOF) {
2178+
RETURN_FALSE;
2179+
}
2180+
2181+
php_stream_seek(intern->u.file.stream, pos, SEEK_SET);
2182+
}
2183+
21692184
RETURN_BOOL(!php_stream_eof(intern->u.file.stream));
21702185
} /* }}} */
21712186

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
GH-19942 (iterator_count() on an empty SplFileObject should return 0)
3+
--FILE--
4+
<?php
5+
$tmpfile = tempnam(sys_get_temp_dir(), 'spl_empty_test');
6+
touch($tmpfile);
7+
8+
$fileObject = new SplFileObject($tmpfile, 'r');
9+
$count = iterator_count($fileObject);
10+
11+
var_dump($count);
12+
13+
unlink($tmpfile);
14+
?>
15+
--EXPECT--
16+
int(0)

0 commit comments

Comments
 (0)