From 641f9615cc81f2393504f569db51c02a19d26061 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Sat, 12 Oct 2019 21:27:44 +0200 Subject: [PATCH] Fix handling of overflowing invalid octal in tokenizer If token_get_all() is used, we still need to correctly distinguish LNUMBER vs DNUMBER here for backwards compatibility. --- Zend/tests/bug71086.phpt | 2 +- Zend/zend_language_scanner.l | 21 ++++++++++++------- .../tests/invalid_octal_dnumber.phpt | 8 +++++++ 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 ext/tokenizer/tests/invalid_octal_dnumber.phpt diff --git a/Zend/tests/bug71086.phpt b/Zend/tests/bug71086.phpt index a7600c51fd..3e64f9c13a 100644 --- a/Zend/tests/bug71086.phpt +++ b/Zend/tests/bug71086.phpt @@ -9,6 +9,6 @@ var_dump($highlightedString); ?> --EXPECT-- string(169) " -<?php 
 
09 09 09; +<?php 
 09 09 09
;
" diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index fbcdd2c9b6..7dcb4dfcee 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -1820,25 +1820,32 @@ NEWLINE ("\r"|"\n"|"\r\n") zend_bool is_octal = lnum[0] == '0'; zend_bool contains_underscores = (memchr(lnum, '_', len) != NULL); + if (contains_underscores) { + lnum = estrndup(lnum, len); + strip_underscores(lnum, &len); + } + /* Digits 8 and 9 are illegal in octal literals. */ if (is_octal) { size_t i; for (i = 0; i < len; i++) { if (lnum[i] == '8' || lnum[i] == '9') { zend_throw_exception(zend_ce_parse_error, "Invalid numeric literal", 0); - ZVAL_UNDEF(zendlval); if (PARSER_MODE()) { + if (contains_underscores) { + efree(lnum); + } + ZVAL_UNDEF(zendlval); RETURN_TOKEN(T_ERROR); } - RETURN_TOKEN_WITH_VAL(T_LNUMBER); + + /* Continue in order to determine if this is T_LNUMBER or T_DNUMBER. */ + len = i; + break; } } } - if (contains_underscores) { - lnum = estrndup(lnum, len); - strip_underscores(lnum, &len); - } if (len < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */ errno = 0; @@ -1850,7 +1857,7 @@ NEWLINE ("\r"|"\n"|"\r\n") ZVAL_LONG(zendlval, ZEND_STRTOL(lnum, &end, 0)); if (errno == ERANGE) { /* Overflow */ errno = 0; - if (lnum[0] == '0') { /* octal overflow */ + if (is_octal) { /* octal overflow */ ZVAL_DOUBLE(zendlval, zend_oct_strtod(lnum, (const char **)&end)); } else { ZVAL_DOUBLE(zendlval, zend_strtod(lnum, (const char **)&end)); diff --git a/ext/tokenizer/tests/invalid_octal_dnumber.phpt b/ext/tokenizer/tests/invalid_octal_dnumber.phpt new file mode 100644 index 0000000000..ebe2bc4bcd --- /dev/null +++ b/ext/tokenizer/tests/invalid_octal_dnumber.phpt @@ -0,0 +1,8 @@ +--TEST-- +Invalid octal number that overflows to double +--FILE-- + +--EXPECT-- +T_DNUMBER -- 2.50.0