Fixed bug #75111 (Memory disclosure or DoS via crafted .bmp image)

Crafted BMP images can cause dynamicSeek() to be called with a negative
position which must not be allowed, since dynamicSeek() works like
fseek() in SEEK_SET mode. We solve this by bailing out if `pos` is
negative, and let the image reading fail gracefully.
This commit is contained in:
Christoph M. Becker 2017-08-24 12:39:45 +02:00
parent cf6f25bd37
commit 5cd348c1d6
4 changed files with 43 additions and 4 deletions

3
NEWS
View File

@ -8,6 +8,9 @@ PHP NEWS
- CURL:
. Fixed bug #75093 (OpenSSL support not detected). (Remi)
- GD:
. Fixed bug #75111 (Memory disclosure or DoS via crafted .bmp image). (cmb)
- PCRE:
. Fixed bug #75089 (preg_grep() is not reporting PREG_BAD_UTF8_ERROR after
first input string). (Dmitry)

View File

@ -711,7 +711,9 @@ static int bmp_read_direct(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, b
/* There is a chance the data isn't until later, would be wierd but it is possible */
if (gdTell(infile) != header->off) {
/* Should make sure we don't seek past the file size */
gdSeek(infile, header->off);
if (!gdSeek(infile, header->off)) {
return 1;
}
}
/* The line must be divisible by 4, else its padded with NULLs */
@ -806,7 +808,9 @@ static int bmp_read_1bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp
/* There is a chance the data isn't until later, would be wierd but it is possible */
if (gdTell(infile) != header->off) {
/* Should make sure we don't seek past the file size */
gdSeek(infile, header->off);
if (!gdSeek(infile, header->off)) {
return 1;
}
}
/* The line must be divisible by 4, else its padded with NULLs */
@ -874,7 +878,9 @@ static int bmp_read_4bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp
/* There is a chance the data isn't until later, would be wierd but it is possible */
if (gdTell(infile) != header->off) {
/* Should make sure we don't seek past the file size */
gdSeek(infile, header->off);
if (!gdSeek(infile, header->off)) {
return 1;
}
}
/* The line must be divisible by 4, else its padded with NULLs */
@ -959,7 +965,9 @@ static int bmp_read_8bit(gdImagePtr im, gdIOCtxPtr infile, bmp_info_t *info, bmp
/* There is a chance the data isn't until later, would be wierd but it is possible */
if (gdTell(infile) != header->off) {
/* Should make sure we don't seek past the file size */
gdSeek(infile, header->off);
if (!gdSeek(infile, header->off)) {
return 1;
}
}
/* The line must be divisible by 4, else its padded with NULLs */

View File

@ -152,6 +152,9 @@ static int dynamicSeek (struct gdIOCtx *ctx, const int pos)
dynamicPtr *dp;
dpIOCtx *dctx;
if (pos < 0) {
return FALSE;
}
dctx = (dpIOCtx *) ctx;
dp = dctx->dp;

View File

@ -0,0 +1,25 @@
--TEST--
Bug #75111 (Memory disclosure or DoS via crafted .bmp image)
--SKIPIF--
<?php
if (!extension_loaded('gd')) die('skip gd extension not available');
?>
--FILE--
<?php
// craft BMP image
$str = hex2bin("424D3603000000000000");
$str .= pack("V", -0x120000); // offset of image data
$str .= pack("V", 40); // length of header
$str .= pack("V", 256); // width
$str .= pack("V", 256); // height
$str .= hex2bin("01001800000000000000000000000000000000000000000000000000");
var_dump(imagecreatefromstring($str));
?>
===DONE===
--EXPECTF--
Warning: imagecreatefromstring(): Passed data is not in 'BMP' format in %s on line %d
Warning: imagecreatefromstring(): Couldn't create GD Image Stream out of Data in %s on line %d
bool(false)
===DONE===