mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Improve ini number handling with INI_SCANNER_TYPED
Fixes GH-11010 Closes GH-11014
This commit is contained in:
parent
471dcf6e40
commit
86ffde3c38
3
NEWS
3
NEWS
@ -170,6 +170,9 @@ PHP NEWS
|
||||
. Fix GH-10239 (proc_close after proc_get_status always returns -1). (nielsdos)
|
||||
. Improve the warning message for unpack() in case not enough values were
|
||||
provided. (nielsdos)
|
||||
. Fix GH-11010 (parse_ini_string() now preserves formatting of unquoted
|
||||
strings starting with numbers when the INI_SCANNER_TYPED flag is
|
||||
specified). (ilutov)
|
||||
|
||||
- Streams:
|
||||
. Fixed bug #51056: blocking fread() will block even if data is available.
|
||||
|
@ -43,6 +43,7 @@ int ini_parse(void);
|
||||
#endif
|
||||
|
||||
#define ZEND_SYSTEM_INI CG(ini_parser_unbuffered_errors)
|
||||
#define INI_ZVAL_IS_NUMBER 1
|
||||
|
||||
static int get_int_val(zval *op) {
|
||||
switch (Z_TYPE_P(op)) {
|
||||
@ -92,8 +93,12 @@ static void zend_ini_do_op(char type, zval *result, zval *op1, zval *op2)
|
||||
break;
|
||||
}
|
||||
|
||||
str_len = sprintf(str_result, "%d", i_result);
|
||||
ZVAL_NEW_STR(result, zend_string_init(str_result, str_len, ZEND_SYSTEM_INI));
|
||||
if (INI_SCNG(scanner_mode) != ZEND_INI_SCANNER_TYPED) {
|
||||
str_len = sprintf(str_result, "%d", i_result);
|
||||
ZVAL_NEW_STR(result, zend_string_init(str_result, str_len, ZEND_SYSTEM_INI));
|
||||
} else {
|
||||
ZVAL_LONG(result, i_result);
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
@ -276,6 +281,41 @@ static void zval_ini_dtor(zval *zv)
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
static inline zend_result convert_to_number(zval *retval, const char *str, const int str_len)
|
||||
{
|
||||
uint8_t type;
|
||||
int overflow;
|
||||
zend_long lval;
|
||||
double dval;
|
||||
|
||||
if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow, NULL)) != 0) {
|
||||
if (type == IS_LONG) {
|
||||
ZVAL_LONG(retval, lval);
|
||||
return SUCCESS;
|
||||
} else if (type == IS_DOUBLE && !overflow) {
|
||||
ZVAL_DOUBLE(retval, dval);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static void normalize_value(zval *zv)
|
||||
{
|
||||
if (INI_SCNG(scanner_mode) != ZEND_INI_SCANNER_TYPED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Z_EXTRA_P(zv) == INI_ZVAL_IS_NUMBER && Z_TYPE_P(zv) == IS_STRING) {
|
||||
zval number_rv;
|
||||
if (convert_to_number(&number_rv, Z_STRVAL_P(zv), Z_STRLEN_P(zv)) == SUCCESS) {
|
||||
zval_ptr_dtor(zv);
|
||||
ZVAL_COPY_VALUE(zv, &number_rv);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
%expect 0
|
||||
@ -351,7 +391,7 @@ section_string_or_value:
|
||||
;
|
||||
|
||||
string_or_value:
|
||||
expr { $$ = $1; }
|
||||
expr { $$ = $1; normalize_value(&$$); }
|
||||
| BOOL_TRUE { $$ = $1; }
|
||||
| BOOL_FALSE { $$ = $1; }
|
||||
| NULL_NULL { $$ = $1; }
|
||||
@ -412,7 +452,11 @@ constant_literal:
|
||||
constant_string:
|
||||
TC_CONSTANT { zend_ini_get_constant(&$$, &$1); }
|
||||
| TC_RAW { $$ = $1; /*printf("TC_RAW: '%s'\n", Z_STRVAL($1));*/ }
|
||||
| TC_NUMBER { $$ = $1; /*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/ }
|
||||
| TC_NUMBER {
|
||||
$$ = $1;
|
||||
Z_EXTRA($$) = INI_ZVAL_IS_NUMBER;
|
||||
/*printf("TC_NUMBER: '%s'\n", Z_STRVAL($1));*/
|
||||
}
|
||||
| TC_STRING { $$ = $1; /*printf("TC_STRING: '%s'\n", Z_STRVAL($1));*/ }
|
||||
| TC_WHITESPACE { $$ = $1; /*printf("TC_WHITESPACE: '%s'\n", Z_STRVAL($1));*/ }
|
||||
;
|
||||
|
@ -151,26 +151,6 @@ ZEND_API zend_ini_scanner_globals ini_scanner_globals;
|
||||
return type; \
|
||||
}
|
||||
|
||||
static inline zend_result convert_to_number(zval *retval, const char *str, const int str_len)
|
||||
{
|
||||
uint8_t type;
|
||||
int overflow;
|
||||
zend_long lval;
|
||||
double dval;
|
||||
|
||||
if ((type = is_numeric_string_ex(str, str_len, &lval, &dval, 0, &overflow, NULL)) != 0) {
|
||||
if (type == IS_LONG) {
|
||||
ZVAL_LONG(retval, lval);
|
||||
return SUCCESS;
|
||||
} else if (type == IS_DOUBLE && !overflow) {
|
||||
ZVAL_DOUBLE(retval, dval);
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return FAILURE;
|
||||
}
|
||||
|
||||
static void zend_ini_copy_typed_value(zval *retval, const int type, const char *str, int len)
|
||||
{
|
||||
switch (type) {
|
||||
@ -183,11 +163,6 @@ static void zend_ini_copy_typed_value(zval *retval, const int type, const char *
|
||||
ZVAL_NULL(retval);
|
||||
break;
|
||||
|
||||
case TC_NUMBER:
|
||||
if (convert_to_number(retval, str, len) == SUCCESS) {
|
||||
break;
|
||||
}
|
||||
ZEND_FALLTHROUGH;
|
||||
default:
|
||||
zend_ini_copy_value(retval, str, len);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ array(%d) {
|
||||
["foo"]=>
|
||||
array(%d) {
|
||||
[123]=>
|
||||
string(%d) "24575"
|
||||
int(24575)
|
||||
[456]=>
|
||||
int(123)
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ var_dump(parse_ini_string($ini, true, INI_SCANNER_TYPED));
|
||||
--EXPECT--
|
||||
array(2) {
|
||||
["val1"]=>
|
||||
string(1) "2"
|
||||
int(2)
|
||||
["val2"]=>
|
||||
string(1) "2"
|
||||
int(2)
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ array(1) {
|
||||
["foo"]=>
|
||||
array(1) {
|
||||
["bar"]=>
|
||||
string(1) "1"
|
||||
int(1)
|
||||
}
|
||||
}
|
||||
array(1) {
|
||||
@ -42,6 +42,6 @@ array(1) {
|
||||
["foo"]=>
|
||||
array(1) {
|
||||
["bar"]=>
|
||||
string(2) "42"
|
||||
int(42)
|
||||
}
|
||||
}
|
||||
|
9
ext/standard/tests/gh11010.phpt
Normal file
9
ext/standard/tests/gh11010.phpt
Normal file
@ -0,0 +1,9 @@
|
||||
--TEST--
|
||||
GH-11010: Preserve ini formatting of concatenated numbers
|
||||
--FILE--
|
||||
<?php
|
||||
$result = parse_ini_string('variable = -00 20 30', false, INI_SCANNER_TYPED);
|
||||
var_dump($result['variable']);
|
||||
?>
|
||||
--EXPECT--
|
||||
string(9) "-00 20 30"
|
Loading…
Reference in New Issue
Block a user