diff --git a/Zend/tests/zend_ini/gh16886.phpt b/Zend/tests/zend_ini/gh16886.phpt new file mode 100644 index 0000000000000..2e85894572359 --- /dev/null +++ b/Zend/tests/zend_ini/gh16886.phpt @@ -0,0 +1,41 @@ +--TEST-- +GH-16886 (ini_parse_quantity() fails to emit warning for 0x+0) +--FILE-- + +--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 diff --git a/Zend/tests/zend_ini/gh16892.phpt b/Zend/tests/zend_ini/gh16892.phpt new file mode 100644 index 0000000000000..05cfe02192e9d --- /dev/null +++ b/Zend/tests/zend_ini/gh16892.phpt @@ -0,0 +1,22 @@ +--TEST-- +GH-16892 (ini_parse_quantity() fails to parse inputs starting with 0x0b) +--FILE-- + +--EXPECT-- +11 +11 +-11 +-11 +48879 +48879 +-48879 +-48879 diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c index 9588574df6cfb..f5d178073066e 100644 --- a/Zend/zend_ini.c +++ b/Zend/zend_ini.c @@ -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;} @@ -598,7 +598,7 @@ 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]) { @@ -606,9 +606,14 @@ static const char *zend_ini_consume_quantity_prefix(const char *const digits, co 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; } } @@ -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));