1
0
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:
Xinchen Hui
2017-09-11 12:46:26 +08:00
16 changed files with 273 additions and 66 deletions

View File

@@ -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);
}
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View 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===

View 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===

View 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

View 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===

View File

@@ -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;

View 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===

View File

@@ -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);
}

View File

@@ -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) {
}

View 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

View File

@@ -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;

View File

@@ -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";

View 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) ""
}