--- 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-- + +--FILE-- +$datetime"); +print_r($obj); + +$datetime = "34770-0-08T21:46:40-0400"; +$obj = xmlrpc_decode("$datetime"); +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-- + +===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-- +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-- +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-- + +--FILE-- + +Done +--EXPECTF-- +Warning: curl_setopt(): Curl option contains invalid characters (\0) in %s/bug68089.php on line 4 +bool(false) +Done