summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/gd/libgd/gd.c4
-rw-r--r--ext/gd/libgd/gd_gd2.c7
-rw-r--r--ext/gd/libgd/gd_interpolation.c3
-rw-r--r--ext/gd/libgd/gd_topal.c2
-rw-r--r--ext/gd/tests/bug72298.phpt15
-rw-r--r--ext/gd/tests/bug72339.gdbin0 -> 67108882 bytes
-rw-r--r--ext/gd/tests/bug72339.phpt11
-rw-r--r--ext/mbstring/php_mbregex.c1
-rw-r--r--ext/mbstring/tests/bug72402.phpt17
-rw-r--r--ext/mcrypt/mcrypt.c10
-rw-r--r--ext/phar/phar_object.c4
-rw-r--r--ext/phar/tests/72321_1.zipbin0 -> 250 bytes
-rw-r--r--ext/phar/tests/72321_2.zipbin0 -> 258 bytes
-rw-r--r--ext/phar/tests/bug72321.phpt26
-rw-r--r--ext/standard/tests/strings/bug72433.phpt32
-rw-r--r--ext/standard/tests/strings/bug72434.phpt33
-rw-r--r--ext/wddx/tests/bug72340.phpt24
-rw-r--r--ext/wddx/wddx.c1
-rw-r--r--ext/zip/php_zip.c9
19 files changed, 194 insertions, 5 deletions
diff --git a/ext/gd/libgd/gd.c b/ext/gd/libgd/gd.c
index afa7e58f33..bb2f9c23aa 100644
--- a/ext/gd/libgd/gd.c
+++ b/ext/gd/libgd/gd.c
@@ -131,6 +131,10 @@ gdImagePtr gdImageCreate (int sx, int sy)
return NULL;
}
+ if (overflow2(sizeof(unsigned char *), sx)) {
+ return NULL;
+ }
+
im = (gdImage *) gdCalloc(1, sizeof(gdImage));
/* Row-major ever since gd 1.3 */
diff --git a/ext/gd/libgd/gd_gd2.c b/ext/gd/libgd/gd_gd2.c
index 6726fee826..e954aafa68 100644
--- a/ext/gd/libgd/gd_gd2.c
+++ b/ext/gd/libgd/gd_gd2.c
@@ -138,11 +138,18 @@ static int _gd2GetHeader(gdIOCtxPtr in, int *sx, int *sy, int *cs, int *vers, in
if (gd2_compressed(*fmt)) {
nc = (*ncx) * (*ncy);
GD2_DBG(php_gd_error("Reading %d chunk index entries", nc));
+ if (overflow2(sizeof(t_chunk_info), nc)) {
+ goto fail1;
+ }
sidx = sizeof(t_chunk_info) * nc;
if (sidx <= 0) {
goto fail1;
}
cidx = gdCalloc(sidx, 1);
+ if (cidx == NULL) {
+ goto fail1;
+ }
+
for (i = 0; i < nc; i++) {
if (gdGetInt(&cidx[i].offset, in) != 1) {
gdFree(cidx);
diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c
index 6d703b8b30..83319966f9 100644
--- a/ext/gd/libgd/gd_interpolation.c
+++ b/ext/gd/libgd/gd_interpolation.c
@@ -1047,6 +1047,9 @@ static inline void _gdScaleVert (const gdImagePtr pSrc, const unsigned int src_w
}
contrib = _gdContributionsCalc(dst_height, src_height, (double)(dst_height) / (double)(src_height), pSrc->interpolation);
+ if (contrib == NULL) {
+ return;
+ }
/* scale each column */
for (u = 0; u < dst_width - 1; u++) {
_gdScaleCol(pSrc, src_width, pDst, dst_width, dst_height, u, contrib);
diff --git a/ext/gd/libgd/gd_topal.c b/ext/gd/libgd/gd_topal.c
index 0206860f05..d8dda45cb9 100644
--- a/ext/gd/libgd/gd_topal.c
+++ b/ext/gd/libgd/gd_topal.c
@@ -1329,7 +1329,7 @@ pass2_no_dither (j_decompress_ptr cinfo,
/* If the pixel is transparent, we assign it the palette index that
* will later be added at the end of the palette as the transparent
* index. */
- if ((oim->transparent >= 0) && (oim->transparent == *(inptr - 1)))
+ if ((oim->transparent >= 0) && (oim->transparent == *inptr))
{
*outptr++ = nim->colorsTotal;
inptr++;
diff --git a/ext/gd/tests/bug72298.phpt b/ext/gd/tests/bug72298.phpt
new file mode 100644
index 0000000000..7fba241ed1
--- /dev/null
+++ b/ext/gd/tests/bug72298.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #72298: pass2_no_dither out-of-bounds access
+--SKIPIF--
+<?php
+ if (!extension_loaded('gd')) die("skip gd extension not available\n");
+?>
+--FILE--
+<?php
+$img = imagecreatetruecolor (1 , 1);
+imagecolortransparent($img, 0);
+imagetruecolortopalette($img, false, 4);
+?>
+DONE
+--EXPECT--
+DONE \ No newline at end of file
diff --git a/ext/gd/tests/bug72339.gd b/ext/gd/tests/bug72339.gd
new file mode 100644
index 0000000000..0634c99005
--- /dev/null
+++ b/ext/gd/tests/bug72339.gd
Binary files differ
diff --git a/ext/gd/tests/bug72339.phpt b/ext/gd/tests/bug72339.phpt
new file mode 100644
index 0000000000..763ae71000
--- /dev/null
+++ b/ext/gd/tests/bug72339.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Bug #72339 Integer Overflow in _gd2GetHeader() resulting in heap overflow
+--SKIPIF--
+<?php if (!function_exists("imagecreatefromgd2")) print "skip"; ?>
+--FILE--
+<?php imagecreatefromgd2(dirname(__FILE__) . DIRECTORY_SEPARATOR . "bug72339.gd"); ?>
+--EXPECTF--
+Warning: imagecreatefromgd2(): gd warning: product of memory allocation multiplication would exceed INT_MAX, failing operation gracefully
+ in %sbug72339.php on line %d
+
+Warning: imagecreatefromgd2(): '%sbug72339.gd' is not a valid GD2 file in %sbug72339.php on line %d
diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c
index 2337926740..573a5e9b9c 100644
--- a/ext/mbstring/php_mbregex.c
+++ b/ext/mbstring/php_mbregex.c
@@ -988,7 +988,6 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
smart_str_free(&eval_buf);
zval_ptr_dtor(&retval);
} else {
- efree(description);
if (!EG(exception)) {
php_error_docref(NULL, E_WARNING, "Unable to call custom replacement function");
}
diff --git a/ext/mbstring/tests/bug72402.phpt b/ext/mbstring/tests/bug72402.phpt
new file mode 100644
index 0000000000..abb290bf4d
--- /dev/null
+++ b/ext/mbstring/tests/bug72402.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Bug #72402: _php_mb_regex_ereg_replace_exec - double free
+--SKIPIF--
+<?php extension_loaded('mbstring') or die('skip mbstring not available'); ?>
+--FILE--
+<?php
+function throwit() {
+ throw new Exception('it');
+}
+$var10 = "throwit";
+try {
+ $var14 = mb_ereg_replace_callback("", $var10, "");
+} catch(Exception $e) {}
+?>
+DONE
+--EXPECT--
+DONE \ No newline at end of file
diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c
index 073bfec775..fb5c638c97 100644
--- a/ext/mcrypt/mcrypt.c
+++ b/ext/mcrypt/mcrypt.c
@@ -637,6 +637,10 @@ PHP_FUNCTION(mcrypt_generic)
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
block_size = mcrypt_enc_get_block_size(pm->td);
data_size = ((((int)data_len - 1) / block_size) + 1) * block_size;
+ if (data_size <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size");
+ RETURN_FALSE;
+ }
data_str = zend_string_alloc(data_size, 0);
memset(ZSTR_VAL(data_str), 0, data_size);
memcpy(ZSTR_VAL(data_str), data, data_len);
@@ -683,7 +687,11 @@ PHP_FUNCTION(mdecrypt_generic)
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
block_size = mcrypt_enc_get_block_size(pm->td);
data_size = ((((int)data_len - 1) / block_size) + 1) * block_size;
- data_s = emalloc(data_size + 1);
+ if (data_size <= 0) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Integer overflow in data size");
+ RETURN_FALSE;
+ }
+ data_s = emalloc((size_t)data_size + 1);
memset(data_s, 0, data_size);
memcpy(data_s, data, data_len);
} else { /* It's not a block algorithm */
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index 7c9c3351aa..c57bdef3c6 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -4166,14 +4166,14 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
if (!php_stream_mkdir(fullpath, entry->flags & PHAR_ENT_PERM_MASK, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
efree(fullpath);
- free(new_state.cwd);
+ efree(new_state.cwd);
return FAILURE;
}
} else {
if (!php_stream_mkdir(fullpath, 0777, PHP_STREAM_MKDIR_RECURSIVE, NULL)) {
spprintf(error, 4096, "Cannot extract \"%s\", could not create directory \"%s\"", entry->filename, fullpath);
efree(fullpath);
- free(new_state.cwd);
+ efree(new_state.cwd);
return FAILURE;
}
}
diff --git a/ext/phar/tests/72321_1.zip b/ext/phar/tests/72321_1.zip
new file mode 100644
index 0000000000..ebc44ea282
--- /dev/null
+++ b/ext/phar/tests/72321_1.zip
Binary files differ
diff --git a/ext/phar/tests/72321_2.zip b/ext/phar/tests/72321_2.zip
new file mode 100644
index 0000000000..de7ca266b8
--- /dev/null
+++ b/ext/phar/tests/72321_2.zip
Binary files differ
diff --git a/ext/phar/tests/bug72321.phpt b/ext/phar/tests/bug72321.phpt
new file mode 100644
index 0000000000..37aca19e82
--- /dev/null
+++ b/ext/phar/tests/bug72321.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Phar: PHP bug #72321: invalid free in phar_extract_file()
+--SKIPIF--
+<?php if (!extension_loaded("phar")) die("skip"); ?>
+--FILE--
+<?php
+chdir(__DIR__);
+mkdir("test72321");
+$phar = new PharData("72321_1.zip");
+$phar->extractTo("test72321");
+$phar = new PharData("72321_2.zip");
+try {
+$phar->extractTo("test72321");
+} catch(PharException $e) {
+ print $e->getMessage()."\n";
+}
+?>
+DONE
+--CLEAN--
+<?php unlink(__DIR__."/test72321/AAAAAAAAxxxxBBBBCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
+rmdir(__DIR__."/test72321");
+?>
+--EXPECTF--
+Warning: PharData::extractTo(): Not a directory in %s/bug72321.php on line %d
+Extraction from phar "%s/72321_2.zip" failed: Cannot extract "AAAAAAAAxxxxBBBBCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/b/c", could not create directory "test72321/AAAAAAAAxxxxBBBBCCCCCCCCxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/b"
+DONE \ No newline at end of file
diff --git a/ext/standard/tests/strings/bug72433.phpt b/ext/standard/tests/strings/bug72433.phpt
new file mode 100644
index 0000000000..3a2c89701b
--- /dev/null
+++ b/ext/standard/tests/strings/bug72433.phpt
@@ -0,0 +1,32 @@
+--TEST--
+Bug #72433: Use After Free Vulnerability in PHP's GC algorithm and unserialize
+--FILE--
+<?php
+// Fill any potential freed spaces until now.
+$filler = array();
+for($i = 0; $i < 100; $i++)
+ $filler[] = "";
+// Create our payload and unserialize it.
+$serialized_payload = 'a:3:{i:0;r:1;i:1;r:1;i:2;C:11:"ArrayObject":19:{x:i:0;r:1;;m:a:0:{}}}';
+$free_me = unserialize($serialized_payload);
+// We need to increment the reference counter of our ArrayObject s.t. all reference counters of our unserialized array become 0.
+$inc_ref_by_one = $free_me[2];
+// The call to gc_collect_cycles will free '$free_me'.
+gc_collect_cycles();
+// We now have multiple freed spaces. Fill all of them.
+$fill_freed_space_1 = "filler_zval_1";
+$fill_freed_space_2 = "filler_zval_2";
+var_dump($free_me);
+?>
+--EXPECTF--
+array(3) {
+ [0]=>
+ *RECURSION*
+ [1]=>
+ *RECURSION*
+ [2]=>
+ object(ArrayObject)#%d (1) {
+ ["storage":"ArrayObject":private]=>
+ *RECURSION*
+ }
+}
diff --git a/ext/standard/tests/strings/bug72434.phpt b/ext/standard/tests/strings/bug72434.phpt
new file mode 100644
index 0000000000..1408b8f578
--- /dev/null
+++ b/ext/standard/tests/strings/bug72434.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #72434: ZipArchive class Use After Free Vulnerability in PHP's GC algorithm and unserialize
+--SKIPIF--
+<?php
+if(!class_exists('zip')) die('ZipArchive');
+?>
+--FILE--
+<?php
+// The following array will be serialized and this representation will be freed later on.
+$free_me = array(new StdClass());
+// Create our payload and unserialize it.
+$serialized_payload = 'a:3:{i:1;N;i:2;O:10:"ZipArchive":1:{s:8:"filename";'.serialize($free_me).'}i:1;R:4;}';
+$unserialized_payload = unserialize($serialized_payload);
+gc_collect_cycles();
+// The reference counter for $free_me is at -1 for PHP 7 right now.
+// Increment the reference counter by 1 -> rc is 0
+$a = $unserialized_payload[1];
+// Increment the reference counter by 1 again -> rc is 1
+$b = $a;
+// Trigger free of $free_me (referenced by $m[1]).
+unset($b);
+$fill_freed_space_1 = "filler_zval_1";
+$fill_freed_space_2 = "filler_zval_2";
+$fill_freed_space_3 = "filler_zval_3";
+$fill_freed_space_4 = "filler_zval_4";
+debug_zval_dump($unserialized_payload[1]);
+?>
+--EXPECTF--
+array(1) refcount(1){
+ [0]=>
+ object(stdClass)#%d (0) refcount(3){
+ }
+}
diff --git a/ext/wddx/tests/bug72340.phpt b/ext/wddx/tests/bug72340.phpt
new file mode 100644
index 0000000000..8d694ca52e
--- /dev/null
+++ b/ext/wddx/tests/bug72340.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #72340: Double Free Courruption in wddx_deserialize
+--SKIPIF--
+<?php
+if (!extension_loaded("wddx")) print "skip";
+?>
+--FILE--
+<?php
+$xml = <<<EOF
+<?xml version='1.0' ?>
+<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
+<wddxPacket version='1.0'>
+ <array><var name="XXXXXXXX"><boolean value="none">TEST</boolean></var>
+ <var name="YYYYYYYY"><var name="ZZZZZZZZ"><var name="EZEZEZEZ">
+ </var></var></var>
+ </array>
+</wddxPacket>
+EOF;
+$array = wddx_deserialize($xml);
+var_dump($array);
+?>
+--EXPECT--
+array(0) {
+}
diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c
index 330cb49f08..34b8eeb87f 100644
--- a/ext/wddx/wddx.c
+++ b/ext/wddx/wddx.c
@@ -1019,6 +1019,7 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
zval_ptr_dtor(&ent->data);
if (ent->varname) {
efree(ent->varname);
+ ent->varname = NULL;
}
ZVAL_UNDEF(&ent->data);
}
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 88bb518442..bdcba78b21 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -958,6 +958,14 @@ static int php_zip_has_property(zval *object, zval *member, int type, void **cac
}
/* }}} */
+static HashTable *php_zip_get_gc(zval *object, zval **gc_data, int *gc_data_count) /* {{{ */
+{
+ *gc_data = NULL;
+ *gc_data_count = 0;
+ return zend_std_get_properties(object);
+}
+/* }}} */
+
static HashTable *php_zip_get_properties(zval *object)/* {{{ */
{
ze_zip_object *obj;
@@ -3014,6 +3022,7 @@ static PHP_MINIT_FUNCTION(zip)
zip_object_handlers.clone_obj = NULL;
zip_object_handlers.get_property_ptr_ptr = php_zip_get_property_ptr_ptr;
+ zip_object_handlers.get_gc = php_zip_get_gc;
zip_object_handlers.get_properties = php_zip_get_properties;
zip_object_handlers.read_property = php_zip_read_property;
zip_object_handlers.has_property = php_zip_has_property;