Skip to content

Fix ini quantity parsing bugs #17274

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions Zend/tests/zend_ini/gh16886.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
--TEST--
GH-16886 (ini_parse_quantity() fails to emit warning for 0x+0)
--FILE--
<?php
echo ini_parse_quantity('0x 0'), "\n";
echo ini_parse_quantity('0x+0'), "\n";
echo ini_parse_quantity('0x-0'), "\n";
echo ini_parse_quantity('0b 0'), "\n";
echo ini_parse_quantity('0b+0'), "\n";
echo ini_parse_quantity('0b-0'), "\n";
echo ini_parse_quantity('0o 0'), "\n";
echo ini_parse_quantity('0o+0'), "\n";
echo ini_parse_quantity('0o-0'), "\n";
?>
--EXPECTF--
Warning: Invalid quantity "0x 0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0x+0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0x-0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0b 0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0b+0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0b-0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0o 0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0o+0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0

Warning: Invalid quantity "0o-0": no digits after base prefix, interpreting as "0" for backwards compatibility in %s on line %d
0
22 changes: 22 additions & 0 deletions Zend/tests/zend_ini/gh16892.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
--TEST--
GH-16892 (ini_parse_quantity() fails to parse inputs starting with 0x0b)
--FILE--
<?php
echo ini_parse_quantity('0x0b'), "\n";
echo ini_parse_quantity('0xb'), "\n";
echo ini_parse_quantity('-0x0B'), "\n";
echo ini_parse_quantity('-0xB'), "\n";
echo ini_parse_quantity('0x0beef'), "\n";
echo ini_parse_quantity('0xbeef'), "\n";
echo ini_parse_quantity('-0x0BEEF'), "\n";
echo ini_parse_quantity('-0xBEEF'), "\n";
?>
--EXPECT--
11
11
-11
-11
48879
48879
-48879
-48879
25 changes: 9 additions & 16 deletions Zend/zend_ini.c
Original file line number Diff line number Diff line change
Expand Up @@ -587,7 +587,7 @@ typedef enum {
ZEND_INI_PARSE_QUANTITY_UNSIGNED,
} zend_ini_parse_quantity_signed_result_t;

static const char *zend_ini_consume_quantity_prefix(const char *const digits, const char *const str_end) {
static const char *zend_ini_consume_quantity_prefix(const char *const digits, const char *const str_end, int base) {
const char *digits_consumed = digits;
/* Ignore leading whitespace. */
while (digits_consumed < str_end && zend_is_whitespace(*digits_consumed)) {++digits_consumed;}
Expand All @@ -598,17 +598,22 @@ static const char *zend_ini_consume_quantity_prefix(const char *const digits, co
if (digits_consumed[0] == '0' && !isdigit(digits_consumed[1])) {
/* Value is just 0 */
if ((digits_consumed+1) == str_end) {
return digits;
return digits_consumed;
}

switch (digits_consumed[1]) {
case 'x':
case 'X':
case 'o':
case 'O':
digits_consumed += 2;
break;
case 'b':
case 'B':
digits_consumed += 2;
if (base != 16) {
/* 0b or 0B is valid in base 16, but not in the other supported bases. */
digits_consumed += 2;
}
break;
}
}
Expand Down Expand Up @@ -696,19 +701,7 @@ static zend_ulong zend_ini_parse_quantity_internal(zend_string *value, zend_ini_
return 0;
}
digits += 2;
if (UNEXPECTED(digits == str_end)) {
/* Escape the string to avoid null bytes and to make non-printable chars
* visible */
smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value));
smart_str_0(&invalid);

*errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no digits after base prefix, interpreting as \"0\" for backwards compatibility",
ZSTR_VAL(invalid.s));

smart_str_free(&invalid);
return 0;
}
if (UNEXPECTED(digits != zend_ini_consume_quantity_prefix(digits, str_end))) {
if (UNEXPECTED(digits == str_end || digits != zend_ini_consume_quantity_prefix(digits, str_end, base))) {
/* Escape the string to avoid null bytes and to make non-printable chars
* visible */
smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value));
Expand Down
Loading