mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-5.5' into PHP-5.6.23
* PHP-5.5: Fixed bug #72446 - Integer Overflow in gdImagePaletteToTrueColor() resulting in heap overflow update NEWS fix tests fix build Fix bug #72455: Heap Overflow due to integer overflows Fix bug #72434: ZipArchive class Use After Free Vulnerability in PHP's GC algorithm and unserialize Fixed ##72433: Use After Free Vulnerability in PHP's GC algorithm and unserialize Fix bug #72407: NULL Pointer Dereference at _gdScaleVert Fix bug #72402: _php_mb_regex_ereg_replace_exec - double free Fix bug #72298 pass2_no_dither out-of-bounds access Fixed #72339 Integer Overflow in _gd2GetHeader() resulting in heap overflow Fix bug #72262 - do not overflow int Fix bug #72400 and #72403 - prevent signed int overflows for string lengths Fix bug #72275: don't allow smart_str to overflow int Fix bug #72340: Double Free Courruption in wddx_deserialize update NEWS Fix #66387: Stack overflow with imagefilltoborder Skip test which is 64bits only 5.5.37 now Conflicts: configure.in ext/mcrypt/mcrypt.c ext/spl/spl_directory.c main/php_version.h
This commit is contained in:
commit
7dde353ee7
21 changed files with 450 additions and 243 deletions
|
@ -13,5 +13,5 @@ var_dump(gc_collect_cycles());
|
|||
echo "ok\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
int(1)
|
||||
int(2)
|
||||
ok
|
||||
|
|
|
@ -133,6 +133,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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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++;
|
||||
|
|
15
ext/gd/tests/bug72298.phpt
Normal file
15
ext/gd/tests/bug72298.phpt
Normal file
|
@ -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
|
BIN
ext/gd/tests/bug72339.gd
Normal file
BIN
ext/gd/tests/bug72339.gd
Normal file
Binary file not shown.
11
ext/gd/tests/bug72339.phpt
Normal file
11
ext/gd/tests/bug72339.phpt
Normal file
|
@ -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
|
|
@ -953,7 +953,7 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
|
|||
eval_buf.len = 0;
|
||||
zval_dtor(&v);
|
||||
} else if (is_callable) {
|
||||
zval *retval_ptr;
|
||||
zval *retval_ptr = NULL;
|
||||
zval **args[1];
|
||||
zval *subpats;
|
||||
int i;
|
||||
|
@ -972,13 +972,12 @@ static void _php_mb_regex_ereg_replace_exec(INTERNAL_FUNCTION_PARAMETERS, OnigOp
|
|||
arg_replace_fci.param_count = 1;
|
||||
arg_replace_fci.params = args;
|
||||
arg_replace_fci.retval_ptr_ptr = &retval_ptr;
|
||||
if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr) {
|
||||
if (zend_call_function(&arg_replace_fci, &arg_replace_fci_cache TSRMLS_CC) == SUCCESS && arg_replace_fci.retval_ptr_ptr && retval_ptr) {
|
||||
convert_to_string_ex(&retval_ptr);
|
||||
smart_str_appendl(&out_buf, Z_STRVAL_P(retval_ptr), Z_STRLEN_P(retval_ptr));
|
||||
eval_buf.len = 0;
|
||||
zval_ptr_dtor(&retval_ptr);
|
||||
} else {
|
||||
efree(description);
|
||||
if (!EG(exception)) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to call custom replacement function");
|
||||
}
|
||||
|
|
17
ext/mbstring/tests/bug72402.phpt
Normal file
17
ext/mbstring/tests/bug72402.phpt
Normal file
|
@ -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
|
|
@ -661,6 +661,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 = (((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_s = emalloc(data_size + 1);
|
||||
memset(data_s, 0, data_size);
|
||||
memcpy(data_s, data, data_len);
|
||||
|
@ -706,6 +710,10 @@ 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 = (((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_s = emalloc(data_size + 1);
|
||||
memset(data_s, 0, data_size);
|
||||
memcpy(data_s, data, data_len);
|
||||
|
|
|
@ -846,6 +846,16 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp TSRMLS_DC) /*
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static HashTable *spl_array_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
||||
*gc_data = &intern->array;
|
||||
*gc_data_count = 1;
|
||||
return zend_std_get_properties(object TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static zval *spl_array_read_property(zval *object, zval *member, int type, const zend_literal *key TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
spl_array_object *intern = (spl_array_object*)zend_object_store_get_object(object TSRMLS_CC);
|
||||
|
@ -1975,6 +1985,7 @@ PHP_MINIT_FUNCTION(spl_array)
|
|||
|
||||
spl_handler_ArrayObject.get_properties = spl_array_get_properties;
|
||||
spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info;
|
||||
spl_handler_ArrayObject.get_gc = spl_array_get_gc;
|
||||
spl_handler_ArrayObject.read_property = spl_array_read_property;
|
||||
spl_handler_ArrayObject.write_property = spl_array_write_property;
|
||||
spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr;
|
||||
|
|
|
@ -2948,6 +2948,10 @@ SPL_METHOD(SplFileObject, fread)
|
|||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be greater than 0");
|
||||
RETURN_FALSE;
|
||||
}
|
||||
if (length > INT_MAX) {
|
||||
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Length parameter must be no more than %d", INT_MAX);
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
Z_STRVAL_P(return_value) = emalloc(length + 1);
|
||||
Z_STRLEN_P(return_value) = php_stream_read(intern->u.file.stream, Z_STRVAL_P(return_value), length);
|
||||
|
|
|
@ -63,6 +63,9 @@
|
|||
newlen = (d)->len + (n); \
|
||||
if (newlen >= (d)->a) { \
|
||||
(d)->a = newlen + SMART_STR_PREALLOC; \
|
||||
if (UNEXPECTED((d)->a >= INT_MAX)) { \
|
||||
zend_error(E_ERROR, "String size overflow"); \
|
||||
} \
|
||||
SMART_STR_DO_REALLOC(d, what); \
|
||||
} \
|
||||
} \
|
||||
|
|
|
@ -132,6 +132,9 @@ static char *php_bin2hex(const unsigned char *old, const size_t oldlen, size_t *
|
|||
register unsigned char *result = NULL;
|
||||
size_t i, j;
|
||||
|
||||
if (UNEXPECTED(oldlen * 2 * sizeof(char) > INT_MAX)) {
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
result = (unsigned char *) safe_emalloc(oldlen, 2 * sizeof(char), 1);
|
||||
|
||||
for (i = j = 0; i < oldlen; i++) {
|
||||
|
@ -2608,6 +2611,7 @@ PHP_FUNCTION(quotemeta)
|
|||
char *p, *q;
|
||||
char c;
|
||||
int old_len;
|
||||
size_t new_len;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &old, &old_len) == FAILURE) {
|
||||
return;
|
||||
|
@ -2642,8 +2646,13 @@ PHP_FUNCTION(quotemeta)
|
|||
}
|
||||
}
|
||||
*q = 0;
|
||||
new_len = q - str;
|
||||
if (UNEXPECTED(new_len > INT_MAX)) {
|
||||
efree(str);
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
|
||||
RETURN_STRINGL(erealloc(str, q - str + 1), q - str, 0);
|
||||
RETURN_STRINGL(erealloc(str, new_len + 1), new_len, 0);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -3495,7 +3504,7 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s
|
|||
char *source, *target;
|
||||
char *end;
|
||||
char c;
|
||||
int newlen;
|
||||
size_t newlen;
|
||||
|
||||
if (!wlength) {
|
||||
wlength = strlen(what);
|
||||
|
@ -3526,11 +3535,15 @@ PHPAPI char *php_addcslashes(const char *str, int length, int *new_length, int s
|
|||
}
|
||||
*target = 0;
|
||||
newlen = target - new_str;
|
||||
if (UNEXPECTED(newlen > INT_MAX)) {
|
||||
efree(new_str);
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
if (target - new_str < length * 4) {
|
||||
new_str = erealloc(new_str, newlen + 1);
|
||||
}
|
||||
if (new_length) {
|
||||
*new_length = newlen;
|
||||
*new_length = (int)newlen;
|
||||
}
|
||||
if (should_free) {
|
||||
STR_FREE((char*)str);
|
||||
|
@ -3582,6 +3595,9 @@ PHPAPI char *php_addslashes(char *str, int length, int *new_length, int should_f
|
|||
|
||||
*target = 0;
|
||||
*new_length = target - new_str;
|
||||
if (UNEXPECTED(*new_length < 0)) {
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
if (should_free) {
|
||||
STR_FREE(str);
|
||||
}
|
||||
|
@ -4285,6 +4301,9 @@ PHP_FUNCTION(nl2br)
|
|||
size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1);
|
||||
|
||||
new_length = str_len + repl_cnt * repl_len;
|
||||
if (UNEXPECTED(new_length > INT_MAX)) {
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
tmp = target = safe_emalloc(repl_cnt, repl_len, str_len + 1);
|
||||
}
|
||||
|
||||
|
|
32
ext/standard/tests/strings/bug72433.phpt
Normal file
32
ext/standard/tests/strings/bug72433.phpt
Normal file
|
@ -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*
|
||||
}
|
||||
}
|
33
ext/standard/tests/strings/bug72434.phpt
Normal file
33
ext/standard/tests/strings/bug72434.phpt
Normal file
|
@ -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){
|
||||
}
|
||||
}
|
|
@ -625,6 +625,10 @@ PHPAPI char *php_raw_url_encode(char const *s, int len, int *new_length)
|
|||
if (new_length) {
|
||||
*new_length = y;
|
||||
}
|
||||
if (UNEXPECTED(y > INT_MAX)) {
|
||||
efree(str);
|
||||
zend_error(E_ERROR, "String size overflow");
|
||||
}
|
||||
return ((char *) str);
|
||||
}
|
||||
/* }}} */
|
||||
|
|
24
ext/wddx/tests/bug72340.phpt
Normal file
24
ext/wddx/tests/bug72340.phpt
Normal file
|
@ -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) {
|
||||
}
|
|
@ -1094,6 +1094,9 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
|
|||
break;
|
||||
|
||||
case ST_BOOLEAN:
|
||||
if(!ent->data) {
|
||||
break;
|
||||
}
|
||||
if (!strcmp(s, "true")) {
|
||||
Z_LVAL_P(ent->data) = 1;
|
||||
} else if (!strcmp(s, "false")) {
|
||||
|
@ -1102,6 +1105,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;
|
||||
}
|
||||
ent->data = NULL;
|
||||
}
|
||||
|
|
|
@ -1042,6 +1042,14 @@ static int php_zip_has_property(zval *object, zval *member, int type KEY_ARG_DC
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static HashTable *php_zip_get_gc(zval *object, zval ***gc_data, int *gc_data_count TSRMLS_DC) /* {{{ */
|
||||
{
|
||||
*gc_data = NULL;
|
||||
*gc_data_count = 0;
|
||||
return zend_std_get_properties(object TSRMLS_CC);
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static HashTable *php_zip_get_properties(zval *object TSRMLS_DC)/* {{{ */
|
||||
{
|
||||
ze_zip_object *obj;
|
||||
|
@ -3039,6 +3047,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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue