Skip to content

Commit db7ff5a

Browse files
committed
Fix GH-8561 and GH-8562
These bugs need a header change, and thus are an ABI break
1 parent 52e9b1c commit db7ff5a

File tree

4 files changed

+66
-5
lines changed

4 files changed

+66
-5
lines changed

ext/spl/spl_directory.c

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2047,10 +2047,12 @@ static void spl_filesystem_file_rewind(zval * this_ptr, spl_filesystem_object *i
20472047
}
20482048
if (-1 == php_stream_rewind(intern->u.file.stream)) {
20492049
zend_throw_exception_ex(spl_ce_RuntimeException, 0, "Cannot rewind file %s", ZSTR_VAL(intern->file_name));
2050-
} else {
2051-
spl_filesystem_file_free_line(intern);
2052-
intern->u.file.current_line_num = 0;
2050+
return;
20532051
}
2052+
2053+
spl_filesystem_file_free_line(intern);
2054+
intern->u.file.current_line_num = 0;
2055+
intern->u.file.lines_to_catch_up = 0;
20542056
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
20552057
spl_filesystem_file_read_line(this_ptr, intern, /* silent */ true);
20562058
}
@@ -2191,6 +2193,8 @@ PHP_METHOD(SplFileObject, fgets)
21912193
if (spl_filesystem_file_read_ex(intern, /* silent */ false, /* line_add */ 1) == FAILURE) {
21922194
RETURN_THROWS();
21932195
}
2196+
/* Inform current() that it needs to catch up a line */
2197+
intern->u.file.lines_to_catch_up++;
21942198
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
21952199
} /* }}} */
21962200

@@ -2205,9 +2209,19 @@ PHP_METHOD(SplFileObject, current)
22052209

22062210
CHECK_SPL_FILE_OBJECT_IS_INITIALIZED(intern);
22072211

2212+
/* No lines have been read yet (rewind or just opened file) */
22082213
if (!intern->u.file.current_line && Z_ISUNDEF(intern->u.file.current_zval)) {
22092214
spl_filesystem_file_read_line(ZEND_THIS, intern, /* silent */ true);
22102215
}
2216+
/* next() of fgets() has been called and we need to read the line which is now pointed at */
2217+
if (intern->u.file.lines_to_catch_up > 0) {
2218+
ZEND_ASSERT(intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval));
2219+
for (; 0 < intern->u.file.lines_to_catch_up; intern->u.file.lines_to_catch_up--) {
2220+
/* Free fetched line */
2221+
spl_filesystem_file_free_line(intern);
2222+
spl_filesystem_file_read_line(ZEND_THIS, intern, /* silent */ true);
2223+
}
2224+
}
22112225
if (intern->u.file.current_line && (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || Z_ISUNDEF(intern->u.file.current_zval))) {
22122226
RETURN_STRINGL(intern->u.file.current_line, intern->u.file.current_line_len);
22132227
} else if (!Z_ISUNDEF(intern->u.file.current_zval)) {
@@ -2242,9 +2256,11 @@ PHP_METHOD(SplFileObject, next)
22422256
RETURN_THROWS();
22432257
}
22442258

2245-
spl_filesystem_file_free_line(intern);
22462259
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2260+
spl_filesystem_file_free_line(intern);
22472261
spl_filesystem_file_read_line(ZEND_THIS, intern, /* silent */ true);
2262+
} else {
2263+
intern->u.file.lines_to_catch_up++;
22482264
}
22492265
intern->u.file.current_line_num++;
22502266
} /* }}} */

ext/spl/spl_directory.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ struct _spl_filesystem_object {
8585
char *current_line;
8686
size_t current_line_len;
8787
size_t max_line_len;
88-
zend_long current_line_num;
88+
zend_long current_line_num;
89+
zend_long lines_to_catch_up;
8990
zval zresource;
9091
zend_function *func_getCurr;
9192
char delimiter;
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug GH-8561: SplFileObject: key() and current() unsinchronized after call to fgets()
3+
--FILE--
4+
<?php
5+
$file = new SplTempFileObject();
6+
7+
// write to file
8+
for ($i = 0; $i < 5; $i++) {
9+
$file->fwrite("line {$i}" . PHP_EOL);
10+
}
11+
12+
$file->rewind();
13+
14+
// read first line
15+
$file->fgets();
16+
17+
// where am I?
18+
echo $file->key(), ': ', $file->current();
19+
20+
?>
21+
--EXPECT--
22+
1: line 1
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug GH-8562: SplFileObject: current() returns wrong result after call to next()
3+
--FILE--
4+
<?php
5+
$file = new SplTempFileObject();
6+
7+
// write to file
8+
for ($i = 0; $i < 5; $i++) {
9+
$file->fwrite("line {$i}" . PHP_EOL);
10+
}
11+
12+
$file->rewind();
13+
14+
$file->next();
15+
echo $file->key(), ': ', $file->current();
16+
$file->next();
17+
echo $file->key(), ': ', $file->current();
18+
19+
?>
20+
--EXPECT--
21+
1: line 1
22+
2: line 2

0 commit comments

Comments
 (0)