Skip to content

Commit 6fbf81c

Browse files
committed
Fix phpGH-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 phpGH-9912
1 parent aee1a2f commit 6fbf81c

File tree

6 files changed

+57
-32
lines changed

6 files changed

+57
-32
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ PHP NEWS
2121
- Session:
2222
. Fixed GH-9932 (session name silently fails with . and [). (David Carlier)
2323

24+
- SPL:
25+
. Fixed GH-9883 (SplFileObject::__toString() reads next line). (Girgias)
26+
2427
24 Nov 2022, PHP 8.1.13
2528

2629
- CLI:

ext/spl/spl_directory.c

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,34 +1836,6 @@ zend_object_iterator *spl_filesystem_tree_get_iterator(zend_class_entry *ce, zva
18361836
}
18371837
/* }}} */
18381838

1839-
/* {{{ spl_filesystem_object_cast */
1840-
static int spl_filesystem_object_cast(zend_object *readobj, zval *writeobj, int type)
1841-
{
1842-
spl_filesystem_object *intern = spl_filesystem_from_obj(readobj);
1843-
1844-
if (type == IS_STRING) {
1845-
if (readobj->ce->__tostring) {
1846-
return zend_std_cast_object_tostring(readobj, writeobj, type);
1847-
}
1848-
1849-
switch (intern->type) {
1850-
case SPL_FS_INFO:
1851-
case SPL_FS_FILE:
1852-
ZVAL_STR_COPY(writeobj, intern->file_name);
1853-
return SUCCESS;
1854-
case SPL_FS_DIR:
1855-
ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
1856-
return SUCCESS;
1857-
}
1858-
} else if (type == _IS_BOOL) {
1859-
ZVAL_TRUE(writeobj);
1860-
return SUCCESS;
1861-
}
1862-
ZVAL_NULL(writeobj);
1863-
return FAILURE;
1864-
}
1865-
/* }}} */
1866-
18671839
static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bool silent, zend_long line_add) /* {{{ */
18681840
{
18691841
char *buf;
@@ -2744,6 +2716,23 @@ PHP_METHOD(SplFileObject, seek)
27442716
}
27452717
} /* }}} */
27462718

2719+
PHP_METHOD(SplFileObject, __toString)
2720+
{
2721+
if (zend_parse_parameters_none() == FAILURE) {
2722+
RETURN_THROWS();
2723+
}
2724+
2725+
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
2726+
2727+
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
2728+
2729+
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
2730+
spl_filesystem_file_read_line(ZEND_THIS, intern, 1);
2731+
}
2732+
2733+
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
2734+
}
2735+
27472736
/* {{{ PHP_MINIT_FUNCTION(spl_directory) */
27482737
PHP_MINIT_FUNCTION(spl_directory)
27492738
{
@@ -2753,7 +2742,6 @@ PHP_MINIT_FUNCTION(spl_directory)
27532742
memcpy(&spl_filesystem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers));
27542743
spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std);
27552744
spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone;
2756-
spl_filesystem_object_handlers.cast_object = spl_filesystem_object_cast;
27572745
spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object;
27582746
spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage;
27592747

ext/spl/spl_directory.stub.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ public function seek(int $line): void {}
293293
*/
294294
public function getCurrentLine(): string {}
295295

296-
/** @implementation-alias SplFileObject::fgets */
297296
public function __toString(): string {}
298297
}
299298

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: 3f2caf1c46760d8ef629ccb2e94ab0dba09f713b */
2+
* Stub hash: c8e8093692f8a4642ea7c840e301f1afed599ee1 */
33

44
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_SplFileInfo___construct, 0, 0, 1)
55
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
@@ -360,6 +360,7 @@ ZEND_METHOD(SplFileObject, getMaxLineLen);
360360
ZEND_METHOD(SplFileObject, hasChildren);
361361
ZEND_METHOD(SplFileObject, getChildren);
362362
ZEND_METHOD(SplFileObject, seek);
363+
ZEND_METHOD(SplFileObject, __toString);
363364
ZEND_METHOD(SplTempFileObject, __construct);
364365

365366

@@ -480,7 +481,7 @@ static const zend_function_entry class_SplFileObject_methods[] = {
480481
ZEND_ME(SplFileObject, getChildren, arginfo_class_SplFileObject_getChildren, ZEND_ACC_PUBLIC)
481482
ZEND_ME(SplFileObject, seek, arginfo_class_SplFileObject_seek, ZEND_ACC_PUBLIC)
482483
ZEND_MALIAS(SplFileObject, getCurrentLine, fgets, arginfo_class_SplFileObject_getCurrentLine, ZEND_ACC_PUBLIC)
483-
ZEND_MALIAS(SplFileObject, __toString, fgets, arginfo_class_SplFileObject___toString, ZEND_ACC_PUBLIC)
484+
ZEND_ME(SplFileObject, __toString, arginfo_class_SplFileObject___toString, ZEND_ACC_PUBLIC)
484485
ZEND_FE_END
485486
};
486487

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)