summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStanislav Malyshev <stas@php.net>2016-08-17 00:23:51 -0700
committerStanislav Malyshev <stas@php.net>2016-08-17 00:43:33 -0700
commit0d13325b660b5ae64267dffcc9a153c7634fdfe2 (patch)
treeb0be1d511a7eb0c18575f9368dc0d7d3d1828d3f
parent75d7666968573a0abea36b46aae2b0c0ad6eb488 (diff)
parent9e00ad2b091f3bbb6e34656c06eb7601fbadb7ce (diff)
downloadphp-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.c1
-rw-r--r--ext/session/session.c21
-rw-r--r--ext/session/tests/bug72681.phpt16
-rw-r--r--ext/standard/base64.c2
-rw-r--r--ext/standard/quot_print.c2
-rw-r--r--ext/standard/tests/strings/bug70436.phpt65
-rw-r--r--ext/standard/tests/strings/bug72663.phpt26
-rw-r--r--ext/standard/tests/strings/bug72663_2.phpt17
-rw-r--r--ext/standard/tests/strings/bug72663_3.phpt20
-rw-r--r--ext/standard/uuencode.c6
-rw-r--r--ext/standard/var_unserializer.c29
-rw-r--r--ext/wddx/wddx.c11
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;
}