From 6fbf81c6742c5fc7370781270aeb8f4c243c37d1 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Wed, 9 Nov 2022 15:24:30 +0000 Subject: [PATCH] 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 --- NEWS | 3 +++ ext/spl/spl_directory.c | 46 ++++++++++++--------------------- ext/spl/spl_directory.stub.php | 1 - ext/spl/spl_directory_arginfo.h | 5 ++-- ext/spl/tests/gh9883-extra.phpt | 14 ++++++++++ ext/spl/tests/gh9883.phpt | 20 ++++++++++++++ 6 files changed, 57 insertions(+), 32 deletions(-) create mode 100644 ext/spl/tests/gh9883-extra.phpt create mode 100644 ext/spl/tests/gh9883.phpt diff --git a/NEWS b/NEWS index 976f031effe..4a77f3ccbfc 100644 --- a/NEWS +++ b/NEWS @@ -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: diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 4edc6361605..aefa2aa933e 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -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; diff --git a/ext/spl/spl_directory.stub.php b/ext/spl/spl_directory.stub.php index ceb4b7124b5..d734a66fe87 100644 --- a/ext/spl/spl_directory.stub.php +++ b/ext/spl/spl_directory.stub.php @@ -293,7 +293,6 @@ class SplFileObject extends SplFileInfo implements RecursiveIterator, SeekableIt */ public function getCurrentLine(): string {} - /** @implementation-alias SplFileObject::fgets */ public function __toString(): string {} } diff --git a/ext/spl/spl_directory_arginfo.h b/ext/spl/spl_directory_arginfo.h index bcdb51ea542..2b22082875d 100644 --- a/ext/spl/spl_directory_arginfo.h +++ b/ext/spl/spl_directory_arginfo.h @@ -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 }; diff --git a/ext/spl/tests/gh9883-extra.phpt b/ext/spl/tests/gh9883-extra.phpt new file mode 100644 index 00000000000..810cdda42c1 --- /dev/null +++ b/ext/spl/tests/gh9883-extra.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug GH-9883 (SplFileObject::__toString() reads next line) +--FILE-- + +--EXPECT-- diff --git a/ext/spl/tests/gh9883.phpt b/ext/spl/tests/gh9883.phpt new file mode 100644 index 00000000000..22972e6f262 --- /dev/null +++ b/ext/spl/tests/gh9883.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug GH-9883 (SplFileObject::__toString() reads next line) +--FILE-- + +--EXPECT-- +