mirror of
https://github.com/php/php-src.git
synced 2024-09-21 09:57:23 +00:00
Fix bug #52335 (fseek() on memory stream behavior different then file)
This changes memory stream to allow seeking past end which makes it the same as seeking on files. It means the position is allowed to be higher than the string length. The size only increases if data is appended to the past position. The space between the previous string and position is filled with zero bytes. Fixes GH-9441 Closes GH-12058
This commit is contained in:
parent
ea10e79bae
commit
ba9650d697
4
NEWS
4
NEWS
@ -20,6 +20,10 @@ PHP NEWS
|
||||
. Fixed GH-11982 (str_getcsv returns null byte for unterminated enclosure).
|
||||
(Jakub Zelenka)
|
||||
|
||||
- Streams:
|
||||
. Fixed bug #52335 (fseek() on memory stream behavior different than file).
|
||||
(Jakub Zelenka)
|
||||
|
||||
17 Aug 2023, PHP 8.3.0beta3
|
||||
|
||||
- Core:
|
||||
|
@ -648,6 +648,9 @@ PHP 8.3 UPGRADE NOTES
|
||||
- Streams:
|
||||
. Blocking fread() on socket connection returns immediately if there are
|
||||
any buffered data instead of waiting for more data.
|
||||
. Memory stream no longer fails if seek offset is past the end. Instead
|
||||
the memory is increase on the next write and date between the old end and
|
||||
offset is filled with zero bytes in the same way how it works for files.
|
||||
|
||||
========================================
|
||||
14. Performance Improvements
|
||||
|
67
ext/standard/tests/file/bug52335.phpt
Normal file
67
ext/standard/tests/file/bug52335.phpt
Normal file
@ -0,0 +1,67 @@
|
||||
--TEST--
|
||||
Bug #52335 (fseek() on memory stream behavior different then file)
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
echo "Read mode\n";
|
||||
$fpr = fopen("php://memory", "r");
|
||||
var_dump(fseek($fpr, 20));
|
||||
var_dump(feof($fpr));
|
||||
var_dump(ftell($fpr));
|
||||
var_dump(feof($fpr));
|
||||
var_dump(fread($fpr, 2));
|
||||
var_dump(feof($fpr));
|
||||
var_dump(fseek($fpr, 24));
|
||||
var_dump(feof($fpr));
|
||||
var_dump(ftell($fpr));
|
||||
fclose($fpr);
|
||||
|
||||
echo "Read write mode\n";
|
||||
$fprw = fopen("php://memory", "r+");
|
||||
var_dump(fwrite($fprw, "data"));
|
||||
var_dump(fseek($fprw, 20, SEEK_END));
|
||||
var_dump(feof($fprw));
|
||||
var_dump(ftell($fprw));
|
||||
var_dump(feof($fprw));
|
||||
var_dump(fread($fprw, 2));
|
||||
var_dump(feof($fprw));
|
||||
var_dump(fseek($fprw, 20));
|
||||
var_dump(fwrite($fprw, " and more data"));
|
||||
var_dump(feof($fprw));
|
||||
var_dump(ftell($fprw));
|
||||
var_dump(fread($fprw, 10));
|
||||
var_dump(fseek($fprw, 16, SEEK_CUR));
|
||||
var_dump(ftell($fprw));
|
||||
var_dump(fseek($fprw, 0));
|
||||
var_dump(bin2hex(stream_get_contents($fprw)));
|
||||
fclose($fprw);
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
Read mode
|
||||
int(0)
|
||||
bool(false)
|
||||
int(20)
|
||||
bool(false)
|
||||
string(0) ""
|
||||
bool(true)
|
||||
int(0)
|
||||
bool(false)
|
||||
int(24)
|
||||
Read write mode
|
||||
int(4)
|
||||
int(0)
|
||||
bool(false)
|
||||
int(24)
|
||||
bool(false)
|
||||
string(0) ""
|
||||
bool(true)
|
||||
int(0)
|
||||
int(14)
|
||||
bool(false)
|
||||
int(34)
|
||||
string(0) ""
|
||||
int(0)
|
||||
int(50)
|
||||
int(0)
|
||||
string(68) "646174610000000000000000000000000000000020616e64206d6f72652064617461"
|
20
ext/standard/tests/file/gh9441.phpt
Normal file
20
ext/standard/tests/file/gh9441.phpt
Normal file
@ -0,0 +1,20 @@
|
||||
--TEST--
|
||||
Bug GH-9441 (fseek does not work with php://input when data is not preread)
|
||||
--INI--
|
||||
enable_post_data_reading=0
|
||||
--POST_RAW--
|
||||
Content-Type: application/unknown
|
||||
a=123456789&b=ZYX
|
||||
--FILE--
|
||||
<?php
|
||||
$input = fopen("php://input", "r");
|
||||
var_dump(fseek($input, 10));
|
||||
var_dump(ftell($input));
|
||||
var_dump(fread($input, 10));
|
||||
var_dump(file_get_contents("php://input"));
|
||||
?>
|
||||
--EXPECT--
|
||||
int(0)
|
||||
int(10)
|
||||
string(7) "9&b=ZYX"
|
||||
string(17) "a=123456789&b=ZYX"
|
@ -125,8 +125,8 @@ int(0)
|
||||
int(3)
|
||||
bool(false)
|
||||
===S:10,C===
|
||||
int(-1)
|
||||
bool(false)
|
||||
int(0)
|
||||
int(13)
|
||||
bool(false)
|
||||
===S:-1,E===
|
||||
int(0)
|
||||
@ -137,6 +137,6 @@ int(0)
|
||||
int(6)
|
||||
bool(false)
|
||||
===S:1,E===
|
||||
int(-1)
|
||||
bool(false)
|
||||
int(0)
|
||||
int(7)
|
||||
bool(false)
|
||||
|
@ -49,11 +49,17 @@ static ssize_t php_stream_memory_write(php_stream *stream, const char *buf, size
|
||||
|
||||
if (ms->mode & TEMP_STREAM_READONLY) {
|
||||
return (ssize_t) -1;
|
||||
} else if (ms->mode & TEMP_STREAM_APPEND) {
|
||||
ms->fpos = ZSTR_LEN(ms->data);
|
||||
}
|
||||
if (ms->fpos + count > ZSTR_LEN(ms->data)) {
|
||||
size_t data_len = ZSTR_LEN(ms->data);
|
||||
if (ms->mode & TEMP_STREAM_APPEND) {
|
||||
ms->fpos = data_len;
|
||||
}
|
||||
if (ms->fpos + count > data_len) {
|
||||
ms->data = zend_string_realloc(ms->data, ms->fpos + count, 0);
|
||||
if (ms->fpos > data_len) {
|
||||
/* zero the bytes added due to seek past end position */
|
||||
memset(ZSTR_VAL(ms->data) + data_len, 0, ms->fpos - data_len);
|
||||
}
|
||||
} else {
|
||||
ms->data = zend_string_separate(ms->data, 0);
|
||||
}
|
||||
@ -73,7 +79,7 @@ static ssize_t php_stream_memory_read(php_stream *stream, char *buf, size_t coun
|
||||
php_stream_memory_data *ms = (php_stream_memory_data*)stream->abstract;
|
||||
assert(ms != NULL);
|
||||
|
||||
if (ms->fpos == ZSTR_LEN(ms->data)) {
|
||||
if (ms->fpos >= ZSTR_LEN(ms->data)) {
|
||||
stream->eof = 1;
|
||||
count = 0;
|
||||
} else {
|
||||
@ -132,20 +138,14 @@ static int php_stream_memory_seek(php_stream *stream, zend_off_t offset, int whe
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (ms->fpos + (size_t)(offset) > ZSTR_LEN(ms->data)) {
|
||||
ms->fpos = ZSTR_LEN(ms->data);
|
||||
*newoffs = -1;
|
||||
return -1;
|
||||
} else {
|
||||
stream->eof = 0;
|
||||
ms->fpos = ms->fpos + offset;
|
||||
*newoffs = ms->fpos;
|
||||
stream->eof = 0;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
case SEEK_SET:
|
||||
if (ZSTR_LEN(ms->data) < (size_t)(offset)) {
|
||||
ms->fpos = ZSTR_LEN(ms->data);
|
||||
if (offset < 0) {
|
||||
ms->fpos = 0;
|
||||
*newoffs = -1;
|
||||
return -1;
|
||||
} else {
|
||||
@ -156,9 +156,10 @@ static int php_stream_memory_seek(php_stream *stream, zend_off_t offset, int whe
|
||||
}
|
||||
case SEEK_END:
|
||||
if (offset > 0) {
|
||||
ms->fpos = ZSTR_LEN(ms->data);
|
||||
*newoffs = -1;
|
||||
return -1;
|
||||
ms->fpos = ZSTR_LEN(ms->data) + offset;
|
||||
*newoffs = ms->fpos;
|
||||
stream->eof = 0;
|
||||
return 0;
|
||||
} else if (ZSTR_LEN(ms->data) < (size_t)(-offset)) {
|
||||
ms->fpos = 0;
|
||||
*newoffs = -1;
|
||||
|
Loading…
Reference in New Issue
Block a user