summarylogtreecommitdiffstats
path: root/cve-php5.3.patch
diff options
context:
space:
mode:
Diffstat (limited to 'cve-php5.3.patch')
-rw-r--r--cve-php5.3.patch842
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