mirror of
https://github.com/php/php-src.git
synced 2026-04-14 11:32:11 +02:00
Merge branch 'PHP-7.1' of git.php.net:/php-src into PHP-7.1
* 'PHP-7.1' of git.php.net:/php-src: Fixed bug #73730 (textdomain(null) throws in strict mode) Fix bug75178.phpt on Windows Fixed bug #75178 (bcpowmod() misbehaves for non-integer base or modulus) Add BC define for users of the typoed zend_symbtable_add_new Fix typo in zend_symtable_add_new() API name Fixed bug #54598 (bcpowmod() may return 1 if modulus is 1) Fixed bug #44995 (bcpowmod() fails if scale != 0) Add missing null termination Fixed bug #70470 Add test for bug #75155 Revert "Fixed #74977 - Appending AppendIterator leads to segfault"
This commit is contained in:
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
16
ext/bcmath/tests/bug44995.phpt
Normal file
16
ext/bcmath/tests/bug44995.phpt
Normal file
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #44995 (bcpowmod() fails if scale != 0)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(bcpowmod('4', '4', '3', 1));
|
||||
var_dump(bcpowmod('3234', '32345', '22345', 1));
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
string(3) "1.0"
|
||||
string(7) "17334.0"
|
||||
===DONE===
|
||||
16
ext/bcmath/tests/bug54598.phpt
Normal file
16
ext/bcmath/tests/bug54598.phpt
Normal file
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #54598 (bcpowmod() may return 1 if modulus is 1)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(bcpowmod(5, 0, 1));
|
||||
var_dump(bcpowmod(5, 0, 1, 3));
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
string(1) "0"
|
||||
string(5) "0.000"
|
||||
===DONE===
|
||||
21
ext/bcmath/tests/bug75178-win32.phpt
Normal file
21
ext/bcmath/tests/bug75178-win32.phpt
Normal file
@@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Bug #75178 (bcpowmod() misbehaves for non-integer base or modulus)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
|
||||
if (substr(PHP_OS, 0, 3) != 'WIN') {
|
||||
die('skip valid only for windows');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(bcpowmod('4.1', '4', '3', 3));
|
||||
var_dump(bcpowmod('4', '4', '3.1', 3));
|
||||
?>
|
||||
===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
|
||||
21
ext/bcmath/tests/bug75178.phpt
Normal file
21
ext/bcmath/tests/bug75178.phpt
Normal file
@@ -0,0 +1,21 @@
|
||||
--TEST--
|
||||
Bug #75178 (bcpowmod() misbehaves for non-integer base or modulus)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('bcmath')) die('skip bcmath extension is not available');
|
||||
if (substr(PHP_OS, 0, 3) == 'WIN') {
|
||||
die('skip Not valid for windows');
|
||||
}
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(bcpowmod('4.1', '4', '3', 3));
|
||||
var_dump(bcpowmod('4', '4', '3.1', 3));
|
||||
?>
|
||||
===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===
|
||||
@@ -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;
|
||||
|
||||
16
ext/gettext/tests/bug73730.phpt
Normal file
16
ext/gettext/tests/bug73730.phpt
Normal file
@@ -0,0 +1,16 @@
|
||||
--TEST--
|
||||
Bug #73730 (textdomain(null) throws in strict mode)
|
||||
--SKIPIF--
|
||||
<?php
|
||||
if (!extension_loaded('gettext')) die('skip gettext extension is not available');
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
var_dump(textdomain(null));
|
||||
?>
|
||||
===DONE===
|
||||
--EXPECT--
|
||||
string(8) "messages"
|
||||
===DONE===
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
--TEST--
|
||||
Bug #74977: Recursion leads to crash
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$iterator = new AppendIterator(array("A","A","A"));
|
||||
$iterator->append($iterator);
|
||||
var_dump($iterator);
|
||||
?>
|
||||
--EXPECTF--
|
||||
object(AppendIterator)#1 (0) {
|
||||
}
|
||||
|
||||
22
ext/spl/tests/bug75155.phpt
Normal file
22
ext/spl/tests/bug75155.phpt
Normal file
@@ -0,0 +1,22 @@
|
||||
--TEST--
|
||||
Bug #75155: AppendIterator::append() is broken when appending another AppendIterator
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
$array_a = new ArrayIterator(array('a', 'b', 'c'));
|
||||
$array_b = new ArrayIterator(array('d', 'e', 'f'));
|
||||
|
||||
$iterator = new AppendIterator;
|
||||
$iterator->append($array_a);
|
||||
|
||||
$iterator2 = new AppendIterator;
|
||||
$iterator2->append($iterator);
|
||||
$iterator2->append($array_b);
|
||||
|
||||
foreach ($iterator2 as $current) {
|
||||
echo $current;
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
abcdef
|
||||
@@ -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;
|
||||
|
||||
@@ -4,8 +4,6 @@ Bug #70470 (Built-in server truncates headers spanning over TCP packets)
|
||||
<?php
|
||||
include "skipif.inc";
|
||||
?>
|
||||
--XFAIL--
|
||||
bug is not fixed yet
|
||||
--FILE--
|
||||
<?php
|
||||
include "php_cli_server.inc";
|
||||
|
||||
35
sapi/cli/tests/emptyheader.phpt
Normal file
35
sapi/cli/tests/emptyheader.phpt
Normal file
@@ -0,0 +1,35 @@
|
||||
--TEST--
|
||||
Correctly handle split and empty header
|
||||
--SKIPIF--
|
||||
<?php
|
||||
include "skipif.inc";
|
||||
?>
|
||||
--FILE--
|
||||
<?php
|
||||
include "php_cli_server.inc";
|
||||
php_cli_server_start("var_dump(getAllheaders());");
|
||||
|
||||
$fp = fsockopen(PHP_CLI_SERVER_HOSTNAME, PHP_CLI_SERVER_PORT, $errno, $errmsg, 0.5);
|
||||
|
||||
if (!$fp) {
|
||||
die("connect failed: " . $errmsg);
|
||||
}
|
||||
|
||||
fwrite($fp, "GET / HTTP/1.1\r\nUser-Agent\r\nAccept: */*\r\nReferer:\r\nHi\r\n\r\n");
|
||||
fflush($fp);
|
||||
while (!feof($fp)) {
|
||||
echo fgets($fp);
|
||||
}
|
||||
fclose($fp);
|
||||
?>
|
||||
--EXPECTF--
|
||||
HTTP/1.1 200 OK
|
||||
%a
|
||||
array(3) {
|
||||
["User-AgentAccept"]=>
|
||||
string(3) "*/*"
|
||||
["Referer"]=>
|
||||
string(0) ""
|
||||
["Hi"]=>
|
||||
string(0) ""
|
||||
}
|
||||
Reference in New Issue
Block a user