Skip to content

Commit 976e71a

Browse files
committed
Fix #80933: SplFileObject::DROP_NEW_LINE is broken for NUL and CR
`buf` may contain NUL bytes, so we must not use `strcspn()` but rather a binary safe variant. However, we also must not detect a stray CR as line ending, and since we only need to check line endings at the end of the buffer, we can nicely optimize. Co-authored-by: Nikita Popov <nikita.ppv@gmail.com> Closes GH-6836.
1 parent 5ccb5fd commit 976e71a

File tree

3 files changed

+37
-3
lines changed

3 files changed

+37
-3
lines changed

NEWS

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 7.4.19
44

5-
5+
- SPL:
6+
. Fixed bug #80933 (SplFileObject::DROP_NEW_LINE is broken for NUL and CR).
7+
(cmb, Nikita)
68

79
29 Apr 2021, PHP 7.4.18
810

ext/spl/spl_directory.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2046,8 +2046,13 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /
20462046
intern->u.file.current_line_len = 0;
20472047
} else {
20482048
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
2049-
line_len = strcspn(buf, "\r\n");
2050-
buf[line_len] = '\0';
2049+
if (line_len > 0 && buf[line_len - 1] == '\n') {
2050+
line_len--;
2051+
if (line_len > 0 && buf[line_len - 1] == '\r') {
2052+
line_len--;
2053+
}
2054+
buf[line_len] = '\0';
2055+
}
20512056
}
20522057

20532058
intern->u.file.current_line = buf;

ext/spl/tests/bug80933.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Bug #80933 (SplFileObject::DROP_NEW_LINE is broken for NUL and CR)
3+
--FILE--
4+
<?php
5+
$lines = [
6+
"Lorem ipsum \0 dolor sit amet", // string with NUL
7+
"Lorem ipsum \r dolor sit amet", // string with CR
8+
];
9+
foreach ($lines as $line) {
10+
$temp = new SplTempFileObject();
11+
$temp->fwrite($line);
12+
13+
$temp->rewind();
14+
$read = $temp->fgets();
15+
var_dump($line === $read);
16+
17+
$temp->rewind();
18+
$temp->setFlags(SplFileObject::DROP_NEW_LINE);
19+
$read = $temp->fgets();
20+
var_dump($line === $read);
21+
}
22+
?>
23+
--EXPECT--
24+
bool(true)
25+
bool(true)
26+
bool(true)
27+
bool(true)

0 commit comments

Comments
 (0)