Merge branch 'PHP-7.0.10' into PHP-7.0

* PHP-7.0.10:
  Fix bug #72749: wddx_deserialize allows illegal memory access
  Fixed bug #72627: Memory Leakage In exif_process_IFD_in_TIFF
  fix tests
  Fix bug#72697 - select_colors write out-of-bounds
  Fix bug #72708 - php_snmp_parse_oid integer overflow in memory allocation
  Fix bug #72730 - imagegammacorrect allows arbitrary write access
  Fix bug #72750: wddx_deserialize null dereference
  Fix bug #72771: ftps:// opendir wrapper is vulnerable to protocol downgrade attack
  fix tests
  add missing skipif section
  Fix for bug #72790 and bug #72799
  Fix bug #72837 - integer overflow in bzdecompress caused heap corruption
  Fix bug #72742 - memory allocator fails to realloc small block to large one
  Use size_t for path length
  Check for string overflow
  Fix for bug #72782: mcrypt accepts only ints, so don't pass anything else
  Fix bug #72674 - check both curl_escape and curl_unescape
This commit is contained in:
Stanislav Malyshev 2016-08-16 23:52:22 -07:00
commit 75d7666968
22 changed files with 327 additions and 50 deletions

View File

@ -1548,21 +1548,21 @@ static void *zend_mm_realloc_heap(zend_mm_heap *heap, void *ptr, size_t size, si
ZEND_MM_CHECK(chunk->heap == heap, "zend_mm_heap corrupted");
if (info & ZEND_MM_IS_SRUN) {
int old_bin_num, bin_num;
old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
int old_bin_num = ZEND_MM_SRUN_BIN_NUM(info);
old_size = bin_data_size[old_bin_num];
bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size);
if (old_bin_num == bin_num) {
if (size <= ZEND_MM_MAX_SMALL_SIZE) {
int bin_num = ZEND_MM_SMALL_SIZE_TO_BIN(size);
if (old_bin_num == bin_num) {
#if ZEND_DEBUG
dbg = zend_mm_get_debug_info(heap, ptr);
dbg->size = real_size;
dbg->filename = __zend_filename;
dbg->orig_filename = __zend_orig_filename;
dbg->lineno = __zend_lineno;
dbg->orig_lineno = __zend_orig_lineno;
dbg = zend_mm_get_debug_info(heap, ptr);
dbg->size = real_size;
dbg->filename = __zend_filename;
dbg->orig_filename = __zend_orig_filename;
dbg->lineno = __zend_lineno;
dbg->orig_lineno = __zend_orig_lineno;
#endif
return ptr;
return ptr;
}
}
} else /* if (info & ZEND_MM_IS_LARGE_RUN) */ {
ZEND_MM_CHECK(ZEND_MM_ALIGNED_OFFSET(page_offset, ZEND_MM_PAGE_SIZE) == 0, "zend_mm_heap corrupted");

View File

@ -594,16 +594,26 @@ static PHP_FUNCTION(bzdecompress)
/* compression is better then 2:1, need to allocate more memory */
bzs.avail_out = source_len;
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
if (size > SIZE_MAX) {
/* no reason to continue if we're going to drop it anyway */
break;
}
dest = safe_erealloc(dest, 1, bzs.avail_out+1, (size_t) size );
bzs.next_out = dest + size;
}
if (error == BZ_STREAM_END || error == BZ_OK) {
size = (bzs.total_out_hi32 * (unsigned int) -1) + bzs.total_out_lo32;
dest = safe_erealloc(dest, 1, (size_t) size, 1);
dest[size] = '\0';
RETVAL_STRINGL(dest, (int) size);
efree(dest);
if (size > SIZE_MAX) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Decompressed size too big, max is %zd", SIZE_MAX);
efree(dest);
RETVAL_LONG(BZ_MEM_ERROR);
} else {
dest = safe_erealloc(dest, 1, (size_t) size, 1);
dest[size] = '\0';
RETVAL_STRINGL(dest, (size_t) size);
efree(dest);
}
} else { /* real error */
efree(dest);
RETVAL_LONG(error);

View File

@ -3517,7 +3517,7 @@ PHP_FUNCTION(curl_reset)
PHP_FUNCTION(curl_escape)
{
char *str = NULL, *res = NULL;
size_t str_len = 0;
size_t str_len = 0;
zval *zid;
php_curl *ch;
@ -3529,6 +3529,10 @@ PHP_FUNCTION(curl_escape)
RETURN_FALSE;
}
if (ZEND_SIZE_T_INT_OVFL(str_len)) {
RETURN_FALSE;
}
if ((res = curl_easy_escape(ch->cp, str, str_len))) {
RETVAL_STRING(res);
curl_free(res);
@ -3556,7 +3560,7 @@ PHP_FUNCTION(curl_unescape)
RETURN_FALSE;
}
if (str_len > INT_MAX) {
if (ZEND_SIZE_T_INT_OVFL(str_len)) {
RETURN_FALSE;
}

View File

@ -3757,6 +3757,10 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse
fgot = php_stream_read(ImageInfo->infile, ImageInfo->Thumbnail.data, ImageInfo->Thumbnail.size);
if (fgot < ImageInfo->Thumbnail.size) {
EXIF_ERRLOG_THUMBEOF(ImageInfo)
efree(ImageInfo->Thumbnail.data);
ImageInfo->Thumbnail.data = NULL;
} else {
exif_thumbnail_build(ImageInfo);
}
exif_thumbnail_build(ImageInfo);
}

View File

@ -0,0 +1,71 @@
--TEST--
Bug #72627 (Memory Leakage In exif_process_IFD_in_TIFF)
--SKIPIF--
<?php if (!extension_loaded('exif')) print 'skip exif extension not available';?>
--FILE--
<?php
$exif = exif_read_data(__DIR__ . '/bug72627.tiff',0,0,true);
var_dump($exif);
?>
--EXPECTF--
Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d
Warning: exif_read_data(%s): Error in TIFF: filesize(x04E2) less than start of IFD dir(x829A0004) in %sbug72627.php on line %d
Warning: exif_read_data(%s): Thumbnail goes IFD boundary or end of file reached in %sbug72627.php on line %d
array(11) {
["FileName"]=>
string(13) "bug72627.tiff"
["FileDateTime"]=>
int(%d)
["FileSize"]=>
int(1250)
["FileType"]=>
int(7)
["MimeType"]=>
string(10) "image/tiff"
["SectionsFound"]=>
string(30) "ANY_TAG, IFD0, THUMBNAIL, EXIF"
["COMPUTED"]=>
array(10) {
["html"]=>
string(24) "width="128" height="132""
["Height"]=>
int(132)
["Width"]=>
int(128)
["IsColor"]=>
int(0)
["ByteOrderMotorola"]=>
int(0)
["ApertureFNumber"]=>
string(5) "f/1.0"
["Thumbnail.FileType"]=>
int(2)
["Thumbnail.MimeType"]=>
string(10) "image/jpeg"
["Thumbnail.Height"]=>
int(132)
["Thumbnail.Width"]=>
int(128)
}
["XResolution"]=>
string(21) "1414812756/1414812756"
["THUMBNAIL"]=>
array(5) {
["ImageWidth"]=>
int(128)
["ImageLength"]=>
int(132)
["JPEGInterchangeFormat"]=>
int(1280)
["JPEGInterchangeFormatLength"]=>
int(100)
["THUMBNAIL"]=>
NULL
}
["ExposureTime"]=>
string(21) "1414812756/1414812756"
["FNumber"]=>
string(21) "1414812756/1414812756"
}

Binary file not shown.

View File

@ -1537,11 +1537,11 @@ PHP_FUNCTION(imagetruecolortopalette)
RETURN_FALSE;
}
if (ncolors <= 0) {
php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero");
if (ncolors <= 0 || ZEND_LONG_INT_OVFL(ncolors)) {
php_error_docref(NULL, E_WARNING, "Number of colors has to be greater than zero and no more than %d", INT_MAX);
RETURN_FALSE;
}
gdImageTrueColorToPalette(im, dither, ncolors);
gdImageTrueColorToPalette(im, dither, (int)ncolors);
RETURN_TRUE;
}
@ -3039,6 +3039,11 @@ PHP_FUNCTION(imagegammacorrect)
return;
}
if ( input <= 0.0 || output <= 0.0 ) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Gamma values should be positive");
RETURN_FALSE;
}
if ((im = (gdImagePtr)zend_fetch_resource(Z_RES_P(IM), "Image", le_gd)) == NULL) {
RETURN_FALSE;
}

View File

@ -0,0 +1,17 @@
--TEST--
Bug #72697: select_colors write out-of-bounds
--SKIPIF--
<?php
if (!function_exists("imagecreatetruecolor")) die("skip");
if (PHP_INT_MAX !== 9223372036854775807) die("skip for 64-bit long systems only");
?>
--FILE--
<?php
$img=imagecreatetruecolor(10, 10);
imagetruecolortopalette($img, false, PHP_INT_MAX / 8);
?>
DONE
--EXPECTF--
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than 2147483647 in %sbug72697.php on line %d
DONE

View File

@ -0,0 +1,15 @@
--TEST--
Bug #72730: imagegammacorrect allows arbitrary write access
--SKIPIF--
<?php
if (!function_exists("imagecreatetruecolor")) die("skip");
?>
--FILE--
<?php
$img = imagecreatetruecolor(1, 1);
imagegammacorrect($img, -1, 1337);
?>
DONE
--EXPECTF--
Warning: imagegammacorrect(): Gamma values should be positive in %sbug72730.php on line %d
DONE

View File

@ -25,4 +25,4 @@ Warning: imagetruecolortopalette() expects parameter 3 to be integer, resource g
Warning: imagetruecolortopalette() expects parameter 3 to be integer, array given in %s on line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s on line %d

View File

@ -16,6 +16,6 @@ imagetruecolortopalette($image, true, -1);
?>
--EXPECTF--
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero in %s on line %d
Warning: imagetruecolortopalette(): Number of colors has to be greater than zero and no more than %d in %s line %d

View File

@ -633,6 +633,10 @@ PHP_FUNCTION(mcrypt_generic)
RETURN_FALSE
}
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
/* Check blocksize */
if (mcrypt_enc_is_block_mode(pm->td) == 1) { /* It's a block algorithm */
block_size = mcrypt_enc_get_block_size(pm->td);
@ -645,10 +649,6 @@ PHP_FUNCTION(mcrypt_generic)
memset(ZSTR_VAL(data_str), 0, data_size);
memcpy(ZSTR_VAL(data_str), data, data_len);
} else { /* It's not a block algorithm */
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
data_size = (int)data_len;
data_str = zend_string_alloc(data_size, 0);
memset(ZSTR_VAL(data_str), 0, data_size);
@ -688,6 +688,10 @@ PHP_FUNCTION(mdecrypt_generic)
}
/* Check blocksize */
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
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;
@ -699,10 +703,6 @@ PHP_FUNCTION(mdecrypt_generic)
memset(data_s, 0, data_size);
memcpy(data_s, data, data_len);
} else { /* It's not a block algorithm */
if (data_len > INT_MAX) {
php_error_docref(NULL, E_WARNING, "Data size too large, %d maximum", INT_MAX);
RETURN_FALSE;
}
data_size = (int)data_len;
data_s = emalloc(data_size + 1);
memset(data_s, 0, data_size);

View File

@ -1011,7 +1011,7 @@ static int php_snmp_parse_oid(zval *object, int st, struct objid_query *objid_qu
php_error_docref(NULL, E_WARNING, "Got empty OID array");
return FALSE;
}
objid_query->vars = (snmpobjarg *)emalloc(sizeof(snmpobjarg) * zend_hash_num_elements(Z_ARRVAL_P(oid)));
objid_query->vars = (snmpobjarg *)safe_emalloc(sizeof(snmpobjarg), zend_hash_num_elements(Z_ARRVAL_P(oid)), 0);
if (objid_query->vars == NULL) {
php_error_docref(NULL, E_WARNING, "emalloc() failed while parsing oid array: %s", strerror(errno));
efree(objid_query->vars);

View File

@ -188,7 +188,8 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char
/* get the response */
result = GET_FTP_RESULT(stream);
if (result != 334) {
use_ssl = 0;
php_stream_wrapper_log_error(wrapper, options, "Server doesn't support FTPS.");
goto connect_errexit;
} else {
/* we must reuse the old SSL session id */
/* if we talk to an old ftpd-ssl */

View File

@ -52,19 +52,22 @@
#define SMART_STRING_DO_REALLOC(d, what) \
(d)->c = SMART_STRING_REALLOC((d)->c, (d)->a + 1, (what))
#define smart_string_alloc4(d, n, what, newlen) do { \
#define smart_string_alloc4(d, n, what, newlen) do { \
if (!(d)->c) { \
(d)->len = 0; \
newlen = (n); \
(d)->a = newlen < SMART_STRING_START_SIZE \
? SMART_STRING_START_SIZE \
: newlen + SMART_STRING_PREALLOC; \
SMART_STRING_DO_REALLOC(d, what); \
(d)->a = newlen < SMART_STRING_START_SIZE \
? SMART_STRING_START_SIZE \
: newlen + SMART_STRING_PREALLOC; \
SMART_STRING_DO_REALLOC(d, what); \
} else { \
if(UNEXPECTED(n > SIZE_MAX - (d)->len)) { \
zend_error(E_ERROR, "String size overflow"); \
} \
newlen = (d)->len + (n); \
if (newlen >= (d)->a) { \
(d)->a = newlen + SMART_STRING_PREALLOC; \
SMART_STRING_DO_REALLOC(d, what); \
(d)->a = newlen + SMART_STRING_PREALLOC; \
SMART_STRING_DO_REALLOC(d, what); \
} \
} \
} while (0)

View File

@ -1,5 +1,7 @@
--TEST--
Bug #72142: WDDX Packet Injection Vulnerability in wddx_serialize_value()
--SKIPIF--
<?php if (!extension_loaded("wddx")) print "skip"; ?>
--FILE--
<?php

View File

@ -0,0 +1,34 @@
--TEST--
Bug #72749: wddx_deserialize allows illegal memory access
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<<XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
<data>
<struct>
<var name='aDateTime3'>
<dateTime>2\r2004-09-10T05:52:49+00</dateTime>
</var>
</struct>
</data>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECT--
array(1) {
["aDateTime3"]=>
string(24) "2
2004-09-10T05:52:49+00"
}

View File

@ -0,0 +1,34 @@
--TEST--
Bug #72750: wddx_deserialize null dereference
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<< XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
<header/>
<data>
<struct>
<var name='aBinary'>
<binary length='11'>\\tYmluYXJRhdGE=</binary>
</var>
</struct>
</data>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECT--
array(1) {
["aBinary"]=>
string(0) ""
}

View File

@ -0,0 +1,36 @@
--TEST--
Bug 72790: wddx_deserialize null dereference with invalid xml
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<< XML
<?xml version='1.0' ?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version='1.0'>
|array>
<var name="XXXX">
<boolean value="this">
</boolean>
</var>
<var name="YYYY">
<var name="UUUU">
<var name="EZEZ">
</var>
</var>
</var>
</array>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECTF--
Notice: Undefined variable: array in %s%ebug72790.php on line %d
NULL

View File

@ -0,0 +1,29 @@
--TEST--
Bug #72799: wddx_deserialize null dereference in php_wddx_pop_element
--SKIPIF--
<?php
if (!extension_loaded('wddx')) {
die('skip. wddx not available');
}
?>
--FILE--
<?php
$xml = <<<XML
<?xml version='1.0'?>
<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'>
<wddxPacket version="1.0">
<var name="XXXX">
<boolean value="1">
<dateTime>1998-06-12T04:32:12+00</dateTime>
</boolean>
</var>
</wddxPacket>
XML;
$array = wddx_deserialize($xml);
var_dump($array);
?>
--EXPECTF--
Notice: Undefined variable: array in %s%ebug72799.php on line 16
NULL

View File

@ -886,10 +886,10 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
if (Z_TYPE(ent1->data) == IS_UNDEF) {
if (stack->top > 1) {
stack->top--;
efree(ent1);
} else {
stack->done = 1;
}
efree(ent1);
return;
}
@ -897,7 +897,11 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name)
zend_string *new_str = php_base64_decode(
(unsigned char *)Z_STRVAL(ent1->data), Z_STRLEN(ent1->data));
zval_ptr_dtor(&ent1->data);
ZVAL_STR(&ent1->data, new_str);
if (new_str) {
ZVAL_STR(&ent1->data, new_str);
} else {
ZVAL_EMPTY_STRING(&ent1->data);
}
}
/* Call __wakeup() method on the object. */
@ -1034,14 +1038,22 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len)
case ST_DATETIME: {
char *tmp;
tmp = emalloc(len + 1);
memcpy(tmp, (char *)s, len);
if (Z_TYPE(ent->data) == IS_STRING) {
tmp = safe_emalloc(Z_STRLEN(ent->data), 1, (size_t)len + 1);
memcpy(tmp, Z_STRVAL(ent->data), Z_STRLEN(ent->data));
memcpy(tmp + Z_STRLEN(ent->data), s, len);
len += Z_STRLEN(ent->data);
zval_dtor(&ent->data);
} else {
tmp = emalloc(len + 1);
memcpy(tmp, (char *)s, len);
}
tmp[len] = '\0';
Z_LVAL(ent->data) = php_parse_date(tmp, NULL);
ZVAL_LONG(&ent->data, php_parse_date(tmp, NULL));
/* date out of range < 1969 or > 2038 */
if (Z_LVAL(ent->data) == -1) {
ZVAL_STRINGL(&ent->data, (char *)s, len);
ZVAL_STRINGL(&ent->data, (char *)tmp, len);
}
efree(tmp);
}

View File

@ -144,7 +144,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
char *path_file;
int resolved_basedir_len;
int resolved_name_len;
int path_len;
size_t path_len;
int nesting_level = 0;
/* Special case basedir==".": Use script-directory */
@ -153,7 +153,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
strlcpy(local_open_basedir, basedir, sizeof(local_open_basedir));
}
path_len = (int)strlen(path);
path_len = strlen(path);
if (path_len > (MAXPATHLEN - 1)) {
/* empty and too long paths are invalid */
return -1;
@ -164,7 +164,7 @@ PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path
return -1;
}
path_len = (int)strlen(resolved_name);
path_len = strlen(resolved_name);
memcpy(path_tmp, resolved_name, path_len + 1); /* safe */
while (VCWD_REALPATH(path_tmp, resolved_name) == NULL) {