diff options
Diffstat (limited to 'cve-php5.3.patch')
-rw-r--r-- | cve-php5.3.patch | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/cve-php5.3.patch b/cve-php5.3.patch new file mode 100644 index 000000000000..5f8ff7b66a99 --- /dev/null +++ b/cve-php5.3.patch @@ -0,0 +1,842 @@ +--- a/ext/fileinfo/libmagic/cdf.c ++++ b/ext/fileinfo/libmagic/cdf.c +@@ -820,7 +820,7 @@ + q = (const uint8_t *)(const void *) + ((const char *)(const void *)p + ofs + - 2 * sizeof(uint32_t)); +- if (q > e) { ++ if (q < p || q > e) { + DPRINTF(("Ran of the end %p > %p\n", q, e)); + goto out; + } +--- a/ext/standard/dns.c ++++ b/ext/standard/dns.c +@@ -412,8 +412,14 @@ + + #if HAVE_FULL_DNS_FUNCS + ++#define CHECKCP(n) do { \ ++ if (cp + n > end) { \ ++ return NULL; \ ++ } \ ++} while (0) ++ + /* {{{ php_parserr */ +-static u_char *php_parserr(u_char *cp, querybuf *answer, int type_to_fetch, int store, zval **subarray) ++static u_char *php_parserr(u_char *cp, u_char *end, querybuf *answer, int type_to_fetch, int store, zval **subarray) + { + u_short type, class, dlen; + u_long ttl; +@@ -425,16 +431,18 @@ + + *subarray = NULL; + +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, sizeof(name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, sizeof(name) - 2); + if (n < 0) { + return NULL; + } + cp += n; + ++ CHECKCP(10); + GETSHORT(type, cp); + GETSHORT(class, cp); + GETLONG(ttl, cp); + GETSHORT(dlen, cp); ++ CHECKCP(dlen); + if (type_to_fetch != T_ANY && type != type_to_fetch) { + cp += dlen; + return cp; +@@ -451,12 +459,14 @@ + add_assoc_string(*subarray, "host", name, 1); + switch (type) { + case DNS_T_A: ++ CHECKCP(4); + add_assoc_string(*subarray, "type", "A", 1); + snprintf(name, sizeof(name), "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); + add_assoc_string(*subarray, "ip", name, 1); + cp += dlen; + break; + case DNS_T_MX: ++ CHECKCP(2); + add_assoc_string(*subarray, "type", "MX", 1); + GETSHORT(n, cp); + add_assoc_long(*subarray, "pri", n); +@@ -475,7 +485,7 @@ + if (type == DNS_T_PTR) { + add_assoc_string(*subarray, "type", "PTR", 1); + } +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -485,18 +495,22 @@ + case DNS_T_HINFO: + /* See RFC 1010 for values */ + add_assoc_string(*subarray, "type", "HINFO", 1); ++ CHECKCP(1); + n = *cp & 0xFF; + cp++; ++ CHECKCP(n); + add_assoc_stringl(*subarray, "cpu", (char*)cp, n, 1); + cp += n; ++ CHECKCP(1); + n = *cp & 0xFF; + cp++; ++ CHECKCP(n); + add_assoc_stringl(*subarray, "os", (char*)cp, n, 1); + cp += n; + break; + case DNS_T_TXT: + { +- int ll = 0; ++ int l1 = 0, l2 = 0; + zval *entries = NULL; + + add_assoc_string(*subarray, "type", "TXT", 1); +@@ -505,37 +519,41 @@ + MAKE_STD_ZVAL(entries); + array_init(entries); + +- while (ll < dlen) { +- n = cp[ll]; +- if ((ll + n) >= dlen) { ++ while (l1 < dlen) { ++ n = cp[l1]; ++ if ((l1 + n) >= dlen) { + // Invalid chunk length, truncate +- n = dlen - (ll + 1); ++ n = dlen - (l1 + 1); + } +- memcpy(tp + ll , cp + ll + 1, n); +- add_next_index_stringl(entries, cp + ll + 1, n, 1); +- ll = ll + n + 1; ++ if (n) { ++ memcpy(tp + l2 , cp + l1 + 1, n); ++ add_next_index_stringl(entries, cp + l1 + 1, n, 1); ++ } ++ l1 = l1 + n + 1; ++ l2 = l2 + n; + } +- tp[dlen] = '\0'; ++ tp[l2] = '\0'; + cp += dlen; + +- add_assoc_stringl(*subarray, "txt", tp, (dlen>0)?dlen - 1:0, 0); ++ add_assoc_stringl(*subarray, "txt", tp, l2, 0); + add_assoc_zval(*subarray, "entries", entries); + } + break; + case DNS_T_SOA: + add_assoc_string(*subarray, "type", "SOA", 1); +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); + if (n < 0) { + return NULL; + } + cp += n; + add_assoc_string(*subarray, "mname", name, 1); +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) -2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) -2); + if (n < 0) { + return NULL; + } + cp += n; + add_assoc_string(*subarray, "rname", name, 1); ++ CHECKCP(5*4); + GETLONG(n, cp); + add_assoc_long(*subarray, "serial", n); + GETLONG(n, cp); +@@ -549,6 +567,7 @@ + break; + case DNS_T_AAAA: + tp = (u_char*)name; ++ CHECKCP(8*2); + for(i=0; i < 8; i++) { + GETSHORT(s, cp); + if (s != 0) { +@@ -583,6 +602,7 @@ + case DNS_T_A6: + p = cp; + add_assoc_string(*subarray, "type", "A6", 1); ++ CHECKCP(1); + n = ((int)cp[0]) & 0xFF; + cp++; + add_assoc_long(*subarray, "masklen", n); +@@ -618,6 +638,7 @@ + cp++; + } + for (i = (n + 8) / 16; i < 8; i++) { ++ CHECKCP(2); + GETSHORT(s, cp); + if (s != 0) { + if (tp > (u_char *)name) { +@@ -647,7 +668,7 @@ + tp[0] = '\0'; + add_assoc_string(*subarray, "ipv6", name, 1); + if (cp < p + dlen) { +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -656,6 +677,7 @@ + } + break; + case DNS_T_SRV: ++ CHECKCP(3*2); + add_assoc_string(*subarray, "type", "SRV", 1); + GETSHORT(n, cp); + add_assoc_long(*subarray, "pri", n); +@@ -663,7 +685,7 @@ + add_assoc_long(*subarray, "weight", n); + GETSHORT(n, cp); + add_assoc_long(*subarray, "port", n); +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -671,21 +693,35 @@ + add_assoc_string(*subarray, "target", name, 1); + break; + case DNS_T_NAPTR: ++ CHECKCP(2*2); + add_assoc_string(*subarray, "type", "NAPTR", 1); + GETSHORT(n, cp); + add_assoc_long(*subarray, "order", n); + GETSHORT(n, cp); + add_assoc_long(*subarray, "pref", n); ++ ++ CHECKCP(1); + n = (cp[0] & 0xFF); +- add_assoc_stringl(*subarray, "flags", (char*)++cp, n, 1); ++ cp++; ++ CHECKCP(n); ++ add_assoc_stringl(*subarray, "flags", (char*)cp, n, 1); + cp += n; ++ ++ CHECKCP(1); + n = (cp[0] & 0xFF); +- add_assoc_stringl(*subarray, "services", (char*)++cp, n, 1); ++ cp++; ++ CHECKCP(n); ++ add_assoc_stringl(*subarray, "services", (char*)cp, n, 1); + cp += n; ++ ++ CHECKCP(1); + n = (cp[0] & 0xFF); +- add_assoc_stringl(*subarray, "regex", (char*)++cp, n, 1); ++ cp++; ++ CHECKCP(n); ++ add_assoc_stringl(*subarray, "regex", (char*)cp, n, 1); + cp += n; +- n = dn_expand(answer->qb2, answer->qb2+65536, cp, name, (sizeof name) - 2); ++ ++ n = dn_expand(answer->qb2, end, cp, name, (sizeof name) - 2); + if (n < 0) { + return NULL; + } +@@ -852,7 +888,7 @@ + while (an-- && cp && cp < end) { + zval *retval; + +- cp = php_parserr(cp, &answer, type_to_fetch, store_results, &retval); ++ cp = php_parserr(cp, end, &answer, type_to_fetch, store_results, &retval); + if (retval != NULL && store_results) { + add_next_index_zval(return_value, retval); + } +@@ -865,7 +901,7 @@ + while (ns-- > 0 && cp && cp < end) { + zval *retval = NULL; + +- cp = php_parserr(cp, &answer, DNS_T_ANY, authns != NULL, &retval); ++ cp = php_parserr(cp, end, &answer, DNS_T_ANY, authns != NULL, &retval); + if (retval != NULL) { + add_next_index_zval(authns, retval); + } +@@ -877,7 +913,7 @@ + while (ar-- > 0 && cp && cp < end) { + zval *retval = NULL; + +- cp = php_parserr(cp, &answer, DNS_T_ANY, 1, &retval); ++ cp = php_parserr(cp, end, &answer, DNS_T_ANY, 1, &retval); + if (retval != NULL) { + add_next_index_zval(addtl, retval); + } +diff --git a/ext/xmlrpc/libxmlrpc/xmlrpc.c b/ext/xmlrpc/libxmlrpc/xmlrpc.c +index ce70c2a..b766a54 100644 +--- a/ext/xmlrpc/libxmlrpc/xmlrpc.c ++++ b/ext/xmlrpc/libxmlrpc/xmlrpc.c +@@ -219,16 +219,19 @@ + n = 10; + tm.tm_mon = 0; + for(i = 0; i < 2; i++) { +- XMLRPC_IS_NUMBER(text[i]) ++ XMLRPC_IS_NUMBER(text[i+4]) + tm.tm_mon += (text[i+4]-'0')*n; + n /= 10; + } + tm.tm_mon --; ++ if(tm.tm_mon < 0 || tm.tm_mon > 11) { ++ return -1; ++ } + + n = 10; + tm.tm_mday = 0; + for(i = 0; i < 2; i++) { +- XMLRPC_IS_NUMBER(text[i]) ++ XMLRPC_IS_NUMBER(text[i+6]) + tm.tm_mday += (text[i+6]-'0')*n; + n /= 10; + } +@@ -236,7 +239,7 @@ + n = 10; + tm.tm_hour = 0; + for(i = 0; i < 2; i++) { +- XMLRPC_IS_NUMBER(text[i]) ++ XMLRPC_IS_NUMBER(text[i+9]) + tm.tm_hour += (text[i+9]-'0')*n; + n /= 10; + } +@@ -244,7 +247,7 @@ + n = 10; + tm.tm_min = 0; + for(i = 0; i < 2; i++) { +- XMLRPC_IS_NUMBER(text[i]) ++ XMLRPC_IS_NUMBER(text[i+12]) + tm.tm_min += (text[i+12]-'0')*n; + n /= 10; + } +@@ -252,7 +255,7 @@ + n = 10; + tm.tm_sec = 0; + for(i = 0; i < 2; i++) { +- XMLRPC_IS_NUMBER(text[i]) ++ XMLRPC_IS_NUMBER(text[i+15]) + tm.tm_sec += (text[i+15]-'0')*n; + n /= 10; + } +--- /dev/null ++++ b/ext/xmlrpc/tests/bug68027.phpt +@@ -0,0 +1,44 @@ ++--TEST-- ++Bug #68027 (buffer overflow in mkgmtime() function) ++--SKIPIF-- ++<?php ++if (!extension_loaded("xmlrpc")) print "skip"; ++?> ++--FILE-- ++<?php ++ ++$d = '6-01-01 20:00:00'; ++xmlrpc_set_type($d, 'datetime'); ++var_dump($d); ++$datetime = "2001-0-08T21:46:40-0400"; ++$obj = xmlrpc_decode("<?xml version=\"1.0\"?><methodResponse><params><param><value><dateTime.iso8601>$datetime</dateTime.iso8601></value></param></params></methodResponse>"); ++print_r($obj); ++ ++$datetime = "34770-0-08T21:46:40-0400"; ++$obj = xmlrpc_decode("<?xml version=\"1.0\"?><methodResponse><params><param><value><dateTime.iso8601>$datetime</dateTime.iso8601></value></param></params></methodResponse>"); ++print_r($obj); ++ ++echo "Done\n"; ++?> ++--EXPECTF-- ++object(stdClass)#1 (3) { ++ ["scalar"]=> ++ string(16) "6-01-01 20:00:00" ++ ["xmlrpc_type"]=> ++ string(8) "datetime" ++ ["timestamp"]=> ++ int(%d) ++} ++stdClass Object ++( ++ [scalar] => 2001-0-08T21:46:40-0400 ++ [xmlrpc_type] => datetime ++ [timestamp] => %s ++) ++stdClass Object ++( ++ [scalar] => 34770-0-08T21:46:40-0400 ++ [xmlrpc_type] => datetime ++ [timestamp] => %d ++) ++Done +--- /dev/null ++++ php5-5.3.10/ext/standard/tests/serialize/bug68044.phpt +@@ -0,0 +1,12 @@ ++--TEST-- ++Bug #68044 Integer overflow in unserialize() (32-bits only) ++--FILE-- ++<?php ++ echo unserialize('C:3:"XYZ":18446744075857035259:{}'); ++?> ++===DONE== ++--EXPECTF-- ++Warning: Insufficient data for unserializing - %d required, 1 present in %s/bug68044.php on line 2 ++ ++Notice: unserialize(): Error at offset 32 of 33 bytes in %s/bug68044.php on line 2 ++===DONE== +--- php5-5.3.10.orig/ext/standard/var_unserializer.c ++++ php5-5.3.10/ext/standard/var_unserializer.c +@@ -333,7 +333,7 @@ + + (*p) += 2; + +- if (datalen < 0 || (*p) + datalen >= max) { ++ if (datalen < 0 || (max - (*p)) <= datalen) { + zend_error(E_WARNING, "Insufficient data for unserializing - %ld required, %ld present", datalen, (long)(max - (*p))); + return 0; + } +--- php5-5.3.10.orig/ext/standard/var_unserializer.re ++++ php5-5.3.10/ext/standard/var_unserializer.re +@@ -339,7 +339,7 @@ + + (*p) += 2; + +- if (datalen < 0 || (*p) + datalen >= max) { ++ if (datalen < 0 || (max - (*p)) <= datalen) { + zend_error(E_WARNING, "Insufficient data for unserializing - %ld required, %ld present", datalen, (long)(max - (*p))); + return 0; + } +--- php5-5.3.10.orig/ext/exif/exif.c ++++ php5-5.3.10/ext/exif/exif.c +@@ -2446,11 +2446,11 @@ + data_ptr += 8; + break; + case TAG_FMT_SINGLE: +- memmove(data_ptr, &info_data->value.f, byte_count); ++ memmove(data_ptr, &info_value->f, 4); + data_ptr += 4; + break; + case TAG_FMT_DOUBLE: +- memmove(data_ptr, &info_data->value.d, byte_count); ++ memmove(data_ptr, &info_value->d, 8); + data_ptr += 8; + break; + } +--- /dev/null ++++ php5-5.3.10/ext/standard/tests/serialize/bug68594.phpt +@@ -0,0 +1,23 @@ ++--TEST-- ++Bug #68545 Use after free vulnerability in unserialize() ++--FILE-- ++<?php ++for ($i=4; $i<100; $i++) { ++ $m = new StdClass(); ++ ++ $u = array(1); ++ ++ $m->aaa = array(1,2,&$u,4,5); ++ $m->bbb = 1; ++ $m->ccc = &$u; ++ $m->ddd = str_repeat("A", $i); ++ ++ $z = serialize($m); ++ $z = str_replace("bbb", "aaa", $z); ++ $y = unserialize($z); ++ $z = serialize($y); ++} ++?> ++===DONE=== ++--EXPECTF-- ++===DONE=== +--- php5-5.3.10.orig/ext/standard/var_unserializer.c ++++ php5-5.3.10/ext/standard/var_unserializer.c +@@ -298,6 +298,9 @@ + } else { + /* object properties should include no integers */ + convert_to_string(key); ++ if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); ++ } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, + sizeof data, NULL); + } +--- php5-5.3.10.orig/ext/standard/var_unserializer.re ++++ php5-5.3.10/ext/standard/var_unserializer.re +@@ -304,6 +304,9 @@ + } else { + /* object properties should include no integers */ + convert_to_string(key); ++ if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ var_push_dtor(var_hash, old_data); ++ } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, + sizeof data, NULL); + } +--- php5-5.3.10.orig/ext/enchant/enchant.c ++++ php5-5.3.10/ext/enchant/enchant.c +@@ -545,13 +545,12 @@ + + d = enchant_broker_request_dict(pbroker->pbroker, (const char *)tag); + if (d) { ++ pos = pbroker->dictcnt++; + if (pbroker->dictcnt) { + pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt); +- pos = pbroker->dictcnt++; + } else { + pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *)); + pos = 0; +- pbroker->dictcnt++; + } + + dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict)); +@@ -606,14 +605,14 @@ + + d = enchant_broker_request_pwl_dict(pbroker->pbroker, (const char *)pwl); + if (d) { ++ pos = pbroker->dictcnt++; + if (pbroker->dictcnt) { +- pos = pbroker->dictcnt++; + pbroker->dict = (enchant_dict **)erealloc(pbroker->dict, sizeof(enchant_dict *) * pbroker->dictcnt); + } else { + pbroker->dict = (enchant_dict **)emalloc(sizeof(enchant_dict *)); + pos = 0; +- pbroker->dictcnt++; + } ++ + dict = pbroker->dict[pos] = (enchant_dict *)emalloc(sizeof(enchant_dict)); + dict->id = pos; + dict->pbroker = pbroker; +--- /dev/null ++++ php5-5.3.10/ext/standard/tests/strings/bug68710.phpt +@@ -0,0 +1,25 @@ ++--TEST-- ++Bug #68710 Use after free vulnerability in unserialize() (bypassing the ++CVE-2014-8142 fix) ++--FILE-- ++<?php ++for ($i=4; $i<100; $i++) { ++ $m = new StdClass(); ++ ++ $u = array(1); ++ ++ $m->aaa = array(1,2,&$u,4,5); ++ $m->bbb = 1; ++ $m->ccc = &$u; ++ $m->ddd = str_repeat("A", $i); ++ ++ $z = serialize($m); ++ $z = str_replace("aaa", "123", $z); ++ $z = str_replace("bbb", "123", $z); ++ $y = unserialize($z); ++ $z = serialize($y); ++} ++?> ++===DONE=== ++--EXPECTF-- ++===DONE=== +--- php5-5.3.10.orig/ext/standard/var_unserializer.c ++++ php5-5.3.10/ext/standard/var_unserializer.c +@@ -298,7 +298,7 @@ + } else { + /* object properties should include no integers */ + convert_to_string(key); +- if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { + var_push_dtor(var_hash, old_data); + } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, +--- php5-5.3.10.orig/ext/standard/var_unserializer.re ++++ php5-5.3.10/ext/standard/var_unserializer.re +@@ -304,7 +304,7 @@ + } else { + /* object properties should include no integers */ + convert_to_string(key); +- if (zend_symtable_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { ++ if (zend_hash_find(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&old_data)==SUCCESS) { + var_push_dtor(var_hash, old_data); + } + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, +--- php5-5.3.10.orig/ext/phar/phar_object.c ++++ php5-5.3.10/ext/phar/phar_object.c +@@ -2320,8 +2320,8 @@ + } + its_ok: + if (SUCCESS == php_stream_stat_path(newpath, &ssb)) { +- efree(oldpath); + zend_throw_exception_ex(spl_ce_BadMethodCallException, 0 TSRMLS_CC, "phar \"%s\" exists and must be unlinked prior to conversion", newpath); ++ efree(oldpath); + return NULL; + } + if (!phar->is_data) { +diff --git a/ext/ereg/regex/regcomp.c b/ext/ereg/regex/regcomp.c +index 156eee9..f4bfc1c 100644 +--- a/ext/ereg/regex/regcomp.c ++++ b/ext/ereg/regex/regcomp.c +@@ -117,7 +117,15 @@ + (NC-1)*sizeof(cat_t)); + if (g == NULL) + return(REG_ESPACE); +- p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ ++ { ++ /* Patched for CERT Vulnerability Note VU#695940, Feb 2015. */ ++ size_t new_ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */ ++ if (new_ssize < len || new_ssize > LONG_MAX / sizeof(sop)) { ++ free((char *) g); ++ return REG_INVARG; ++ } ++ p->ssize = new_ssize; ++ } + p->strip = (sop *)malloc(p->ssize * sizeof(sop)); + p->slen = 0; + if (p->strip == NULL) { +--- php5-5.3.10.orig/ext/phar/phar.c ++++ php5-5.3.10/ext/phar/phar.c +@@ -600,52 +600,41 @@ + * + * Meta-data is in this format: + * [len32][data...] +- * ++ * + * data is the serialized zval + */ +-int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSRMLS_DC) /* {{{ */ ++int phar_parse_metadata(char **buffer, zval **metadata, php_uint32 zip_metadata_len TSRMLS_DC) /* {{{ */ + { +- const unsigned char *p; +- php_uint32 buf_len; + php_unserialize_data_t var_hash; + +- if (!zip_metadata_len) { +- PHAR_GET_32(*buffer, buf_len); +- } else { +- buf_len = zip_metadata_len; +- } +- +- if (buf_len) { ++ if (zip_metadata_len) { ++ const unsigned char *p, *p_buff = estrndup(*buffer, zip_metadata_len); ++ p = p_buff; + ALLOC_ZVAL(*metadata); + INIT_ZVAL(**metadata); +- p = (const unsigned char*) *buffer; + PHP_VAR_UNSERIALIZE_INIT(var_hash); + +- if (!php_var_unserialize(metadata, &p, p + buf_len, &var_hash TSRMLS_CC)) { ++ if (!php_var_unserialize(metadata, &p, p + zip_metadata_len, &var_hash TSRMLS_CC)) { ++ efree(p_buff); + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + zval_ptr_dtor(metadata); + *metadata = NULL; + return FAILURE; + } +- ++ efree(p_buff); + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + + if (PHAR_G(persist)) { + /* lazy init metadata */ + zval_ptr_dtor(metadata); +- *metadata = (zval *) pemalloc(buf_len, 1); +- memcpy(*metadata, *buffer, buf_len); +- *buffer += buf_len; ++ *metadata = (zval *) pemalloc(zip_metadata_len, 1); ++ memcpy(*metadata, *buffer, zip_metadata_len); + return SUCCESS; + } + } else { + *metadata = NULL; + } + +- if (!zip_metadata_len) { +- *buffer += buf_len; +- } +- + return SUCCESS; + } + /* }}}*/ +@@ -655,7 +644,7 @@ + * + * Parse a new one and add it to the cache, returning either SUCCESS or + * FAILURE, and setting pphar to the pointer to the manifest entry +- * ++ * + * This is used by phar_open_from_filename to process the manifest, but can be called + * directly. + */ +@@ -666,6 +655,7 @@ + phar_entry_info entry; + php_uint32 manifest_len, manifest_count, manifest_flags, manifest_index, tmp_len, sig_flags; + php_uint16 manifest_ver; ++ php_uint32 len; + long offset; + int sig_len, register_alias = 0, temp_alias = 0; + char *signature = NULL; +@@ -1031,16 +1021,21 @@ + mydata->is_persistent = PHAR_G(persist); + + /* check whether we have meta data, zero check works regardless of byte order */ ++ PHAR_GET_32(buffer, len); + if (mydata->is_persistent) { +- PHAR_GET_32(buffer, mydata->metadata_len); +- if (phar_parse_metadata(&buffer, &mydata->metadata, mydata->metadata_len TSRMLS_CC) == FAILURE) { +- MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\""); +- } +- } else { +- if (phar_parse_metadata(&buffer, &mydata->metadata, 0 TSRMLS_CC) == FAILURE) { +- MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\""); ++ mydata->metadata_len = len; ++ if(!len) { ++ /* FIXME: not sure why this is needed but removing it breaks tests */ ++ PHAR_GET_32(buffer, len); + } + } ++ if(len > endbuffer - buffer) { ++ MAPPHAR_FAIL("internal corruption of phar \"%s\" (trying to read past buffer end)"); ++ } ++ if (phar_parse_metadata(&buffer, &mydata->metadata, len TSRMLS_CC) == FAILURE) { ++ MAPPHAR_FAIL("unable to read phar metadata in .phar file \"%s\""); ++ } ++ buffer += len; + + /* set up our manifest */ + zend_hash_init(&mydata->manifest, manifest_count, +@@ -1075,7 +1070,7 @@ + entry.manifest_pos = manifest_index; + } + +- if (buffer + entry.filename_len + 20 > endbuffer) { ++ if (entry.filename_len + 20 > endbuffer - buffer) { + MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)"); + } + +@@ -1111,19 +1106,20 @@ + entry.flags |= PHAR_ENT_PERM_DEF_DIR; + } + ++ PHAR_GET_32(buffer, len); + if (entry.is_persistent) { +- PHAR_GET_32(buffer, entry.metadata_len); +- if (!entry.metadata_len) buffer -= 4; +- if (phar_parse_metadata(&buffer, &entry.metadata, entry.metadata_len TSRMLS_CC) == FAILURE) { +- pefree(entry.filename, entry.is_persistent); +- MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\""); +- } ++ entry.metadata_len = len; + } else { +- if (phar_parse_metadata(&buffer, &entry.metadata, 0 TSRMLS_CC) == FAILURE) { +- pefree(entry.filename, entry.is_persistent); +- MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\""); +- } ++ entry.metadata_len = 0; + } ++ if (len > endbuffer - buffer) { ++ MAPPHAR_FAIL("internal corruption of phar \"%s\" (truncated manifest entry)"); ++ } ++ if (phar_parse_metadata(&buffer, &entry.metadata, len TSRMLS_CC) == FAILURE) { ++ pefree(entry.filename, entry.is_persistent); ++ MAPPHAR_FAIL("unable to read file metadata in .phar file \"%s\""); ++ } ++ buffer += len; + + entry.offset = entry.offset_abs = offset; + offset += entry.compressed_filesize; +@@ -2243,7 +2239,7 @@ + + /** + * Process a phar stream name, ensuring we can handle any of: +- * ++ * + * - whatever.phar + * - whatever.phar.gz + * - whatever.phar.bz2 +--- php5-5.3.10.orig/ext/phar/phar_internal.h ++++ php5-5.3.10/ext/phar/phar_internal.h +@@ -654,7 +654,7 @@ + char *phar_find_in_include_path(char *file, int file_len, phar_archive_data **pphar TSRMLS_DC); + char *phar_fix_filepath(char *path, int *new_len, int use_cwd TSRMLS_DC); + phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error TSRMLS_DC); +-int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSRMLS_DC); ++int phar_parse_metadata(char **buffer, zval **metadata, php_uint32 zip_metadata_len TSRMLS_DC); + void destroy_phar_manifest_entry(void *pDest); + int phar_seek_efp(phar_entry_info *entry, off_t offset, int whence, off_t position, int follow_links TSRMLS_DC); + php_stream *phar_get_efp(phar_entry_info *entry, int follow_links TSRMLS_DC); +--- php5-5.3.10.orig/ext/standard/var_unserializer.c ++++ php5-5.3.10/ext/standard/var_unserializer.c +@@ -304,6 +304,7 @@ + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, + sizeof data, NULL); + } ++ var_push_dtor(var_hash, &data); + + zval_dtor(key); + FREE_ZVAL(key); +--- php5-5.3.10.orig/ext/standard/var_unserializer.re ++++ php5-5.3.10/ext/standard/var_unserializer.re +@@ -310,6 +310,7 @@ + zend_hash_update(ht, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, &data, + sizeof data, NULL); + } ++ var_push_dtor(var_hash, &data); + + zval_dtor(key); + FREE_ZVAL(key); +--- php5-5.3.10.orig/ext/phar/phar_internal.h ++++ php5-5.3.10/ext/phar/phar_internal.h +@@ -618,10 +618,13 @@ + { + char tmp[MAXPATHLEN]; + int tmp_len; ++ size_t len; + +- tmp_len = entry->filename_len + entry->phar->fname_len; +- memcpy(tmp, entry->phar->fname, entry->phar->fname_len); +- memcpy(tmp + entry->phar->fname_len, entry->filename, entry->filename_len); ++ tmp_len = MIN(MAXPATHLEN, entry->filename_len + entry->phar->fname_len); ++ len = MIN(entry->phar->fname_len, tmp_len); ++ memcpy(tmp, entry->phar->fname, len); ++ len = MIN(tmp_len - len, entry->filename_len); ++ memcpy(tmp + entry->phar->fname_len, entry->filename, len); + entry->inode = (unsigned short)zend_get_hash_value(tmp, tmp_len); + } + /* }}} */ +--- php5-5.3.10.orig/sapi/apache2handler/sapi_apache2.c ++++ php5-5.3.10/sapi/apache2handler/sapi_apache2.c +@@ -708,6 +708,7 @@ + } zend_end_try(); + } + apr_brigade_cleanup(brigade); ++ apr_pool_cleanup_run(r->pool, (void *)&SG(server_context), php_server_context_cleanup); + } else { + ctx->r = parent_req; + } +--- php5-5.3.10.orig/ext/curl/interface.c ++++ php5-5.3.10/ext/curl/interface.c +@@ -172,6 +172,11 @@ + #endif + TSRMLS_FETCH(); + ++ if (strlen(url) != len) { ++ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Curl option contains invalid characters (\\0)"); ++ return 0; ++ } ++ + /* Disable file:// if open_basedir or safe_mode are used */ + if ((PG(open_basedir) && *PG(open_basedir)) || PG(safe_mode)) { + #if LIBCURL_VERSION_NUM >= 0x071304 +--- /dev/null ++++ php5-5.3.10/ext/curl/tests/bug68089.phpt +@@ -0,0 +1,18 @@ ++--TEST-- ++Bug #68089 (NULL byte injection - cURL lib) ++--SKIPIF-- ++<?php ++include 'skipif.inc'; ++ ++?> ++--FILE-- ++<?php ++$url = "file:///etc/passwd\0http://google.com"; ++$ch = curl_init(); ++var_dump(curl_setopt($ch, CURLOPT_URL, $url)); ++?> ++Done ++--EXPECTF-- ++Warning: curl_setopt(): Curl option contains invalid characters (\0) in %s/bug68089.php on line 4 ++bool(false) ++Done |