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.
This commit is contained in:
Christoph M. Becker 2021-04-13 12:35:10 +02:00
parent 5ccb5fd91e
commit 976e71a2fa
No known key found for this signature in database
GPG key ID: D66C9593118BCCB6
3 changed files with 37 additions and 3 deletions

4
NEWS
View file

@ -2,7 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 7.4.19
- SPL:
. Fixed bug #80933 (SplFileObject::DROP_NEW_LINE is broken for NUL and CR).
(cmb, Nikita)
29 Apr 2021, PHP 7.4.18

View file

@ -2046,8 +2046,13 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /
intern->u.file.current_line_len = 0;
} else {
if (SPL_HAS_FLAG(intern->flags, SPL_FILE_OBJECT_DROP_NEW_LINE)) {
line_len = strcspn(buf, "\r\n");
buf[line_len] = '\0';
if (line_len > 0 && buf[line_len - 1] == '\n') {
line_len--;
if (line_len > 0 && buf[line_len - 1] == '\r') {
line_len--;
}
buf[line_len] = '\0';
}
}
intern->u.file.current_line = buf;

View file

@ -0,0 +1,27 @@
--TEST--
Bug #80933 (SplFileObject::DROP_NEW_LINE is broken for NUL and CR)
--FILE--
<?php
$lines = [
"Lorem ipsum \0 dolor sit amet", // string with NUL
"Lorem ipsum \r dolor sit amet", // string with CR
];
foreach ($lines as $line) {
$temp = new SplTempFileObject();
$temp->fwrite($line);
$temp->rewind();
$read = $temp->fgets();
var_dump($line === $read);
$temp->rewind();
$temp->setFlags(SplFileObject::DROP_NEW_LINE);
$read = $temp->fgets();
var_dump($line === $read);
}
?>
--EXPECT--
bool(true)
bool(true)
bool(true)
bool(true)