Skip to content

Commit 8aa034e

Browse files
committed
Fix #62004: SplFileObject: fgets after seek returns wrong line
As it is, `::seek(0)` sets the file pointer to the beginning of the file, but `::seek($n)` where `$n > 0` sets the file pointer to the beginning of the following line, having line `$n` already read into the line buffer. This is pretty inconsistent; we fix it by always seeking to the beginning of the line.
1 parent 79a606b commit 8aa034e

File tree

5 files changed

+28
-7
lines changed

5 files changed

+28
-7
lines changed

ext/spl/spl_directory.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3011,7 +3011,7 @@ SPL_METHOD(SplFileObject, ftruncate)
30113011
SPL_METHOD(SplFileObject, seek)
30123012
{
30133013
spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS);
3014-
zend_long line_pos;
3014+
zend_long line_pos, i;
30153015

30163016
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) {
30173017
return;
@@ -3028,11 +3028,15 @@ SPL_METHOD(SplFileObject, seek)
30283028

30293029
spl_filesystem_file_rewind(ZEND_THIS, intern);
30303030

3031-
while(intern->u.file.current_line_num < line_pos) {
3031+
for (i = 0; i < line_pos; i++) {
30323032
if (spl_filesystem_file_read_line(ZEND_THIS, intern, 1) == FAILURE) {
3033-
break;
3033+
return;
30343034
}
30353035
}
3036+
if (line_pos > 0) {
3037+
intern->u.file.current_line_num++;
3038+
spl_filesystem_file_free_line(intern);
3039+
}
30363040
} /* }}} */
30373041

30383042
/* {{{ Function/Class/Method definitions */

ext/spl/tests/SplFileObject_key_error001.phpt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@ Erwin Poeze <erwin.poeze@gmail.com>
1212
//line 5
1313
$s = new SplFileObject(__FILE__);
1414

15-
$s->seek(12);
15+
$s->seek(13);
1616
$s->next();
1717
var_dump($s->key());
1818
var_dump($s->valid());
1919
?>
2020
--EXPECT--
21-
int(13)
21+
int(14)
2222
bool(false)

ext/spl/tests/SplFileObject_next_variation002.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ echo $s->current();
2626
--EXPECT--
2727
//line 3
2828
//line 4
29-
//line 3
3029
//line 4
30+
//line 5

ext/spl/tests/bug62004.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Bug #62004 (SplFileObject: fgets after seek returns wrong line)
3+
--FILE--
4+
<?php
5+
$f = new SplFileObject(__DIR__ . '/bug62004.txt');
6+
$f->setFlags(SplFileObject::SKIP_EMPTY);
7+
$f->seek(0);
8+
echo $f->fgets();
9+
$f->seek(1);
10+
echo $f->fgets();
11+
$f->seek(2);
12+
echo $f->fgets();
13+
?>
14+
--EXPECT--
15+
Line 1
16+
Line 2
17+
Line 3

ext/spl/tests/fileobject_getcurrentline_basic.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ echo $s->getCurrentLine();
1515
echo $s->getCurrentLine();
1616
?>
1717
--EXPECT--
18+
//line 2
1819
//line 3
19-
//line 4

0 commit comments

Comments
 (0)