diff options
author | Stanislav Malyshev <stas@php.net> | 2016-08-17 00:23:51 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2016-08-17 00:43:33 -0700 |
commit | 0d13325b660b5ae64267dffcc9a153c7634fdfe2 (patch) | |
tree | b0be1d511a7eb0c18575f9368dc0d7d3d1828d3f | |
parent | 75d7666968573a0abea36b46aae2b0c0ad6eb488 (diff) | |
parent | 9e00ad2b091f3bbb6e34656c06eb7601fbadb7ce (diff) | |
download | php-git-0d13325b660b5ae64267dffcc9a153c7634fdfe2.tar.gz |
Merge branch 'PHP-5.6' into PHP-7.0
* PHP-5.6: (24 commits)
Update NEWS
BLock test with memory leak
fix tests
Fix TSRM build
Fix bug #72850 - integer overflow in uuencode
Fixed bug #72849 - integer overflow in urlencode
Fix bug #72848 - integer overflow in quoted_printable_encode caused heap corruption
Fix bug #72838 - Integer overflow lead to heap corruption in sql_regcase
Fix bug #72837 - integer overflow in bzdecompress caused heap corruption
Fix bug #72836 - integer overflow in base64_decode caused heap corruption
Fix for bug #72807 - do not produce strings with negative length
Fix for bug #72790 and bug #72799
Fix bug #72730 - imagegammacorrect allows arbitrary write access
Fix bug#72697 - select_colors write out-of-bounds
Fixed bug #72627: Memory Leakage In exif_process_IFD_in_TIFF
Fix bug #72750: wddx_deserialize null dereference
Fix bug #72771: ftps:// opendir wrapper is vulnerable to protocol downgrade attack
Improve fix for #72663
Fix bug #70436: Use After Free Vulnerability in unserialize()
Fix bug #72749: wddx_deserialize allows illegal memory access
...
Conflicts:
Zend/zend_API.h
ext/bz2/bz2.c
ext/curl/interface.c
ext/ereg/ereg.c
ext/exif/exif.c
ext/gd/gd.c
ext/gd/tests/imagetruecolortopalette_error3.phpt
ext/gd/tests/imagetruecolortopalette_error4.phpt
ext/session/session.c
ext/snmp/snmp.c
ext/standard/base64.c
ext/standard/ftp_fopen_wrapper.c
ext/standard/quot_print.c
ext/standard/url.c
ext/standard/uuencode.c
ext/standard/var.c
ext/standard/var_unserializer.c
ext/standard/var_unserializer.re
ext/wddx/tests/bug72790.phpt
ext/wddx/tests/bug72799.phpt
ext/wddx/wddx.c
sapi/cli/generate_mime_type_map.php
-rw-r--r-- | ext/exif/exif.c | 1 | ||||
-rw-r--r-- | ext/session/session.c | 21 | ||||
-rw-r--r-- | ext/session/tests/bug72681.phpt | 16 | ||||
-rw-r--r-- | ext/standard/base64.c | 2 | ||||
-rw-r--r-- | ext/standard/quot_print.c | 2 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug70436.phpt | 65 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug72663.phpt | 26 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug72663_2.phpt | 17 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug72663_3.phpt | 20 | ||||
-rw-r--r-- | ext/standard/uuencode.c | 6 | ||||
-rw-r--r-- | ext/standard/var_unserializer.c | 29 | ||||
-rw-r--r-- | ext/wddx/wddx.c | 11 |
12 files changed, 187 insertions, 29 deletions
diff --git a/ext/exif/exif.c b/ext/exif/exif.c index 2594cadf51..f0c631e07b 100644 --- a/ext/exif/exif.c +++ b/ext/exif/exif.c @@ -3762,7 +3762,6 @@ static int exif_process_IFD_in_TIFF(image_info_type *ImageInfo, size_t dir_offse } else { exif_thumbnail_build(ImageInfo); } - exif_thumbnail_build(ImageInfo); } #ifdef EXIF_DEBUG exif_error_docref(NULL EXIFERR_CC, ImageInfo, E_NOTICE, "Read next IFD (THUMBNAIL) done"); diff --git a/ext/session/session.c b/ext/session/session.c index 380cad5b58..48cd0f1bdf 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -963,11 +963,13 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ int namelen; zend_string *name; php_unserialize_data_t var_hash; + int skip = 0; PHP_VAR_UNSERIALIZE_INIT(var_hash); for (p = val; p < endptr; ) { zval *tmp; + skip = 0; namelen = ((unsigned char)(*p)) & (~PS_BIN_UNDEF); if (namelen < 0 || namelen > PS_BIN_MAX || (p + namelen) >= endptr) { @@ -984,8 +986,7 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ if ((tmp = zend_hash_find(&EG(symbol_table), name))) { if ((Z_TYPE_P(tmp) == IS_ARRAY && Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) { - zend_string_release(name); - continue; + skip = 1; } } @@ -994,7 +995,9 @@ PS_SERIALIZER_DECODE_FUNC(php_binary) /* {{{ */ current = var_tmp_var(&var_hash); if (php_var_unserialize(current, (const unsigned char **) &p, (const unsigned char *) endptr, &var_hash)) { ZVAL_PTR(&rv, current); - php_set_session_var(name, &rv, &var_hash ); + if (!skip) { + php_set_session_var(name, &rv, &var_hash); + } } else { zend_string_release(name); php_session_normalize_vars(); @@ -1056,6 +1059,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ zend_string *name; int has_value, retval = SUCCESS; php_unserialize_data_t var_hash; + int skip = 0; PHP_VAR_UNSERIALIZE_INIT(var_hash); @@ -1064,6 +1068,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ while (p < endptr) { zval *tmp; q = p; + skip = 0; while (*q != PS_DELIMITER) { if (++q >= endptr) goto break_outer_loop; } @@ -1081,7 +1086,7 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ if ((tmp = zend_hash_find(&EG(symbol_table), name))) { if ((Z_TYPE_P(tmp) == IS_ARRAY && Z_ARRVAL_P(tmp) == &EG(symbol_table)) || tmp == &PS(http_session_vars)) { - goto skip; + skip = 1; } } @@ -1090,14 +1095,18 @@ PS_SERIALIZER_DECODE_FUNC(php) /* {{{ */ current = var_tmp_var(&var_hash); if (php_var_unserialize(current, (const unsigned char **)&q, (const unsigned char *)endptr, &var_hash)) { ZVAL_PTR(&rv, current); - php_set_session_var(name, &rv, &var_hash); + if (!skip) { + php_set_session_var(name, &rv, &var_hash); + } } else { zend_string_release(name); retval = FAILURE; goto break_outer_loop; } } else { - PS_ADD_VARL(name); + if(!skip) { + PS_ADD_VARL(name); + } } skip: zend_string_release(name); diff --git a/ext/session/tests/bug72681.phpt b/ext/session/tests/bug72681.phpt new file mode 100644 index 0000000000..ca38b07fc9 --- /dev/null +++ b/ext/session/tests/bug72681.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #72681: PHP Session Data Injection Vulnerability +--SKIPIF-- +<?php include('skipif.inc'); ?> +--FILE-- +<?php +ini_set('session.serialize_handler', 'php'); +session_start(); +$_SESSION['_SESSION'] = 'ryat|O:8:"stdClass":0:{}'; +session_write_close(); +session_start(); +var_dump($_SESSION); +?> +--EXPECT-- +array(0) { +} diff --git a/ext/standard/base64.c b/ext/standard/base64.c index d625dc0752..f6dbdf577a 100644 --- a/ext/standard/base64.c +++ b/ext/standard/base64.c @@ -59,7 +59,7 @@ PHPAPI zend_string *php_base64_encode(const unsigned char *str, size_t length) / unsigned char *p; zend_string *result; - result = zend_string_alloc(((length + 2) / 3) * 4 * sizeof(char), 0); + result = zend_string_safe_alloc(((length + 2) / 3), 4 * sizeof(char), 0, 0); p = (unsigned char *)ZSTR_VAL(result); while (length > 2) { /* keep going until we have less than 24 bits */ diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c index a55b1e5edc..be352cbf80 100644 --- a/ext/standard/quot_print.c +++ b/ext/standard/quot_print.c @@ -275,7 +275,7 @@ PHP_FUNCTION(quoted_printable_encode) RETURN_EMPTY_STRING(); } - new_str = php_quot_print_encode((unsigned char *)ZSTR_VAL(str), (size_t)ZSTR_LEN(str)); + new_str = php_quot_print_encode((unsigned char *)ZSTR_VAL(str), ZSTR_LEN(str)); RETURN_STR(new_str); } /* }}} */ diff --git a/ext/standard/tests/strings/bug70436.phpt b/ext/standard/tests/strings/bug70436.phpt new file mode 100644 index 0000000000..c62e468726 --- /dev/null +++ b/ext/standard/tests/strings/bug70436.phpt @@ -0,0 +1,65 @@ +--TEST-- +Bug #70436: Use After Free Vulnerability in unserialize() +--FILE-- +<?php + +class obj implements Serializable +{ + var $data; + + function serialize() + { + return serialize($this->data); + } + + function unserialize($data) + { + $this->data = unserialize($data); + } +} + +$fakezval = ptr2str(1122334455); +$fakezval .= ptr2str(0); +$fakezval .= "\x00\x00\x00\x00"; +$fakezval .= "\x01"; +$fakezval .= "\x00"; +$fakezval .= "\x00\x00"; + +$inner = 'C:3:"obj":3:{ryat'; +$exploit = 'a:4:{i:0;i:1;i:1;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:2;s:'.strlen($fakezval).':"'.$fakezval.'";i:3;R:5;}'; + +$data = unserialize($exploit); + +var_dump($data); + +function ptr2str($ptr) +{ + $out = ''; + + for ($i = 0; $i < 8; $i++) { + $out .= chr($ptr & 0xff); + $ptr >>= 8; + } + + return $out; +} +?> +DONE +--EXPECTF-- +Notice: unserialize(): Error at offset 0 of 3 bytes in %sbug70436.php on line %d + +Notice: unserialize(): Error at offset 17 of 17 bytes in %sbug70436.php on line %d +array(4) { + [0]=> + int(1) + [1]=> + object(obj)#%d (1) { + ["data"]=> + bool(false) + } + [2]=> + string(24) "%s" + [3]=> + bool(false) +} +DONE
\ No newline at end of file diff --git a/ext/standard/tests/strings/bug72663.phpt b/ext/standard/tests/strings/bug72663.phpt new file mode 100644 index 0000000000..e61f939d4d --- /dev/null +++ b/ext/standard/tests/strings/bug72663.phpt @@ -0,0 +1,26 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--FILE-- +<?php +class obj implements Serializable { + var $data; + function serialize() { + return serialize($this->data); + } + function unserialize($data) { + $this->data = unserialize($data); + } +} + +$inner = 'a:1:{i:0;O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:4;}'; +$exploit = 'a:2:{i:0;C:3:"obj":'.strlen($inner).':{'.$inner.'}i:1;R:4;}'; + +$data = unserialize($exploit); +echo $data[1]; +?> +DONE +--EXPECTF-- +Notice: unserialize(): Unexpected end of serialized data in %sbug72663.php on line %d + +Notice: unserialize(): Error at offset 46 of 47 bytes in %sbug72663.php on line %d +DONE
\ No newline at end of file diff --git a/ext/standard/tests/strings/bug72663_2.phpt b/ext/standard/tests/strings/bug72663_2.phpt new file mode 100644 index 0000000000..ac605e9fd2 --- /dev/null +++ b/ext/standard/tests/strings/bug72663_2.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--FILE-- +<?php + +ini_set('session.serialize_handler', 'php_serialize'); +session_start(); +$sess = 'O:9:"Exception":2:{s:7:"'."\0".'*'."\0".'file";R:1;}'; +session_decode($sess); +var_dump($_SESSION); +?> +DONE +--EXPECTF-- +Notice: session_decode(): Unexpected end of serialized data in %sbug72663_2.php on line %d +array(0) { +} +DONE
\ No newline at end of file diff --git a/ext/standard/tests/strings/bug72663_3.phpt b/ext/standard/tests/strings/bug72663_3.phpt new file mode 100644 index 0000000000..f7d66efd17 --- /dev/null +++ b/ext/standard/tests/strings/bug72663_3.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #72663: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization +--XFAIL-- +Memory leak, TBF later. +--FILE-- +<?php +class obj { + var $ryat; + function __wakeup() { + $this->ryat = str_repeat('A', 0x112); + } +} + +$poc = 'O:8:"stdClass":1:{i:0;O:3:"obj":1:{s:4:"ryat";R:1;'; +unserialize($poc); +?> +DONE +--EXPECTF-- +Notice: unserialize(): Error at offset 51 of 50 bytes in %sbug72663_3.php on line %d +DONE diff --git a/ext/standard/uuencode.c b/ext/standard/uuencode.c index e443337ec4..787569e430 100644 --- a/ext/standard/uuencode.c +++ b/ext/standard/uuencode.c @@ -71,8 +71,10 @@ PHPAPI zend_string *php_uuencode(char *src, size_t src_len) /* {{{ */ char *p, *s, *e, *ee; zend_string *dest; - /* encoded length is ~ 38% greater than the original */ - dest = zend_string_alloc((size_t)ceil(src_len * 1.38) + 46, 0); + /* encoded length is ~ 38% greater than the original + Use 1.5 for easier calculation. + */ + dest = zend_string_safe_alloc(src_len/2, 3, 46, 0); p = ZSTR_VAL(dest); s = src; e = src + src_len; diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 3fc074dd6a..f464c0b63a 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 */ +/* Generated by re2c 0.13.7.5 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ @@ -651,7 +651,8 @@ yy20: if (yybm[0+yych] & 128) { goto yy20; } - if (yych != ':') goto yy18; + if (yych <= '/') goto yy18; + if (yych >= ';') goto yy18; yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; @@ -800,7 +801,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 804 "ext/standard/var_unserializer.c" +#line 805 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -832,7 +833,7 @@ yy27: return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 836 "ext/standard/var_unserializer.c" +#line 837 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -877,7 +878,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 881 "ext/standard/var_unserializer.c" +#line 882 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -932,7 +933,7 @@ yy41: ZVAL_STR(rval, str); return 1; } -#line 936 "ext/standard/var_unserializer.c" +#line 937 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -985,7 +986,7 @@ yy48: ZVAL_STRINGL(rval, str, len); return 1; } -#line 989 "ext/standard/var_unserializer.c" +#line 990 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1082,7 +1083,7 @@ use_double: ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1086 "ext/standard/var_unserializer.c" +#line 1087 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1157,7 +1158,7 @@ yy73: return 1; } -#line 1161 "ext/standard/var_unserializer.c" +#line 1162 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1210,7 +1211,7 @@ yy79: ZVAL_LONG(rval, parse_iv(start + 2)); return 1; } -#line 1214 "ext/standard/var_unserializer.c" +#line 1215 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1224,7 +1225,7 @@ yy83: ZVAL_BOOL(rval, parse_iv(start + 2)); return 1; } -#line 1228 "ext/standard/var_unserializer.c" +#line 1229 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; #line 573 "ext/standard/var_unserializer.re" @@ -1233,7 +1234,7 @@ yy87: ZVAL_NULL(rval); return 1; } -#line 1237 "ext/standard/var_unserializer.c" +#line 1238 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1281,7 +1282,7 @@ yy91: return 1; } -#line 1285 "ext/standard/var_unserializer.c" +#line 1286 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1330,7 +1331,7 @@ yy97: return 1; } -#line 1334 "ext/standard/var_unserializer.c" +#line 1335 "ext/standard/var_unserializer.c" } #line 886 "ext/standard/var_unserializer.re" diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index a11efe66de..08f9c4f37e 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -921,7 +921,7 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) wddx_stack_top(stack, (void**)&ent2); /* if non-existent field */ - if (ent2->type == ST_FIELD && Z_ISUNDEF(ent2->data)) { + if (Z_ISUNDEF(ent2->data)) { zval_ptr_dtor(&ent1->data); efree(ent1); return; @@ -1055,7 +1055,6 @@ static void php_wddx_process_data(void *user_data, const XML_Char *s, int len) if (Z_LVAL(ent->data) == -1) { ZVAL_STRINGL(&ent->data, (char *)tmp, len); } - efree(tmp); } break; @@ -1089,8 +1088,12 @@ int php_wddx_deserialize_ex(const char *value, size_t vallen, zval *return_value if (stack.top == 1) { wddx_stack_top(&stack, (void**)&ent); - ZVAL_COPY(return_value, &ent->data); - retval = SUCCESS; + if (IS_UNDEF(ent->data)) { + retval = FAILURE; + } else { + ZVAL_COPY(return_value, &ent->data); + retval = SUCCESS; + } } else { retval = FAILURE; } |