diff options
author | Stanislav Malyshev <stas@php.net> | 2016-09-12 21:09:30 -0700 |
---|---|---|
committer | Stanislav Malyshev <stas@php.net> | 2016-09-12 21:09:30 -0700 |
commit | 07c6bdb85d3efe21598ebb8af6fcebceb9d486e9 (patch) | |
tree | 0fb02e7c08ec0b50791020ac862fc56e1f475135 | |
parent | 2d8ab51576695630a7471ff829cc5ea10becdc0f (diff) | |
parent | c984661d39cfa4db1dd97fde1f59c77a44991440 (diff) | |
download | php-git-07c6bdb85d3efe21598ebb8af6fcebceb9d486e9.tar.gz |
Merge branch 'PHP-7.0.11' into PHP-7.0
* PHP-7.0.11: (22 commits)
Fix bug #72293 - Heap overflow in mysqlnd related to BIT fields
I don't think 8cceb012a7aabf3c36ab7c2724a436f976cdd165 is needed
Fix test
Add check in fgetcsv in case sizeof(unit) != sizeof(size_t)
Fix bug #73065: Out-Of-Bounds Read in php_wddx_push_element of wddx.c
Fix bug #73035 (Out of bound when verify signature of tar phar in phar_parse_tarfile)
Fix bug #73052 - Memory Corruption in During Deserialized-object Destruction
Fix bug #73029 - Missing type check when unserializing SplArray
Fix bug #72860: wddx_deserialize use-after-free
Fix bug #73007: add locale length check
Fix bug #72928 - Out of bound when verify signature of zip phar in phar_parse_zipfile
sync NEWS
Revert "Merge branch 'PHP-5.6' into PHP-7.0"
Merge branch 'PHP-5.6' into PHP-7.0
Merge branch 'PHP-5.6' into PHP-7.0
Revert "Revert "Merge branch 'PHP-5.6' into PHP-7.0""
fix version
sync NEWS
Fix bug #72957
set versions
...
-rw-r--r-- | ext/intl/msgformat/msgformat_format.c | 2 | ||||
-rw-r--r-- | ext/mysqlnd/mysqlnd_wireprotocol.c | 7 | ||||
-rw-r--r-- | ext/phar/tar.c | 2 | ||||
-rw-r--r-- | ext/phar/tests/bug72928.phpt | 18 | ||||
-rw-r--r-- | ext/phar/tests/bug72928.zip | bin | 0 -> 140 bytes | |||
-rw-r--r-- | ext/phar/tests/bug73035.phpt | 18 | ||||
-rw-r--r-- | ext/phar/tests/bug73035.tar | bin | 0 -> 10240 bytes | |||
-rw-r--r-- | ext/phar/util.c | 28 | ||||
-rw-r--r-- | ext/phar/zip.c | 2 | ||||
-rw-r--r-- | ext/spl/spl_array.c | 5 | ||||
-rw-r--r-- | ext/spl/tests/bug70068.phpt | 5 | ||||
-rw-r--r-- | ext/spl/tests/bug73029.phpt | 16 | ||||
-rw-r--r-- | ext/standard/tests/serialize/bug73052.phpt | 18 | ||||
-rw-r--r-- | ext/standard/tests/strings/bug72703.phpt | 17 | ||||
-rw-r--r-- | ext/wddx/tests/bug72860.phpt | 27 | ||||
-rw-r--r-- | ext/wddx/tests/bug73065.phpt | 98 | ||||
-rw-r--r-- | ext/wddx/wddx.c | 24 |
17 files changed, 255 insertions, 32 deletions
diff --git a/ext/intl/msgformat/msgformat_format.c b/ext/intl/msgformat/msgformat_format.c index 73fb5eeff6..cb74a3fb1b 100644 --- a/ext/intl/msgformat/msgformat_format.c +++ b/ext/intl/msgformat/msgformat_format.c @@ -116,6 +116,8 @@ PHP_FUNCTION( msgfmt_format_message ) RETURN_FALSE; } + INTL_CHECK_LOCALE_LEN(slocale_len); + memset(mfo, 0, sizeof(*mfo)); msgformat_data_init(&mfo->mf_data); diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 8f80bbaada..5871c3c346 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1608,6 +1608,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zend_uchar * p = row_buffer->ptr; size_t data_size = row_buffer->app; zend_uchar * bit_area = (zend_uchar*) row_buffer->ptr + data_size + 1; /* we allocate from here */ + const zend_uchar * const packet_end = (zend_uchar*) row_buffer->ptr + data_size; DBG_ENTER("php_mysqlnd_rowp_read_text_protocol_aux"); @@ -1619,11 +1620,15 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) { /* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */ - zend_ulong len = php_mysqlnd_net_field_length(&p); + const zend_ulong len = php_mysqlnd_net_field_length(&p); /* NULL or NOT NULL, this is the question! */ if (len == MYSQLND_NULL_LENGTH) { ZVAL_NULL(current_field); + } else if ((p + len) > packet_end) { + php_error_docref(NULL, E_WARNING, "Malformed server packet. Field length pointing "MYSQLND_SZ_T_SPEC + " bytes after end of packet", (p + len) - packet_end - 1); + DBG_RETURN(FAIL); } else { #if defined(MYSQLND_STRING_TO_INT_CONVERSION) struct st_mysqlnd_perm_bind perm_bind = diff --git a/ext/phar/tar.c b/ext/phar/tar.c index aeb5c7ef1e..72b653db97 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -286,7 +286,7 @@ bail: } curloc = php_stream_tell(fp); read = php_stream_read(fp, buf, size); - if (read != size) { + if (read != size || read <= 8) { if (error) { spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be read", fname); } diff --git a/ext/phar/tests/bug72928.phpt b/ext/phar/tests/bug72928.phpt new file mode 100644 index 0000000000..8e6a95418c --- /dev/null +++ b/ext/phar/tests/bug72928.phpt @@ -0,0 +1,18 @@ +--TEST-- +Phar: #72928 (Out of bound when verify signature of zip phar in phar_parse_zipfile) +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +chdir(__DIR__); +try { +$phar = new PharData('bug72928.zip'); +var_dump($phar); +} catch(UnexpectedValueException $e) { + print $e->getMessage()."\n"; +} +?> +DONE +--EXPECTF-- +phar error: signature cannot be read in zip-based phar "%sbug72928.zip" +DONE
\ No newline at end of file diff --git a/ext/phar/tests/bug72928.zip b/ext/phar/tests/bug72928.zip Binary files differnew file mode 100644 index 0000000000..c480c5f537 --- /dev/null +++ b/ext/phar/tests/bug72928.zip diff --git a/ext/phar/tests/bug73035.phpt b/ext/phar/tests/bug73035.phpt new file mode 100644 index 0000000000..5928428abc --- /dev/null +++ b/ext/phar/tests/bug73035.phpt @@ -0,0 +1,18 @@ +--TEST-- +Phar: #73035 (Out of bound when verify signature of tar phar in phar_parse_tarfile) +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +chdir(__DIR__); +try { +$phar = new PharData('bug73035.tar'); +var_dump($phar); +} catch(UnexpectedValueException $e) { + print $e->getMessage()."\n"; +} +?> +DONE +--EXPECTF-- +phar error: tar-based phar "%sbug73035.tar" signature cannot be read +DONE
\ No newline at end of file diff --git a/ext/phar/tests/bug73035.tar b/ext/phar/tests/bug73035.tar Binary files differnew file mode 100644 index 0000000000..d8e426866b --- /dev/null +++ b/ext/phar/tests/bug73035.tar diff --git a/ext/phar/util.c b/ext/phar/util.c index eca33efc38..08d58b9301 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1609,6 +1609,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[64]; PHP_SHA512_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_SHA512Init(&context); read_len = end_of_phar; @@ -1642,6 +1649,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[32]; PHP_SHA256_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_SHA256Init(&context); read_len = end_of_phar; @@ -1683,6 +1697,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[20]; PHP_SHA1_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_SHA1Init(&context); read_len = end_of_phar; @@ -1716,6 +1737,13 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_typ unsigned char digest[16]; PHP_MD5_CTX context; + if (sig_len < sizeof(digest)) { + if (error) { + spprintf(error, 0, "broken signature"); + } + return FAILURE; + } + PHP_MD5Init(&context); read_len = end_of_phar; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 73a11870aa..a29a75d212 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -418,7 +418,7 @@ foundit: php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET); sig = (char *) emalloc(entry.uncompressed_filesize); read = php_stream_read(fp, sig, entry.uncompressed_filesize); - if (read != entry.uncompressed_filesize) { + if (read != entry.uncompressed_filesize || read <= 8) { php_stream_close(sigfile); efree(sig); PHAR_ZIP_FAIL("signature cannot be read"); diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 3bb0e367ea..fe3873541e 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -295,7 +295,7 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, spl_array_object * zend_string *offset_key; HashTable *ht = spl_array_get_hash_table(intern); - if (!offset || Z_ISUNDEF_P(offset)) { + if (!offset || Z_ISUNDEF_P(offset) || !ht) { return &EG(uninitialized_zval); } @@ -1790,7 +1790,8 @@ SPL_METHOD(Array, unserialize) intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK; zval_ptr_dtor(&intern->array); ZVAL_UNDEF(&intern->array); - if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash)) { + if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash) + || (Z_TYPE(intern->array) != IS_ARRAY && Z_TYPE(intern->array) != IS_OBJECT)) { goto outexcept; } var_push_dtor(&var_hash, &intern->array); diff --git a/ext/spl/tests/bug70068.phpt b/ext/spl/tests/bug70068.phpt index 92a38dfbd6..96b2fa808f 100644 --- a/ext/spl/tests/bug70068.phpt +++ b/ext/spl/tests/bug70068.phpt @@ -2,8 +2,13 @@ Bug #70068 (Dangling pointer in the unserialization of ArrayObject items) --FILE-- <?php +try { $a = unserialize('a:3:{i:0;C:11:"ArrayObject":20:{x:i:0;r:3;;m:a:0:{};}i:1;d:11;i:2;S:31:"AAAAAAAABBBBCCCC\01\00\00\00\04\00\00\00\00\00\00\00\00\00\00";}'); +} catch(Exception $e) { + print $e->getMessage()."\n"; +} ?> OK --EXPECT-- +Error at offset 10 of 20 bytes OK
\ No newline at end of file diff --git a/ext/spl/tests/bug73029.phpt b/ext/spl/tests/bug73029.phpt new file mode 100644 index 0000000000..a379f8005e --- /dev/null +++ b/ext/spl/tests/bug73029.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #73029: Missing type check when unserializing SplArray +--FILE-- +<?php +try { +$a = 'C:11:"ArrayObject":19:0x:i:0;r:2;;m:a:0:{}}'; +$m = unserialize($a); +$x = $m[2]; +} catch(UnexpectedValueException $e) { + print $e->getMessage() . "\n"; +} +?> +DONE +--EXPECTF-- +Error at offset 10 of 19 bytes +DONE diff --git a/ext/standard/tests/serialize/bug73052.phpt b/ext/standard/tests/serialize/bug73052.phpt new file mode 100644 index 0000000000..63b484bf14 --- /dev/null +++ b/ext/standard/tests/serialize/bug73052.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #73052: Memory Corruption in During Deserialized-object Destruction +--FILE-- +<?php + +class obj { + var $ryat; + public function __destruct() { + $this->ryat = null; + } +} + +$poc = 'O:3:"obj":1:{'; +var_dump(unserialize($poc)); +?> +--EXPECTF-- +Notice: unserialize(): Error at offset 13 of 13 bytes in %sbug73052.php on line %d +bool(false) diff --git a/ext/standard/tests/strings/bug72703.phpt b/ext/standard/tests/strings/bug72703.phpt deleted file mode 100644 index 5e3bf4875d..0000000000 --- a/ext/standard/tests/strings/bug72703.phpt +++ /dev/null @@ -1,17 +0,0 @@ ---TEST-- -Bug #72703 Out of bounds global memory read in BF_crypt triggered by password_verify ---SKIPIF-- -<?php -if (!function_exists('crypt'))) { - die("SKIP crypt() is not available"); -} -?> ---FILE-- -<?php - var_dump(password_verify("","$2y$10$$")); -?> -==OK== ---EXPECT-- -bool(false) -==OK== - diff --git a/ext/wddx/tests/bug72860.phpt b/ext/wddx/tests/bug72860.phpt new file mode 100644 index 0000000000..6385457e8e --- /dev/null +++ b/ext/wddx/tests/bug72860.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #72860: wddx_deserialize use-after-free +--SKIPIF-- +<?php +if (!extension_loaded('wddx')) { + die('skip. wddx not available'); +} +?> +--FILE-- +<?php + +$xml=<<<XML +<?xml version='1.0'?> +<!DOCTYPE wddxPacket SYSTEM 'wddx_0100.dtd'> +<wddxPacket version='1.0'> + <recordset fieldNames='F'> + <field name='F'> + </recordset> +</wddxPacket> +XML; + +var_dump(wddx_deserialize($xml)); +?> +DONE +--EXPECT-- +NULL +DONE
\ No newline at end of file diff --git a/ext/wddx/tests/bug73065.phpt b/ext/wddx/tests/bug73065.phpt new file mode 100644 index 0000000000..aa301aa838 --- /dev/null +++ b/ext/wddx/tests/bug73065.phpt @@ -0,0 +1,98 @@ +--TEST-- +Bug #73065: Out-Of-Bounds Read in php_wddx_push_element of wddx.c +--SKIPIF-- +<?php +if (!extension_loaded('wddx')) { + die('skip. wddx not available'); +} +?> +--FILE-- +<?php + +$xml1 = <<<XML +<?xml version='1.0' ?> + <!DOCTYPE et SYSTEM 'w'> + <wddxPacket ven='1.0'> + <array> + <var Name="name"> + <boolean value="keliu"></boolean> + </var> + <var name="1111"> + <var name="2222"> + <var name="3333"></var> + </var> + </var> + </array> + </wddxPacket> +XML; + +$xml2 = <<<XML +<?xml version='1.0' ?> + <!DOCTYPE et SYSTEM 'w'> + <wddxPacket ven='1.0'> + <array> + <char Name="code"> + <boolean value="keliu"></boolean> + </char> + </array> + </wddxPacket> +XML; + +$xml3 = <<<XML +<?xml version='1.0' ?> + <!DOCTYPE et SYSTEM 'w'> + <wddxPacket ven='1.0'> + <array> + <boolean Name="value"> + <boolean value="keliu"></boolean> + </boolean> + </array> + </wddxPacket> +XML; + +$xml4 = <<<XML +<?xml version='1.0' ?> + <!DOCTYPE et SYSTEM 'w'> + <wddxPacket ven='1.0'> + <array> + <recordset Name="fieldNames"> + <boolean value="keliu"></boolean> + </recordset> + </array> + </wddxPacket> +XML; + +$xml5 = <<<XML +<?xml version='1.0' ?> + <!DOCTYPE et SYSTEM 'w'> + <wddxPacket ven='1.0'> + <array> + <field Name="name"> + <boolean value="keliu"></boolean> + </field> + </array> + </wddxPacket> +XML; + +for($i=1;$i<=5;$i++) { + $xmlvar = "xml$i"; + $array = wddx_deserialize($$xmlvar); + var_dump($array); +} +?> +DONE +--EXPECTF-- +array(0) { +} +array(0) { +} +array(0) { +} +array(1) { + [0]=> + array(0) { + } +} +array(0) { +} +DONE
\ No newline at end of file diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index 3a6835fbb6..7d805e484f 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -230,7 +230,10 @@ static int wddx_stack_destroy(wddx_stack *stack) if (stack->elements) { for (i = 0; i < stack->top; i++) { - zval_ptr_dtor(&((st_entry *)stack->elements[i])->data); + if (Z_TYPE(((st_entry *)stack->elements[i])->data) != IS_UNDEF + && ((st_entry *)stack->elements[i])->type != ST_FIELD) { + zval_ptr_dtor(&((st_entry *)stack->elements[i])->data); + } if (((st_entry *)stack->elements[i])->varname) { efree(((st_entry *)stack->elements[i])->varname); } @@ -738,10 +741,10 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X int i; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp((char *)atts[i], EL_CHAR_CODE) && atts[++i] && atts[i][0]) { + if (!strcmp((char *)atts[i], EL_CHAR_CODE) && atts[i+1] && atts[i+1][0]) { char tmp_buf[2]; - snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol((char *)atts[i], NULL, 16)); + snprintf(tmp_buf, sizeof(tmp_buf), "%c", (char)strtol((char *)atts[i+1], NULL, 16)); php_wddx_process_data(user_data, (XML_Char *) tmp_buf, strlen(tmp_buf)); break; } @@ -756,13 +759,13 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X int i; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp((char *)atts[i], EL_VALUE) && atts[++i] && atts[i][0]) { + if (!strcmp((char *)atts[i], EL_VALUE) && atts[i+1] && atts[i+1][0]) { ent.type = ST_BOOLEAN; SET_STACK_VARNAME; ZVAL_TRUE(&ent.data); wddx_stack_push((wddx_stack *)stack, &ent, sizeof(st_entry)); - php_wddx_process_data(user_data, atts[i], strlen((char *)atts[i])); + php_wddx_process_data(user_data, atts[i+1], strlen((char *)atts[i+1])); break; } } @@ -788,9 +791,9 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X int i; if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp((char *)atts[i], EL_NAME) && atts[++i] && atts[i][0]) { + if (!strcmp((char *)atts[i], EL_NAME) && atts[i+1] && atts[i+1][0]) { if (stack->varname) efree(stack->varname); - stack->varname = estrdup((char *)atts[i]); + stack->varname = estrdup((char *)atts[i+1]); break; } } @@ -802,11 +805,12 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X array_init(&ent.data); if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp((char *)atts[i], "fieldNames") && atts[++i] && atts[i][0]) { + if (!strcmp((char *)atts[i], "fieldNames") && atts[i+1] && atts[i+1][0]) { zval tmp; char *key; const char *p1, *p2, *endp; + i++; endp = (char *)atts[i] + strlen((char *)atts[i]); p1 = (char *)atts[i]; while ((p2 = php_memnstr(p1, ",", sizeof(",")-1, endp)) != NULL) { @@ -836,13 +840,13 @@ static void php_wddx_push_element(void *user_data, const XML_Char *name, const X ZVAL_UNDEF(&ent.data); if (atts) for (i = 0; atts[i]; i++) { - if (!strcmp((char *)atts[i], EL_NAME) && atts[++i] && atts[i][0]) { + if (!strcmp((char *)atts[i], EL_NAME) && atts[i+1] && atts[i+1][0]) { st_entry *recordset; zval *field; if (wddx_stack_top(stack, (void**)&recordset) == SUCCESS && recordset->type == ST_RECORDSET && - (field = zend_hash_str_find(Z_ARRVAL(recordset->data), (char*)atts[i], strlen((char *)atts[i]))) != NULL) { + (field = zend_hash_str_find(Z_ARRVAL(recordset->data), (char*)atts[i+1], strlen((char *)atts[i+1]))) != NULL) { ZVAL_COPY_VALUE(&ent.data, field); } |