Fix GH-9883 SplFileObject::__toString() reads next line

We need to overwrite the __toString magic method for SplFileObject, similarly to how DirectoryIterator overwrites it
Moreover, the custom cast handler is useless as we define __toString methods, so use the standard one instead.

Closes GH-9912
This commit is contained in:
George Peter Banyard 2022-11-09 15:24:30 +00:00
parent aee1a2f4c0
commit 6fbf81c674
No known key found for this signature in database
GPG Key ID: 3306078E3194AEBD
6 changed files with 57 additions and 32 deletions

3
NEWS
View File

@ -21,6 +21,9 @@ PHP NEWS
- Session:
. Fixed GH-9932 (session name silently fails with . and [). (David Carlier)
- SPL:
. Fixed GH-9883 (SplFileObject::__toString() reads next line). (Girgias)
24 Nov 2022, PHP 8.1.13
- CLI:

View File

@ -1836,34 +1836,6 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva
}
/* }}} */
/* {{{ spl_filesystem_object_cast */
static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int type)
{
spl_filesystem_object *intern = spl_filesystem_from_obj(readobj);
if (type == IS_STRING) {
if (readobj->ce->__tostring) {
return zend_std_cast_object_tostring(readobj, writeobj, type);
}
switch (intern->type) {
case SPL_FS_INFO:
case SPL_FS_FILE:
ZVAL_STR_COPY(writeobj, intern->file_name);
return SUCCESS;
case SPL_FS_DIR:
ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
return SUCCESS;
}
} else if (type == _IS_BOOL) {
ZVAL_TRUE(writeobj);
return SUCCESS;
}
ZVAL_NULL(writeobj);
return FAILURE;
}
/* }}} */
static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bool silent, zend_long line_add) /* {{{ */
{
char *buf;
@ -2744,6 +2716,23 @@ PHP_METHOD(SplFileObject, seek)
}
} /* }}} */
PHP_METHOD(SplFileObject, __toString)
{
if (zend_parse_parameters_none() == FAILURE) {
RETURN_THROWS();
}
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
spl_filesystem_file_read_line(ZEND_THIS, intern, 1);
}
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
}
/* {{{ PHP_MINIT_FUNCTION(spl_directory) */
PHP_MINIT_FUNCTION(spl_directory)
{
@ -2753,7 +2742,6 @@ PHP_MINIT_FUNCTION(spl_directory)
memcpy(&spl_filesystem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object;
spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;

View File

@ -293,7 +293,6 @@ class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIt
*/
public function getCurrentLine(): string {}
/** @implementation-alias SplFileObject::fgets */
public function __toString(): string {}
}

View File

@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 3f2caf1c46760d8ef629ccb2e94ab0dba09f713b */
* Stub hash: c8e8093692f8a4642ea7c840e301f1afed599ee1 */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SplFileInfo___construct, 0, 0, 1)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
@ -360,6 +360,7 @@ ZEND_METHOD(SplFileObject, getMaxLineLen);
ZEND_METHOD(SplFileObject, hasChildren);
ZEND_METHOD(SplFileObject, getChildren);
ZEND_METHOD(SplFileObject, seek);
ZEND_METHOD(SplFileObject, __toString);
ZEND_METHOD(SplTempFileObject, __construct);
@ -480,7 +481,7 @@ static const zend_function_entry class_SplFileObject_methods[] = {
ZEND_ME(SplFileObject, getChildren, arginfo_class_SplFileObject_getChildren, ZEND_ACC_PUBLIC)
ZEND_ME(SplFileObject, seek, arginfo_class_SplFileObject_seek, ZEND_ACC_PUBLIC)
ZEND_MALIAS(SplFileObject, getCurrentLine, fgets, arginfo_class_SplFileObject_getCurrentLine, ZEND_ACC_PUBLIC)
ZEND_MALIAS(SplFileObject, __toString, fgets, arginfo_class_SplFileObject___toString, ZEND_ACC_PUBLIC)
ZEND_ME(SplFileObject, __toString, arginfo_class_SplFileObject___toString, ZEND_ACC_PUBLIC)
ZEND_FE_END
};

View File

@ -0,0 +1,14 @@
--TEST--
Bug GH-9883 (SplFileObject::__toString() reads next line)
--FILE--
<?php
$file_stream = new SplTempFileObject();
echo $file_stream; // line 4
echo $file_stream; // line 5
echo $file_stream; // line 6
echo $file_stream; // line 7
echo $file_stream; // line 8
echo $file_stream; // line 9
?>
--EXPECT--

20
ext/spl/tests/gh9883.phpt Normal file
View File

@ -0,0 +1,20 @@
--TEST--
Bug GH-9883 (SplFileObject::__toString() reads next line)
--FILE--
<?php
$file_stream = new SplFileObject(__FILE__, 'rb');
echo $file_stream; // line 4
echo $file_stream; // line 5
echo $file_stream; // line 6
echo $file_stream; // line 7
echo $file_stream; // line 8
echo $file_stream; // line 9
?>
--EXPECT--
<?php
<?php
<?php
<?php
<?php
<?php