Skip to content

Commit 6f87a5c

Browse files
committed
Fix GH-8563 Different results for seek() on SplFileObject and SplTempFileObject
With memory streams if we get a NULL buffer we must not instantiate an empty line
1 parent 93a44f8 commit 6f87a5c

10 files changed

+142
-16
lines changed

NEWS

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ PHP NEWS
3838
. Fixed errorInfo() result on successful PDOStatement->execute(). (Yurunsoft)
3939
. Fixed handling of single-key connection strings. (Calvin Buckley)
4040

41+
- SPL:
42+
. Fixed bug GH-8563 (Different results for seek() on SplFileObject and SplTempFileObject). (Girgias)
43+
4144
- Zip:
4245
. Fixed bug GH-8781 (ZipArchive::close deletes zip file without updating stat
4346
cache). (Remi)

ext/spl/spl_directory.c

+11-12
Original file line numberDiff line numberDiff line change
@@ -1883,22 +1883,21 @@ static zend_result spl_filesystem_file_read_ex(spl_filesystem_object *intern, bo
18831883
}
18841884

18851885
if (!buf) {
1886-
intern->u.file.current_line = estrdup("");
1887-
intern->u.file.current_line_len = 0;
1888-
} else {
1889-
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
1890-
if (line_len > 0 && buf[line_len - 1] == '\n') {
1886+
return FAILURE;
1887+
}
1888+
1889+
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
1890+
if (line_len > 0 && buf[line_len - 1] == '\n') {
1891+
line_len--;
1892+
if (line_len > 0 && buf[line_len - 1] == '\r') {
18911893
line_len--;
1892-
if (line_len > 0 && buf[line_len - 1] == '\r') {
1893-
line_len--;
1894-
}
1895-
buf[line_len] = '\0';
18961894
}
1895+
buf[line_len] = '\0';
18971896
}
1898-
1899-
intern->u.file.current_line = buf;
1900-
intern->u.file.current_line_len = line_len;
19011897
}
1898+
1899+
intern->u.file.current_line = buf;
1900+
intern->u.file.current_line_len = line_len;
19021901
intern->u.file.current_line_num += line_add;
19031902

19041903
return SUCCESS;

ext/spl/tests/SplFileObject_fgetcsv_basic.phpt renamed to ext/spl/tests/SplFileObject/SplFileObject_fgetcsv_basic.phpt

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ fclose($fp);
1313

1414
$fo = new SplFileObject('SplFileObject__fgetcsv1.csv');
1515
var_dump($fo->fgetcsv());
16+
var_dump($fo->fgetcsv());
1617
?>
1718
--CLEAN--
1819
<?php
@@ -29,3 +30,4 @@ array(4) {
2930
[3]=>
3031
string(1) "5"
3132
}
33+
NULL

ext/spl/tests/SplFileObject_key_error001.phpt renamed to ext/spl/tests/SplFileObject/SplFileObject_key_error001.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ var_dump($s->key());
1818
var_dump($s->valid());
1919
?>
2020
--EXPECT--
21-
int(14)
21+
int(12)
2222
bool(false)

ext/spl/tests/SplFileObject_key_error002.phpt renamed to ext/spl/tests/SplFileObject/SplFileObject_key_error002.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,5 @@ var_dump($s->key());
1818
var_dump($s->valid());
1919
?>
2020
--EXPECT--
21-
int(13)
21+
int(12)
2222
bool(false)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
SplFileObject::fgetcsv with empty lines
3+
--FILE--
4+
<?php
5+
6+
$file = new SplTempFileObject();
7+
8+
$file->fwrite("foo,bar\n");
9+
$file->fwrite("\n");
10+
$file->fwrite("baz,qux");
11+
12+
$file->rewind();
13+
14+
15+
var_dump($file->fgetcsv());
16+
var_dump($file->fgetcsv());
17+
var_dump($file->fgetcsv());
18+
var_dump($file->fgetcsv());
19+
20+
?>
21+
--EXPECT--
22+
array(2) {
23+
[0]=>
24+
string(3) "foo"
25+
[1]=>
26+
string(3) "bar"
27+
}
28+
array(1) {
29+
[0]=>
30+
NULL
31+
}
32+
array(2) {
33+
[0]=>
34+
string(3) "baz"
35+
[1]=>
36+
string(3) "qux"
37+
}
38+
NULL
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
Iterate over SplFileObject with empty lines with CSV flags
3+
--FILE--
4+
<?php
5+
6+
$file = new SplTempFileObject();
7+
8+
$file->fwrite("foo,bar\n");
9+
$file->fwrite("\n");
10+
$file->fwrite("baz,qux");
11+
12+
$file->rewind();
13+
14+
$file->setFlags(SplFileObject::READ_CSV | SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY /* | SplFileObject::DROP_NEW_LINE */);
15+
16+
17+
foreach ($file as $line) {
18+
var_dump($line);
19+
}
20+
?>
21+
--EXPECT--
22+
array(2) {
23+
[0]=>
24+
string(3) "foo"
25+
[1]=>
26+
string(3) "bar"
27+
}
28+
array(1) {
29+
[0]=>
30+
NULL
31+
}
32+
array(2) {
33+
[0]=>
34+
string(3) "baz"
35+
[1]=>
36+
string(3) "qux"
37+
}
+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
Bug GH-8563: Different results for seek() on SplFileObject and SplTempFileObject
3+
--FILE--
4+
<?php
5+
6+
const LINES = 5;
7+
const INDEX = 10;
8+
9+
$file_01 = new SplFileObject(__DIR__ . '/gh8563.txt', 'w+');
10+
$file_02 = new SplTempFileObject(-1);
11+
$file_03 = new SplTempFileObject(0);
12+
$file_04 = new SplTempFileObject();
13+
14+
// write to files
15+
for ($i = 0; $i < LINES; $i++) {
16+
$file_01->fwrite("line {$i}" . PHP_EOL);
17+
$file_02->fwrite("line {$i}" . PHP_EOL);
18+
$file_03->fwrite("line {$i}" . PHP_EOL);
19+
$file_04->fwrite("line {$i}" . PHP_EOL);
20+
}
21+
22+
// reset
23+
$file_01->rewind();
24+
$file_02->rewind();
25+
$file_03->rewind();
26+
$file_04->rewind();
27+
28+
// seek
29+
$file_01->seek(INDEX);
30+
$file_02->seek(INDEX);
31+
$file_03->seek(INDEX);
32+
$file_04->seek(INDEX);
33+
34+
// show results
35+
echo 'file_01: ' . $file_01->key(), PHP_EOL;
36+
echo 'file_02: ' . $file_02->key(), PHP_EOL;
37+
echo 'file_03: ' . $file_03->key(), PHP_EOL;
38+
echo 'file_04: ' . $file_04->key(), PHP_EOL;
39+
?>
40+
--CLEAN--
41+
<?php
42+
unlink(__DIR__ . '/gh8563.txt');
43+
?>
44+
--EXPECT--
45+
file_01: 4
46+
file_02: 4
47+
file_03: 4
48+
file_04: 4

ext/spl/tests/bug81477.phpt

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ string(8) "baz,bat
2121
"
2222
string(10) "more,data
2323
"
24-
string(0) ""
2524
--CLEAN--
2625
<?php
2726
@unlink(__DIR__ . '/bug81477.csv');

ext/spl/tests/fileobject_001.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ string(1) "4"
7070
int(5)
7171
string(1) "5"
7272
int(6)
73-
string(0) ""
73+
bool(false)
7474
===B===
7575
int(0)
7676
string(1) "0"

0 commit comments

Comments
 (0)