Skip to content

Commit

Permalink
Fixed bug #75111 (Memory disclosure or DoS via crafted .bmp image)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cmb69 committed Aug 24, 2017
1 parent cf6f25b commit 5cd348c
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 4 deletions.
3 changes: 3 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
16 changes: 12 additions & 4 deletions ext/gd/libgd/gd_bmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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 */
Expand Down
3 changes: 3 additions & 0 deletions ext/gd/libgd/gd_io_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
25 changes: 25 additions & 0 deletions ext/gd/tests/bug75111.phpt
Original file line number Diff line number Diff line change
@@ -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===

0 comments on commit 5cd348c

Please sign in to comment.