diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index 4ec48a4c427..1c656a7ad0b 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -1280,7 +1280,7 @@ ZEND_FUNCTION(get_object_vars) zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_len); zend_hash_str_add_new(Z_ARRVAL_P(return_value), prop_name, prop_len, value); } else { - zend_symbtable_add_new(Z_ARRVAL_P(return_value), key, value); + zend_symtable_add_new(Z_ARRVAL_P(return_value), key, value); } } } diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 1b998085e9e..5a31c352d0f 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -337,7 +337,7 @@ static zend_always_inline int zend_hash_str_exists_ind(const HashTable *ht, cons Z_TYPE_P(Z_INDIRECT_P(zv)) != IS_UNDEF); } -static zend_always_inline zval *zend_symbtable_add_new(HashTable *ht, zend_string *key, zval *pData) +static zend_always_inline zval *zend_symtable_add_new(HashTable *ht, zend_string *key, zval *pData) { zend_ulong idx; @@ -348,6 +348,10 @@ static zend_always_inline zval *zend_symbtable_add_new(HashTable *ht, zend_strin } } +/* This typo snuck into 7.0.17 and 7.1.3, this define exists for BC */ +#define zend_symbtable_add_new(ht, key, pData) \ + zend_symtable_add_new(ht, key, pData) + static zend_always_inline zval *zend_symtable_update(HashTable *ht, zend_string *key, zval *pData) { zend_ulong idx; diff --git a/ext/bcmath/libbcmath/src/divmod.c b/ext/bcmath/libbcmath/src/divmod.c index d7aaa3509da..08c2f8a2a2d 100644 --- a/ext/bcmath/libbcmath/src/divmod.c +++ b/ext/bcmath/libbcmath/src/divmod.c @@ -59,7 +59,7 @@ bc_divmod (bc_num num1, bc_num num2, bc_num *quot, bc_num *rem, int scale) bc_init_num(&temp); /* Calculate it. */ - bc_divide (num1, num2, &temp, scale); + bc_divide (num1, num2, &temp, 0); if (quot) quotient = bc_copy_num (temp); bc_multiply (temp, num2, &temp, rscale); diff --git a/ext/bcmath/libbcmath/src/raisemod.c b/ext/bcmath/libbcmath/src/raisemod.c index 72a838a3646..84788b4770c 100644 --- a/ext/bcmath/libbcmath/src/raisemod.c +++ b/ext/bcmath/libbcmath/src/raisemod.c @@ -45,7 +45,7 @@ int bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) { - bc_num power, exponent, parity, temp; + bc_num power, exponent, modulus, parity, temp; int rscale; /* Check for correct numbers. */ @@ -55,12 +55,16 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) /* Set initial values. */ power = bc_copy_num (base); exponent = bc_copy_num (expo); + modulus = bc_copy_num (mod); temp = bc_copy_num (BCG(_one_)); bc_init_num(&parity); /* Check the base for scale digits. */ - if (base->n_scale != 0) + if (power->n_scale != 0) + { bc_rt_warn ("non-zero scale in base"); + bc_divide (power, BCG(_one_), &power, 0); /*truncate */ + } /* Check the exponent for scale digits. */ if (exponent->n_scale != 0) @@ -70,27 +74,38 @@ bc_raisemod (bc_num base, bc_num expo, bc_num mod, bc_num *result, int scale) } /* Check the modulus for scale digits. */ - if (mod->n_scale != 0) + if (modulus->n_scale != 0) + { bc_rt_warn ("non-zero scale in modulus"); + bc_divide (modulus, BCG(_one_), &modulus, 0); /*truncate */ + } /* Do the calculation. */ - rscale = MAX(scale, base->n_scale); - while ( !bc_is_zero(exponent) ) + rscale = MAX(scale, power->n_scale); + if ( !bc_compare(modulus, BCG(_one_)) ) { - (void) bc_divmod (exponent, BCG(_two_), &exponent, &parity, 0); - if ( !bc_is_zero(parity) ) + temp = bc_new_num (1, scale); + } + else + { + while ( !bc_is_zero(exponent) ) { - bc_multiply (temp, power, &temp, rscale); - (void) bc_modulo (temp, mod, &temp, scale); - } + (void) bc_divmod (exponent, BCG(_two_), &exponent, &parity, 0); + if ( !bc_is_zero(parity) ) + { + bc_multiply (temp, power, &temp, rscale); + (void) bc_modulo (temp, modulus, &temp, scale); + } - bc_multiply (power, power, &power, rscale); - (void) bc_modulo (power, mod, &power, scale); + bc_multiply (power, power, &power, rscale); + (void) bc_modulo (power, modulus, &power, scale); + } } /* Assign the value. */ bc_free_num (&power); bc_free_num (&exponent); + bc_free_num (&modulus); bc_free_num (result); bc_free_num (&parity); *result = temp; diff --git a/ext/bcmath/tests/bug44995.phpt b/ext/bcmath/tests/bug44995.phpt new file mode 100644 index 00000000000..6eb591f92b7 --- /dev/null +++ b/ext/bcmath/tests/bug44995.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #44995 (bcpowmod() fails if scale != 0) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +string(3) "1.0" +string(7) "17334.0" +===DONE=== diff --git a/ext/bcmath/tests/bug54598.phpt b/ext/bcmath/tests/bug54598.phpt new file mode 100644 index 00000000000..6ccd61a2d02 --- /dev/null +++ b/ext/bcmath/tests/bug54598.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #54598 (bcpowmod() may return 1 if modulus is 1) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +string(1) "0" +string(5) "0.000" +===DONE=== diff --git a/ext/bcmath/tests/bug75178-win32.phpt b/ext/bcmath/tests/bug75178-win32.phpt new file mode 100644 index 00000000000..bae590fb5b3 --- /dev/null +++ b/ext/bcmath/tests/bug75178-win32.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #75178 (bcpowmod() misbehaves for non-integer base or modulus) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +string(5) "1.000" +string(5) "1.000" +===DONE=== +bc math warning: non-zero scale in base +bc math warning: non-zero scale in modulus diff --git a/ext/bcmath/tests/bug75178.phpt b/ext/bcmath/tests/bug75178.phpt new file mode 100644 index 00000000000..bdfa25a2e17 --- /dev/null +++ b/ext/bcmath/tests/bug75178.phpt @@ -0,0 +1,21 @@ +--TEST-- +Bug #75178 (bcpowmod() misbehaves for non-integer base or modulus) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +bc math warning: non-zero scale in base +string(5) "1.000" +bc math warning: non-zero scale in modulus +string(5) "1.000" +===DONE=== diff --git a/ext/gettext/gettext.c b/ext/gettext/gettext.c index 9cc2ba5a6fe..f4d6694cee7 100644 --- a/ext/gettext/gettext.c +++ b/ext/gettext/gettext.c @@ -161,16 +161,16 @@ PHP_MINFO_FUNCTION(php_gettext) Set the textdomain to "domain". Returns the current domain */ PHP_NAMED_FUNCTION(zif_textdomain) { - char *domain, *domain_name, *retval; - size_t domain_len; + char *domain = NULL, *domain_name, *retval; + size_t domain_len = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &domain, &domain_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!", &domain, &domain_len) == FAILURE) { return; } PHP_GETTEXT_DOMAIN_LENGTH_CHECK - if (strcmp(domain, "") && strcmp(domain, "0")) { + if (domain != NULL && strcmp(domain, "") && strcmp(domain, "0")) { domain_name = domain; } else { domain_name = NULL; diff --git a/ext/gettext/tests/bug73730.phpt b/ext/gettext/tests/bug73730.phpt new file mode 100644 index 00000000000..df6d7b0f11c --- /dev/null +++ b/ext/gettext/tests/bug73730.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #73730 (textdomain(null) throws in strict mode) +--SKIPIF-- + +--FILE-- + +===DONE=== +--EXPECT-- +string(8) "messages" +===DONE=== diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index 0daa55f4b44..4373a3b6518 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -3367,7 +3367,7 @@ SPL_METHOD(AppendIterator, __construct) Append an iterator */ SPL_METHOD(AppendIterator, append) { - spl_dual_it_object *intern, *appender; + spl_dual_it_object *intern; zval *it; SPL_FETCH_AND_CHECK_DUAL_IT(intern, getThis()); @@ -3379,11 +3379,6 @@ SPL_METHOD(AppendIterator, append) spl_array_iterator_append(&intern->u.append.zarrayit, it); intern->u.append.iterator->funcs->move_forward(intern->u.append.iterator); }else{ - appender = Z_SPLDUAL_IT_P(it); - if (appender->dit_type == DIT_AppendIterator) { - spl_array_iterator_append(&intern->u.append.zarrayit, &appender->u.append.zarrayit); - return; - } spl_array_iterator_append(&intern->u.append.zarrayit, it); } diff --git a/ext/spl/tests/bug74977.phpt b/ext/spl/tests/bug74977.phpt deleted file mode 100644 index 09e16eedfe4..00000000000 --- a/ext/spl/tests/bug74977.phpt +++ /dev/null @@ -1,13 +0,0 @@ ---TEST-- -Bug #74977: Recursion leads to crash ---FILE-- -append($iterator); -var_dump($iterator); -?> ---EXPECTF-- -object(AppendIterator)#1 (0) { -} - diff --git a/ext/spl/tests/bug75155.phpt b/ext/spl/tests/bug75155.phpt new file mode 100644 index 00000000000..0d0c0753e09 --- /dev/null +++ b/ext/spl/tests/bug75155.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #75155: AppendIterator::append() is broken when appending another AppendIterator +--FILE-- +append($array_a); + +$iterator2 = new AppendIterator; +$iterator2->append($iterator); +$iterator2->append($array_b); + +foreach ($iterator2 as $current) { + echo $current; +} + +?> +--EXPECT-- +abcdef diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index e7650cb763c..fb636d06a37 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -172,6 +172,9 @@ typedef struct php_cli_server_client { char *current_header_name; size_t current_header_name_len; unsigned int current_header_name_allocated:1; + char *current_header_value; + size_t current_header_value_len; + enum { HEADER_NONE=0, HEADER_FIELD, HEADER_VALUE } last_header_element; size_t post_read_offset; php_cli_server_request request; unsigned int content_sender_initialized:1; @@ -1487,7 +1490,7 @@ static void normalize_vpath(char **retval, size_t *retval_len, const char *vpath #ifdef PHP_WIN32 { char *p = decoded_vpath; - + do { if (*p == '\\') { *p = '/'; @@ -1590,50 +1593,103 @@ static int php_cli_server_client_read_request_on_fragment(php_http_parser *parse return 0; } -static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length) +static void php_cli_server_client_save_header(php_cli_server_client *client) { - php_cli_server_client *client = parser->data; + /* strip off the colon */ + zend_string *orig_header_name = zend_string_init(client->current_header_name, client->current_header_name_len, 1); + char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); + zend_hash_str_add_ptr(&client->request.headers, lc_header_name, client->current_header_name_len, client->current_header_value); + zend_hash_add_ptr(&client->request.headers_original_case, orig_header_name, client->current_header_value); + efree(lc_header_name); + zend_string_release(orig_header_name); + if (client->current_header_name_allocated) { pefree(client->current_header_name, 1); client->current_header_name_allocated = 0; } - client->current_header_name = (char *)at; - client->current_header_name_len = length; + client->current_header_name = NULL; + client->current_header_name_len = 0; + client->current_header_value = NULL; + client->current_header_value_len = 0; +} + +static int php_cli_server_client_read_request_on_header_field(php_http_parser *parser, const char *at, size_t length) +{ + php_cli_server_client *client = parser->data; + switch (client->last_header_element) { + case HEADER_VALUE: + php_cli_server_client_save_header(client); + /* break missing intentionally */ + case HEADER_NONE: + client->current_header_name = (char *)at; + client->current_header_name_len = length; + break; + case HEADER_FIELD: + if (client->current_header_name_allocated) { + size_t new_length = client->current_header_name_len + length; + client->current_header_name = perealloc(client->current_header_name, new_length + 1, 1); + memcpy(client->current_header_name + client->current_header_name_len, at, length); + client->current_header_name[new_length] = '\0'; + client->current_header_name_len = new_length; + } else { + size_t new_length = client->current_header_name_len + length; + char* field = pemalloc(new_length + 1, 1); + memcpy(field, client->current_header_name, client->current_header_name_len); + memcpy(field + client->current_header_name_len, at, length); + field[new_length] = '\0'; + client->current_header_name = field; + client->current_header_name_len = new_length; + client->current_header_name_allocated = 1; + } + break; + } + + client->last_header_element = HEADER_FIELD; return 0; } static int php_cli_server_client_read_request_on_header_value(php_http_parser *parser, const char *at, size_t length) { php_cli_server_client *client = parser->data; - char *value = pestrndup(at, length, 1); - if (!value) { - return 1; - } - { - /* strip off the colon */ - zend_string *orig_header_name = zend_string_init(client->current_header_name, client->current_header_name_len, 1); - char *lc_header_name = zend_str_tolower_dup(client->current_header_name, client->current_header_name_len); - zend_hash_str_add_ptr(&client->request.headers, lc_header_name, client->current_header_name_len, value); - zend_hash_add_ptr(&client->request.headers_original_case, orig_header_name, value); - efree(lc_header_name); - zend_string_release(orig_header_name); - } - - if (client->current_header_name_allocated) { - pefree(client->current_header_name, 1); - client->current_header_name_allocated = 0; + switch (client->last_header_element) { + case HEADER_FIELD: + client->current_header_value = pestrndup(at, length, 1); + client->current_header_value_len = length; + break; + case HEADER_VALUE: + { + size_t new_length = client->current_header_value_len + length; + client->current_header_value = perealloc(client->current_header_value, new_length + 1, 1); + memcpy(client->current_header_value + client->current_header_value_len, at, length); + client->current_header_value[new_length] = '\0'; + client->current_header_value_len = new_length; + } + break; + case HEADER_NONE: + // can't happen + assert(0); + break; } + client->last_header_element = HEADER_VALUE; return 0; } static int php_cli_server_client_read_request_on_headers_complete(php_http_parser *parser) { php_cli_server_client *client = parser->data; - if (client->current_header_name_allocated) { - pefree(client->current_header_name, 1); - client->current_header_name_allocated = 0; + switch (client->last_header_element) { + case HEADER_NONE: + break; + case HEADER_FIELD: + client->current_header_value = pemalloc(1, 1); + *client->current_header_value = '\0'; + client->current_header_value_len = 0; + /* break missing intentionally */ + case HEADER_VALUE: + php_cli_server_client_save_header(client); + break; } - client->current_header_name = NULL; + client->last_header_element = HEADER_NONE; return 0; } @@ -1809,9 +1865,14 @@ static int php_cli_server_client_ctor(php_cli_server_client *client, php_cli_ser } php_http_parser_init(&client->parser, PHP_HTTP_REQUEST); client->request_read = 0; + + client->last_header_element = HEADER_NONE; client->current_header_name = NULL; client->current_header_name_len = 0; client->current_header_name_allocated = 0; + client->current_header_value = NULL; + client->current_header_value_len = 0; + client->post_read_offset = 0; if (FAILURE == php_cli_server_request_ctor(&client->request)) { return FAILURE; diff --git a/sapi/cli/tests/bug70470.phpt b/sapi/cli/tests/bug70470.phpt index acd8c98f05a..1e05f184b40 100644 --- a/sapi/cli/tests/bug70470.phpt +++ b/sapi/cli/tests/bug70470.phpt @@ -4,8 +4,6 @@ Bug #70470 (Built-in server truncates headers spanning over TCP packets) ---XFAIL-- -bug is not fixed yet --FILE-- +--FILE-- + +--EXPECTF-- +HTTP/1.1 200 OK +%a +array(3) { + ["User-AgentAccept"]=> + string(3) "*/*" + ["Referer"]=> + string(0) "" + ["Hi"]=> + string(0) "" +}