summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTony Cook <tony@develop-help.com>2017-08-03 12:11:56 +1000
committerTony Cook <tony@develop-help.com>2017-08-14 15:38:54 +1000
commitadb0f5c46e10ac97fd958f4cd5526ea6d4b058f6 (patch)
tree9c7407d18b168df569e41c3057930054525f9a87
parent7aaa36b196e5a478a3d1bd32506797db7cebf0b2 (diff)
downloadperl-adb0f5c46e10ac97fd958f4cd5526ea6d4b058f6.tar.gz
(perl #131725) ignore the exponent on a decimal float if no digits
Previously the "1e-" in "1e--5" would be treated as "1", but consumed the "e-". This wasn't an issue for hex floats. I considered (and implemented) croaking instead, but this was inconsistent with the behaviour for hex floats, which only reach this code if a full hex float has been parsed.
-rw-r--r--t/lib/croak/toke10
-rw-r--r--toke.c21
2 files changed, 29 insertions, 2 deletions
diff --git a/t/lib/croak/toke b/t/lib/croak/toke
index 2603224fdd..c477be0336 100644
--- a/t/lib/croak/toke
+++ b/t/lib/croak/toke
@@ -394,3 +394,13 @@ $a = <<~ ;
EXPECT
Use of bare << to mean <<"" is forbidden at - line 1.
+########
+# NAME incomplete floating point decimal exponent (#131725)
+1e--5
+EXPECT
+Bareword found where operator expected at - line 1, near "1e"
+ (Missing operator before e?)
+Number found where operator expected at - line 1, near "--5"
+ (Missing operator before 5?)
+syntax error at - line 1, near "1e"
+Execution of - aborted due to compilation errors.
diff --git a/toke.c b/toke.c
index 6aa5f2690e..6de7d09ea4 100644
--- a/toke.c
+++ b/toke.c
@@ -11182,9 +11182,11 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
|| UNLIKELY(hexfp && isALPHA_FOLD_EQ(*s, 'p')))
&& strchr("+-0123456789_", s[1]))
{
- floatit = TRUE;
+ int exp_digits = 0;
+ const char *save_s = s;
+ char * save_d = d;
- /* regardless of whether user said 3E5 or 3e5, use lower 'e',
+ /* regardless of whether user said 3E5 or 3e5, use lower 'e',
ditto for p (hexfloats) */
if ((isALPHA_FOLD_EQ(*s, 'e'))) {
/* At least some Mach atof()s don't grok 'E' */
@@ -11216,6 +11218,7 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
/* read digits of exponent */
while (isDIGIT(*s) || *s == '_') {
if (isDIGIT(*s)) {
+ ++exp_digits;
if (d >= e)
Perl_croak(aTHX_ "%s", number_too_long);
*d++ = *s++;
@@ -11227,6 +11230,20 @@ Perl_scan_num(pTHX_ const char *start, YYSTYPE* lvalp)
lastub = s++;
}
}
+
+ if (!exp_digits) {
+ /* no exponent digits, the [eEpP] could be for something else,
+ * though in practice we don't get here for p since that's preparsed
+ * earlier, and results in only the 0xX being consumed, so behave similarly
+ * for decimal floats and consume only the D.DD, leaving the [eE] to the
+ * next token.
+ */
+ s = save_s;
+ d = save_d;
+ }
+ else {
+ floatit = TRUE;
+ }
}