]> granicus.if.org Git - php/commitdiff
Fix handling of overflowing invalid octal in tokenizer
authorNikita Popov <nikita.ppv@gmail.com>
Sat, 12 Oct 2019 19:27:44 +0000 (21:27 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 14 Oct 2019 14:36:27 +0000 (16:36 +0200)
If token_get_all() is used, we still need to correctly distinguish
LNUMBER vs DNUMBER here for backwards compatibility.

Zend/tests/bug71086.phpt
Zend/zend_language_scanner.l
ext/tokenizer/tests/invalid_octal_dnumber.phpt [new file with mode: 0644]

index a7600c51fd0667d99c4c3b3801891457d0759578..3e64f9c13a518f786583cb95a643094edc2166a7 100644 (file)
@@ -9,6 +9,6 @@ var_dump($highlightedString);
 ?>
 --EXPECT--
 string(169) "<code><span style="color: #000000">
-<span style="color: #0000BB">&lt;?php&nbsp;<br />&nbsp;</span><span style="color: #007700">09&nbsp;09&nbsp;09;</span>
+<span style="color: #0000BB">&lt;?php&nbsp;<br />&nbsp;09&nbsp;09&nbsp;09</span><span style="color: #007700">;</span>
 </span>
 </code>"
index fbcdd2c9b650f44986c46d6415b8e95dcb329e06..7dcb4dfcee11739456b9f75c43f985e449f03343 100644 (file)
@@ -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 (file)
index 0000000..ebe2bc4
--- /dev/null
@@ -0,0 +1,8 @@
+--TEST--
+Invalid octal number that overflows to double
+--FILE--
+<?php
+echo token_name(token_get_all('<?php 0177777777777777777777787')[1][0]), "\n";
+?>
+--EXPECT--
+T_DNUMBER