-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Fix GH-19942: avoid infinite loop when using iterator_count() on an empty SplFileObject #19957
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: PHP-8.3
Are you sure you want to change the base?
Fix GH-19942: avoid infinite loop when using iterator_count() on an empty SplFileObject #19957
Conversation
5d86b6c
to
eaec347
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks reasonable
Will this break for non-seekable file streams? |
eaec347
to
c80b777
Compare
Good catch, I added checks to only perform this on seekable streams + a test to cover it. |
…n empty SplFileObject
c80b777
to
4b81bba
Compare
a heads-up: This isn't just happening for empty files. <?php
file_put_contents('/tmp/file', "a\n");
var_dump(iterator_count(new SplFileObject("/tmp/file", "r"))); Testing it now. |
Right indeed. php-src/ext/spl/spl_directory.c Lines 2209 to 2212 in 80e4278
because this isn't set, the current stream offset never advances and therefore EOF is never reached. This causes the infinite loop. |
This also means btw that calling SplFileObject::valid() after seeking can give erroneous results. I think we should attempt to make a read (which would solve both issues, although I'm not sure if this gives the right results and what consequences are): diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index a769d627a54..b4c643d9f54 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -2118,6 +2118,7 @@ PHP_METHOD(SplFileObject, eof)
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
+ // TODO: should this be consistent with valid() ?
RETURN_BOOL(php_stream_eof(intern->u.file.stream));
} /* }}} */
@@ -2136,6 +2137,10 @@ PHP_METHOD(SplFileObject, valid)
if (!intern->u.file.stream) {
RETURN_FALSE;
}
+ /* If there is no current line, we might've seeked, so we need to attempt a read. */
+ if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
+ spl_filesystem_file_read_line(ZEND_THIS, intern, true);
+ }
RETURN_BOOL(!php_stream_eof(intern->u.file.stream));
} /* }}} */
|
No description provided.