mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.1' into PHP-8.2
* PHP-8.1: Fix GH-10834: exif_read_data() cannot read smaller stream wrapper chunk sizes
This commit is contained in:
commit
d369a7764f
3 changed files with 116 additions and 10 deletions
4
NEWS
4
NEWS
|
@ -13,6 +13,10 @@ PHP NEWS
|
|||
. Fixed bug GH-11222 (foreach by-ref may jump over keys during a rehash).
|
||||
(Bob)
|
||||
|
||||
- Exif:
|
||||
. Fixed bug GH-10834 (exif_read_data() cannot read smaller stream wrapper
|
||||
chunk sizes). (nielsdos)
|
||||
|
||||
- Hash:
|
||||
. Fixed bug GH-11180 (hash_file() appears to be restricted to 3 arguments).
|
||||
(nielsdos)
|
||||
|
|
|
@ -215,6 +215,25 @@ zend_module_entry exif_module_entry = {
|
|||
ZEND_GET_MODULE(exif)
|
||||
#endif
|
||||
|
||||
/* php_stream_read() may return early without reading all data, depending on the chunk size
|
||||
* and whether it's a URL stream or not. This helper keeps reading until the requested amount
|
||||
* is read or until there is no more data available to read. */
|
||||
static ssize_t exif_read_from_stream_file_looped(php_stream *stream, char *buf, size_t count)
|
||||
{
|
||||
ssize_t total_read = 0;
|
||||
while (total_read < count) {
|
||||
ssize_t ret = php_stream_read(stream, buf + total_read, count - total_read);
|
||||
if (ret == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (ret == 0) {
|
||||
break;
|
||||
}
|
||||
total_read += ret;
|
||||
}
|
||||
return total_read;
|
||||
}
|
||||
|
||||
/* {{{ php_strnlen
|
||||
* get length of string if buffer if less than buffer size or buffer size */
|
||||
static size_t php_strnlen(char* str, size_t maxlen) {
|
||||
|
@ -3321,7 +3340,7 @@ static bool exif_process_IFD_TAG_impl(image_info_type *ImageInfo, char *dir_entr
|
|||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Wrong file pointer: 0x%08X != 0x%08X", fgot, displacement+offset_val);
|
||||
return false;
|
||||
}
|
||||
fgot = php_stream_read(ImageInfo->infile, value_ptr, byte_count);
|
||||
fgot = exif_read_from_stream_file_looped(ImageInfo->infile, value_ptr, byte_count);
|
||||
php_stream_seek(ImageInfo->infile, fpos, SEEK_SET);
|
||||
if (fgot != byte_count) {
|
||||
EFREE_IF(outside);
|
||||
|
@ -3854,7 +3873,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
|
|||
Data[0] = (uchar)lh;
|
||||
Data[1] = (uchar)ll;
|
||||
|
||||
got = php_stream_read(ImageInfo->infile, (char*)(Data+2), itemlen-2); /* Read the whole section. */
|
||||
got = exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(Data+2), itemlen-2); /* Read the whole section. */
|
||||
if (got != itemlen-2) {
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Error reading from file: got=x%04X(=%d) != itemlen-2=x%04X(=%d)", got, got, itemlen-2, itemlen-2);
|
||||
return false;
|
||||
|
@ -3872,7 +3891,7 @@ static bool exif_scan_JPEG_header(image_info_type *ImageInfo)
|
|||
size = ImageInfo->FileSize - fpos;
|
||||
sn = exif_file_sections_add(ImageInfo, M_PSEUDO, size, NULL);
|
||||
Data = ImageInfo->file.list[sn].data;
|
||||
got = php_stream_read(ImageInfo->infile, (char*)Data, size);
|
||||
got = exif_read_from_stream_file_looped(ImageInfo->infile, (char*)Data, size);
|
||||
if (got != size) {
|
||||
EXIF_ERRLOG_FILEEOF(ImageInfo)
|
||||
return false;
|
||||
|
@ -4049,7 +4068,9 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
|
|||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read from TIFF: filesize(x%04X), IFD dir(x%04X + x%04X)", ImageInfo->FileSize, dir_offset, 2);
|
||||
#endif
|
||||
php_stream_seek(ImageInfo->infile, dir_offset, SEEK_SET); /* we do not know the order of sections */
|
||||
php_stream_read(ImageInfo->infile, (char*)ImageInfo->file.list[sn].data, 2);
|
||||
if (UNEXPECTED(exif_read_from_stream_file_looped(ImageInfo->infile, (char*)ImageInfo->file.list[sn].data, 2) != 2)) {
|
||||
return false;
|
||||
}
|
||||
num_entries = php_ifd_get16u(ImageInfo->file.list[sn].data, ImageInfo->motorola_intel);
|
||||
dir_size = 2/*num dir entries*/ +12/*length of entry*/*(size_t)num_entries +4/* offset to next ifd (points to thumbnail or NULL)*/;
|
||||
if (ImageInfo->FileSize >= dir_size && ImageInfo->FileSize - dir_size >= dir_offset) {
|
||||
|
@ -4059,7 +4080,9 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
|
|||
if (exif_file_sections_realloc(ImageInfo, sn, dir_size)) {
|
||||
return false;
|
||||
}
|
||||
php_stream_read(ImageInfo->infile, (char*)(ImageInfo->file.list[sn].data+2), dir_size-2);
|
||||
if (UNEXPECTED(exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(ImageInfo->file.list[sn].data+2), dir_size-2) != dir_size - 2)) {
|
||||
return false;
|
||||
}
|
||||
next_offset = php_ifd_get32u(ImageInfo->file.list[sn].data + dir_size - 4, ImageInfo->motorola_intel);
|
||||
#ifdef EXIF_DEBUG
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read from TIFF done, next offset x%04X", next_offset);
|
||||
|
@ -4147,7 +4170,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
|
|||
#ifdef EXIF_DEBUG
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read from TIFF: filesize(x%04X), IFD(x%04X + x%04X)", ImageInfo->FileSize, dir_offset, ifd_size);
|
||||
#endif
|
||||
php_stream_read(ImageInfo->infile, (char*)(ImageInfo->file.list[sn].data+dir_size), ifd_size-dir_size);
|
||||
exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(ImageInfo->file.list[sn].data+dir_size), ifd_size-dir_size);
|
||||
#ifdef EXIF_DEBUG
|
||||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read from TIFF, done");
|
||||
#endif
|
||||
|
@ -4198,7 +4221,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
|
|||
if (!ImageInfo->Thumbnail.data) {
|
||||
ImageInfo->Thumbnail.data = safe_emalloc(ImageInfo->Thumbnail.size, 1, 0);
|
||||
php_stream_seek(ImageInfo->infile, ImageInfo->Thumbnail.offset, SEEK_SET);
|
||||
fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
|
||||
fgot = exif_read_from_stream_file_looped(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
|
||||
if (fgot != ImageInfo->Thumbnail.size) {
|
||||
EXIF_ERRLOG_THUMBEOF(ImageInfo)
|
||||
efree(ImageInfo->Thumbnail.data);
|
||||
|
@ -4238,7 +4261,7 @@ static bool exif_process_IFD_in_TIFF_impl(image_info_type *ImageInfo, size_t dir
|
|||
if (!ImageInfo->Thumbnail.data && ImageInfo->Thumbnail.offset && ImageInfo->Thumbnail.size && ImageInfo->read_thumbnail) {
|
||||
ImageInfo->Thumbnail.data = safe_emalloc(ImageInfo->Thumbnail.size, 1, 0);
|
||||
php_stream_seek(ImageInfo->infile, ImageInfo->Thumbnail.offset, SEEK_SET);
|
||||
fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
|
||||
fgot = exif_read_from_stream_file_looped(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
|
||||
if (fgot != ImageInfo->Thumbnail.size) {
|
||||
EXIF_ERRLOG_THUMBEOF(ImageInfo)
|
||||
efree(ImageInfo->Thumbnail.data);
|
||||
|
@ -4293,7 +4316,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
|
|||
|
||||
if (ImageInfo->FileSize >= 2) {
|
||||
php_stream_seek(ImageInfo->infile, 0, SEEK_SET);
|
||||
if (php_stream_read(ImageInfo->infile, (char*)file_header, 2) != 2) {
|
||||
if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)file_header, 2) != 2) {
|
||||
return false;
|
||||
}
|
||||
if ((file_header[0]==0xff) && (file_header[1]==M_SOI)) {
|
||||
|
@ -4304,7 +4327,7 @@ static bool exif_scan_FILE_header(image_info_type *ImageInfo)
|
|||
exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_WARNING, "Invalid JPEG file");
|
||||
}
|
||||
} else if (ImageInfo->FileSize >= 8) {
|
||||
if (php_stream_read(ImageInfo->infile, (char*)(file_header+2), 6) != 6) {
|
||||
if (exif_read_from_stream_file_looped(ImageInfo->infile, (char*)(file_header+2), 6) != 6) {
|
||||
return false;
|
||||
}
|
||||
if (!memcmp(file_header, "II\x2A\x00", 4)) {
|
||||
|
|
79
ext/exif/tests/gh10834.phpt
Normal file
79
ext/exif/tests/gh10834.phpt
Normal file
|
@ -0,0 +1,79 @@
|
|||
--TEST--
|
||||
GH-10834 (exif_read_data() cannot read smaller stream wrapper chunk sizes)
|
||||
--EXTENSIONS--
|
||||
exif
|
||||
--FILE--
|
||||
<?php
|
||||
class VariableStream {
|
||||
private $data;
|
||||
private $position;
|
||||
public $context;
|
||||
|
||||
function stream_close() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function stream_eof() {
|
||||
return $this->position >= strlen($this->data);
|
||||
}
|
||||
|
||||
function stream_open($path, $mode, $options, &$opened_path) {
|
||||
$this->position = 0;
|
||||
$this->data = file_get_contents(__DIR__.'/bug50845.jpg');
|
||||
return true;
|
||||
}
|
||||
|
||||
function stream_seek($offset, $whence) {
|
||||
switch ($whence) {
|
||||
case SEEK_SET:
|
||||
if ($offset < strlen($this->data) && $offset >= 0) {
|
||||
$this->position = $offset;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SEEK_CUR:
|
||||
if ($offset >= 0) {
|
||||
$this->position += $offset;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case SEEK_END:
|
||||
if (strlen($this->data) + $offset >= 0) {
|
||||
$this->position = strlen($this->data) + $offset;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function stream_read($count) {
|
||||
$ret = substr($this->data, $this->position, $count);
|
||||
$this->position += strlen($ret);
|
||||
return $ret;
|
||||
}
|
||||
|
||||
function stream_tell() {
|
||||
return $this->position;
|
||||
}
|
||||
}
|
||||
|
||||
stream_wrapper_register('var', 'VariableStream');
|
||||
|
||||
$fp = fopen('var://myvar', 'rb');
|
||||
|
||||
stream_set_chunk_size($fp, 10);
|
||||
$headers = exif_read_data($fp);
|
||||
var_dump(is_array($headers));
|
||||
|
||||
fclose($fp);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
Loading…
Add table
Add a link
Reference in a new issue