Skip to content

Commit e595885

Browse files
committed
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.
1 parent ac50830 commit e595885

File tree

5 files changed

+55
-32
lines changed

5 files changed

+55
-32
lines changed

ext/spl/spl_directory.c

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1828,34 +1828,6 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva
18281828
}
18291829
/* }}} */
18301830

1831-
/* {{{ spl_filesystem_object_cast */
1832-
static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int type)
1833-
{
1834-
spl_filesystem_object *intern = spl_filesystem_from_obj(readobj);
1835-
1836-
if (type == IS_STRING) {
1837-
if (readobj->ce->__tostring) {
1838-
return zend_std_cast_object_tostring(readobj, writeobj, type);
1839-
}
1840-
1841-
switch (intern->type) {
1842-
case SPL_FS_INFO:
1843-
case SPL_FS_FILE:
1844-
ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len);
1845-
return SUCCESS;
1846-
case SPL_FS_DIR:
1847-
ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
1848-
return SUCCESS;
1849-
}
1850-
} else if (type == _IS_BOOL) {
1851-
ZVAL_TRUE(writeobj);
1852-
return SUCCESS;
1853-
}
1854-
ZVAL_NULL(writeobj);
1855-
return FAILURE;
1856-
}
1857-
/* }}} */
1858-
18591831
static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bool silent, zend_long line_add) /* {{{ */
18601832
{
18611833
char *buf;
@@ -2750,14 +2722,31 @@ PHP_METHOD(SplFileObject, seek)
27502722
}
27512723
} /* }}} */
27522724

2725+
PHP_METHOD(SplFileObject, __toString)
2726+
{
2727+
if (zend_parse_parameters_none() == FAILURE) {
2728+
RETURN_THROWS();
2729+
}
2730+
2731+
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
2732+
2733+
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
2734+
2735+
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
2736+
spl_filesystem_file_read_line(ZEND_THIS, intern, 1);
2737+
}
2738+
2739+
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
2740+
}
2741+
27532742
/* {{{ PHP_MINIT_FUNCTION(spl_directory) */
27542743
PHP_MINIT_FUNCTION(spl_directory)
27552744
{
27562745
REGISTER_SPL_STD_CLASS_EX(SplFileInfo, spl_filesystem_object_new, class_SplFileInfo_methods);
27572746
memcpy(&spl_filesystem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
27582747
spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
27592748
spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
2760-
spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
2749+
spl_filesystem_object_handlers.cast_object = zend_std_cast_object_tostring;
27612750
spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object;
27622751
spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;
27632752
spl_ce_SplFileInfo->serialize = zend_class_serialize_deny;

ext/spl/spl_directory.stub.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,6 @@ public function seek(int $line) {}
286286
*/
287287
public function getCurrentLine() {}
288288

289-
/** @implementation-alias SplFileObject::fgets */
290289
public function __toString(): string {}
291290
}
292291

ext/spl/spl_directory_arginfo.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* This is a generated file, edit the .stub.php file instead.
2-
* Stub hash: d9110bb238c9edb5c013bd482649ed96e24ff7b6 */
2+
* Stub hash: d60261a3b0678ccb1184e67dd99a57014ecf5c3e */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SplFileInfo___construct, 0, 0, 1)
55
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
@@ -342,6 +342,7 @@ ZEND_METHOD(SplFileObject, getMaxLineLen);
342342
ZEND_METHOD(SplFileObject, hasChildren);
343343
ZEND_METHOD(SplFileObject, getChildren);
344344
ZEND_METHOD(SplFileObject, seek);
345+
ZEND_METHOD(SplFileObject, __toString);
345346
ZEND_METHOD(SplTempFileObject, __construct);
346347

347348

@@ -462,7 +463,7 @@ static const zend_function_entry class_SplFileObject_methods[] = {
462463
ZEND_ME(SplFileObject, getChildren, arginfo_class_SplFileObject_getChildren, ZEND_ACC_PUBLIC)
463464
ZEND_ME(SplFileObject, seek, arginfo_class_SplFileObject_seek, ZEND_ACC_PUBLIC)
464465
ZEND_MALIAS(SplFileObject, getCurrentLine, fgets, arginfo_class_SplFileObject_getCurrentLine, ZEND_ACC_PUBLIC)
465-
ZEND_MALIAS(SplFileObject, __toString, fgets, arginfo_class_SplFileObject___toString, ZEND_ACC_PUBLIC)
466+
ZEND_ME(SplFileObject, __toString, arginfo_class_SplFileObject___toString, ZEND_ACC_PUBLIC)
466467
ZEND_FE_END
467468
};
468469

ext/spl/tests/gh9883-extra.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Bug GH-9883 (SplFileObject::__toString() reads next line)
3+
--FILE--
4+
<?php
5+
$file_stream = new SplTempFileObject();
6+
7+
echo $file_stream; // line 4
8+
echo $file_stream; // line 5
9+
echo $file_stream; // line 6
10+
echo $file_stream; // line 7
11+
echo $file_stream; // line 8
12+
echo $file_stream; // line 9
13+
?>
14+
--EXPECT--

ext/spl/tests/gh9883.phpt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Bug GH-9883 (SplFileObject::__toString() reads next line)
3+
--FILE--
4+
<?php
5+
$file_stream = new SplFileObject(__FILE__, 'rb');
6+
7+
echo $file_stream; // line 4
8+
echo $file_stream; // line 5
9+
echo $file_stream; // line 6
10+
echo $file_stream; // line 7
11+
echo $file_stream; // line 8
12+
echo $file_stream; // line 9
13+
?>
14+
--EXPECT--
15+
<?php
16+
<?php
17+
<?php
18+
<?php
19+
<?php
20+
<?php

0 commit comments

Comments
 (0)