[php-src] master: Guard uninitialized SplFileObject in fputcsv() and next()
Ilia Alshanetsky <[email protected]>
| Newsgroups | gmane.comp.php.cvs.general |
|---|---|
| Message-ID | <[email protected]> |
Author: Ilia Alshanetsky (iliaal)
Date: 2026-06-25T18:14:24-04:00
Commit: https://github.com/php/php-src/commit/60d8e92ed4a0c1b310a81103f3b423713aece6c8
Raw diff: https://github.com/php/php-src/commit/60d8e92ed4a0c1b310a81103f3b423713aece6c8.diff
Guard uninitialized SplFileObject in fputcsv() and next()
fputcsv() and next() reached the file stream without the
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED guard their siblings carry, so
invoking them via reflection on an object from
newInstanceWithoutConstructor() (constructor bypassed, stream NULL)
crashed instead of throwing. next() only touches the stream with the
READ_AHEAD flag, itself settable through the equally unguarded
setFlags(). Both now throw "Object not initialized".
Fixes GH-16217
Closes GH-22454
Changed paths:
A ext/spl/tests/gh16217.phpt
M NEWS
M ext/spl/spl_directory.c
Diff:
diff --git a/NEWS b/NEWS
index 7dd1aea4b881..39f2359152f0 100644
--- a/NEWS
+++ b/NEWS
@@ -24,6 +24,8 @@ PHP NEWS
(jorgsowa)
. Ignore leading back-slash in class_parents(), class_implements(), and
class_uses(). (jorgsowa)
+ . Fixed bug GH-16217 (SplFileObject::fputcsv() on an uninitialized object
+ segfaults). (iliaal)
- Standard:
. Fixed bug GH-22360 (convert.base64-encode corruption on
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index f83ea9f84aca..eb3fb8caef64 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -2224,6 +2224,8 @@ PHP_METHOD(SplFileObject, next)
RETURN_THROWS();
}
+ CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
+
spl_filesystem_file_free_line(intern);
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
spl_filesystem_file_read_line(ZEND_THIS, intern, true);
@@ -2376,6 +2378,8 @@ PHP_METHOD(SplFileObject, fputcsv)
RETURN_THROWS();
}
+ CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
+
if (delim) {
if (d_len != 1) {
zend_argument_value_error(2, "must be a single character");
diff --git a/ext/spl/tests/gh16217.phpt b/ext/spl/tests/gh16217.phpt
new file mode 100644
index 000000000000..71760389c8e4
--- /dev/null
+++ b/ext/spl/tests/gh16217.phpt
@@ -0,0 +1,35 @@
+--TEST--
+GH-16217 (SplFileObject methods on an uninitialized object segfault)
+--FILE--
+<?php
+function uninitialized(): SplFileObject {
+ return (new ReflectionClass(SplFileObject::class))->newInstanceWithoutConstructor();
+}
+
+try {
+ (new ReflectionMethod(SplFileObject::class, "fputcsv"))->invoke(uninitialized(), []);
+} catch (Error $e) {
+ echo "fputcsv: ", $e->getMessage(), "\n";
+}
+
+try {
+ (new ReflectionMethod(SplFileObject::class, "next"))->invoke(uninitialized());
+} catch (Error $e) {
+ echo "next: ", $e->getMessage(), "\n";
+}
+
+$obj = uninitialized();
+(new ReflectionMethod(SplFileObject::class, "setFlags"))->invoke($obj, SplFileObject::READ_AHEAD);
+try {
+ (new ReflectionMethod(SplFileObject::class, "next"))->invoke($obj);
+} catch (Error $e) {
+ echo "next (READ_AHEAD): ", $e->getMessage(), "\n";
+}
+
+echo "Done\n";
+?>
+--EXPECT--
+fputcsv: Object not initialized
+next: Object not initialized
+next (READ_AHEAD): Object not initialized
+Done