From dc375ce5bf6883698d85621b560edc78680def68 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 18 Nov 2020 12:22:31 +0100 Subject: [PATCH 1/3] 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. --- ext/spl/spl_directory.c | 10 +++++++--- ext/spl/tests/SplFileObject_key_error001.phpt | 4 ++-- .../tests/SplFileObject_next_variation002.phpt | 2 +- ext/spl/tests/bug62004.phpt | 17 +++++++++++++++++ .../tests/fileobject_getcurrentline_basic.phpt | 2 +- 5 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 ext/spl/tests/bug62004.phpt diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 3d0dae243502b..7d9ea9cc2bfaa 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -2727,7 +2727,7 @@ PHP_METHOD(SplFileObject, ftruncate) PHP_METHOD(SplFileObject, seek) { spl_filesystem_object *intern = Z_SPLFILESYSTEM_P(ZEND_THIS); - zend_long line_pos; + zend_long line_pos, i; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &line_pos) == FAILURE) { RETURN_THROWS(); @@ -2742,11 +2742,15 @@ PHP_METHOD(SplFileObject, seek) spl_filesystem_file_rewind(ZEND_THIS, intern); - while(intern->u.file.current_line_num < line_pos) { + for (i = 0; i < line_pos; i++) { if (spl_filesystem_file_read_line(ZEND_THIS, intern, 1) == FAILURE) { - break; + return; } } + if (line_pos > 0) { + intern->u.file.current_line_num++; + spl_filesystem_file_free_line(intern); + } } /* }}} */ /* {{{ PHP_MINIT_FUNCTION(spl_directory) */ diff --git a/ext/spl/tests/SplFileObject_key_error001.phpt b/ext/spl/tests/SplFileObject_key_error001.phpt index b0834f00290ae..0c21d0b905e95 100644 --- a/ext/spl/tests/SplFileObject_key_error001.phpt +++ b/ext/spl/tests/SplFileObject_key_error001.phpt @@ -12,11 +12,11 @@ Erwin Poeze //line 5 $s = new SplFileObject(__FILE__); -$s->seek(12); +$s->seek(13); $s->next(); var_dump($s->key()); var_dump($s->valid()); ?> --EXPECT-- -int(13) +int(14) bool(false) diff --git a/ext/spl/tests/SplFileObject_next_variation002.phpt b/ext/spl/tests/SplFileObject_next_variation002.phpt index d48ff8c22371c..e4903dce0cd23 100644 --- a/ext/spl/tests/SplFileObject_next_variation002.phpt +++ b/ext/spl/tests/SplFileObject_next_variation002.phpt @@ -26,5 +26,5 @@ echo $s->current(); --EXPECT-- //line 3 //line 4 -//line 3 //line 4 +//line 5 diff --git a/ext/spl/tests/bug62004.phpt b/ext/spl/tests/bug62004.phpt new file mode 100644 index 0000000000000..4a06738594a3b --- /dev/null +++ b/ext/spl/tests/bug62004.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #62004 (SplFileObject: fgets after seek returns wrong line) +--FILE-- +setFlags(SplFileObject::SKIP_EMPTY); +$f->seek(0); +echo $f->fgets(); +$f->seek(1); +echo $f->fgets(); +$f->seek(2); +echo $f->fgets(); +?> +--EXPECT-- +Line 1 +Line 2 +Line 3 diff --git a/ext/spl/tests/fileobject_getcurrentline_basic.phpt b/ext/spl/tests/fileobject_getcurrentline_basic.phpt index 607fce6640a3d..47f6e28dd8b40 100644 --- a/ext/spl/tests/fileobject_getcurrentline_basic.phpt +++ b/ext/spl/tests/fileobject_getcurrentline_basic.phpt @@ -15,5 +15,5 @@ echo $s->getCurrentLine(); echo $s->getCurrentLine(); ?> --EXPECT-- +//line 2 //line 3 -//line 4 From 93c78fd440dba15b9a0cadc5dc8ee3e16d87768e Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 18 Nov 2020 13:40:56 +0100 Subject: [PATCH 2/3] Add missing txt file --- ext/spl/tests/bug62004.txt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 ext/spl/tests/bug62004.txt diff --git a/ext/spl/tests/bug62004.txt b/ext/spl/tests/bug62004.txt new file mode 100644 index 0000000000000..e5791419fa06d --- /dev/null +++ b/ext/spl/tests/bug62004.txt @@ -0,0 +1,4 @@ +Line 1 +Line 2 +Line 3 +Line 4 From b61192c36d8a333ea5a86960bedeaf238a1a3ab6 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 18 Nov 2020 13:41:21 +0100 Subject: [PATCH 3/3] Add test case for bug #46569 --- ext/spl/tests/bug46569.csv | 5 +++++ ext/spl/tests/bug46569.phpt | 14 ++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 ext/spl/tests/bug46569.csv create mode 100644 ext/spl/tests/bug46569.phpt diff --git a/ext/spl/tests/bug46569.csv b/ext/spl/tests/bug46569.csv new file mode 100644 index 0000000000000..f456a03b78515 --- /dev/null +++ b/ext/spl/tests/bug46569.csv @@ -0,0 +1,5 @@ +first,line +second,line +third,line +fourth,line +fifth,line diff --git a/ext/spl/tests/bug46569.phpt b/ext/spl/tests/bug46569.phpt new file mode 100644 index 0000000000000..0c1ab6ce1427e --- /dev/null +++ b/ext/spl/tests/bug46569.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #46569 (SplFileObject: fgetcsv after seek returns wrong line) +--FILE-- +seek(1); +print_r($file->fgetcsv()); +?> +--EXPECT-- +Array +( + [0] => second + [1] => line +)