Skip to content

Commit 1d9a1f9

Browse files
committed
Fix GH-8121: SplFileObject - seek and key with csv file inconsistent
First, we must not free the current line before we call `spl_filesystem_file_read_csv()`, because then the `current_line` will not be properly updated. Since the EOF check is superfluous here, we move that part of the code to the branch for subtypes. This issue has been introduced by the fix for bug 75917. Second, we only must increase the `current_line` if we're not reading ahead. This issue has been introduced by the fix for bug 62004. Closes GH-8138.
1 parent 15949b6 commit 1d9a1f9

File tree

4 files changed

+55
-8
lines changed

4 files changed

+55
-8
lines changed

NEWS

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ PHP NEWS
1313
- Pcntl:
1414
. Fixed bug GH-8142 (Compilation error on cygwin). (David Carlier)
1515

16+
- SPL:
17+
. Fixed bug GH-8121 (SplFileObject - seek and key with csv file inconsistent).
18+
(cmb)
19+
1620
- Standard:
1721
. Fixed bug GH-8048 (Force macOS to use statfs). (risner)
1822

ext/spl/spl_directory.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1938,7 +1938,11 @@ static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_obje
19381938
zval retval;
19391939

19401940
/* 1) use fgetcsv? 2) overloaded call the function, 3) do it directly */
1941-
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV) || intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
1941+
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) {
1942+
return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL);
1943+
}
1944+
if (intern->u.file.func_getCurr->common.scope != spl_ce_SplFileObject) {
1945+
zend_execute_data *execute_data = EG(current_execute_data);
19421946
spl_filesystem_file_free_line(intern);
19431947

19441948
if (php_stream_eof(intern->u.file.stream)) {
@@ -1947,12 +1951,7 @@ static int spl_filesystem_file_read_line_ex(zval * this_ptr, spl_filesystem_obje
19471951
}
19481952
return FAILURE;
19491953
}
1950-
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_CSV)) {
1951-
return spl_filesystem_file_read_csv(intern, intern->u.file.delimiter, intern->u.file.enclosure, intern->u.file.escape, NULL);
1952-
} else {
1953-
zend_execute_data *execute_data = EG(current_execute_data);
1954-
zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(ZEND_THIS), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
1955-
}
1954+
zend_call_method_with_0_params(Z_OBJ_P(this_ptr), Z_OBJCE_P(ZEND_THIS), &intern->u.file.func_getCurr, "getCurrentLine", &retval);
19561955
if (!Z_ISUNDEF(retval)) {
19571956
if (intern->u.file.current_line || !Z_ISUNDEF(intern->u.file.current_zval)) {
19581957
intern->u.file.current_line_num++;
@@ -2739,8 +2738,8 @@ PHP_METHOD(SplFileObject, seek)
27392738
}
27402739
}
27412740
if (line_pos > 0) {
2742-
intern->u.file.current_line_num++;
27432741
if (!SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_READ_AHEAD)) {
2742+
intern->u.file.current_line_num++;
27442743
spl_filesystem_file_free_line(intern);
27452744
}
27462745
}

ext/spl/tests/gh8121.csv

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
id,status,on_sale,brand,name,link,meta_title,meta_desc,description
2+
1,2,15,Samsung,M21,samsung-m21,Samsung M21,Samsung M21,Samsung M21
3+
2,2,15,Samsung,M32,samsung-m32,Samsung M32,Samsung M32,Samsung M32
4+
3,2,15,Samsung,M21,samsung-m21,Samsung M21,Samsung M21,Samsung M21
5+
4,2,15,Samsung,M32,samsung-m32,Samsung M32,Samsung M32,Samsung M32

ext/spl/tests/gh8121.phpt

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
--TEST--
2+
GH-8121 (SplFileObject - seek and key with csv file inconsistent)
3+
--FILE--
4+
<?php
5+
$flagss = [
6+
SplFileObject::READ_AHEAD | SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE,
7+
SplFileObject::READ_AHEAD | SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE,
8+
SplFileObject::SKIP_EMPTY | SplFileObject::DROP_NEW_LINE,
9+
];
10+
foreach ($flagss as $flags) {
11+
$file = new SplFileObject(__DIR__ . "/gh8121.csv", "r");
12+
echo "flags: $flags\n";
13+
$file->setFlags($flags);
14+
$file->seek(0);
15+
var_dump($file->key());
16+
$file->seek(1);
17+
var_dump($file->key());
18+
$file->seek(2);
19+
var_dump($file->key());
20+
$file->seek(3);
21+
var_dump($file->key());
22+
}
23+
?>
24+
--EXPECT--
25+
flags: 15
26+
int(0)
27+
int(1)
28+
int(2)
29+
int(3)
30+
flags: 7
31+
int(0)
32+
int(1)
33+
int(2)
34+
int(3)
35+
flags: 5
36+
int(0)
37+
int(1)
38+
int(2)
39+
int(3)

0 commit comments

Comments
 (0)