1
0
mirror of https://github.com/golang/go synced 2024-11-13 19:00:25 -07:00

text/scanner: don't allow Float exponents with no mantissa

Previously Scanner would allow float literals like "1.5e" and "1e+"
that weren't actually valid Go float literals, and also not valid
when passed to ParseFloat. This commit fixes that behaviour to match
the documentation ("recognizes all literals as defined by the Go
language specification"), and Scanner emits an error in these cases.

Fixes #26374

Change-Id: I6855402ea43febb448c6dff105b9578e31803c01
Reviewed-on: https://go-review.googlesource.com/129095
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
Ben Hoyt 2018-08-11 12:02:52 +02:00 committed by Robert Griesemer
parent 7b9c2c1950
commit 6c7e199e50
2 changed files with 30 additions and 0 deletions

View File

@ -384,6 +384,9 @@ func (s *Scanner) scanExponent(ch rune) rune {
if ch == '-' || ch == '+' { if ch == '-' || ch == '+' {
ch = s.next() ch = s.next()
} }
if !isDecimal(ch) {
s.error("illegal exponent")
}
ch = s.scanMantissa(ch) ch = s.scanMantissa(ch)
} }
return ch return ch

View File

@ -252,6 +252,14 @@ func checkTok(t *testing.T, s *Scanner, line int, got, want rune, text string) {
} }
} }
func checkTokErr(t *testing.T, s *Scanner, line int, want rune, text string) {
prevCount := s.ErrorCount
checkTok(t, s, line, s.Scan(), want, text)
if s.ErrorCount != prevCount+1 {
t.Fatalf("want error for %q", text)
}
}
func countNewlines(s string) int { func countNewlines(s string) int {
n := 0 n := 0
for _, ch := range s { for _, ch := range s {
@ -282,6 +290,21 @@ func TestScan(t *testing.T) {
testScan(t, GoTokens&^SkipComments) testScan(t, GoTokens&^SkipComments)
} }
func TestIllegalExponent(t *testing.T) {
const src = "1.5e 1.5E 1e+ 1e- 1.5z"
s := new(Scanner).Init(strings.NewReader(src))
checkTokErr(t, s, 1, Float, "1.5e")
checkTokErr(t, s, 1, Float, "1.5E")
checkTokErr(t, s, 1, Float, "1e+")
checkTokErr(t, s, 1, Float, "1e-")
checkTok(t, s, 1, s.Scan(), Float, "1.5")
checkTok(t, s, 1, s.Scan(), Ident, "z")
checkTok(t, s, 1, s.Scan(), EOF, "")
if s.ErrorCount != 4 {
t.Errorf("%d errors, want 4", s.ErrorCount)
}
}
func TestPosition(t *testing.T) { func TestPosition(t *testing.T) {
src := makeSource("\t\t\t\t%s\n") src := makeSource("\t\t\t\t%s\n")
s := new(Scanner).Init(src) s := new(Scanner).Init(src)
@ -475,6 +498,10 @@ func TestError(t *testing.T) {
testError(t, `0x`, "<input>:1:3", "illegal hexadecimal number", Int) testError(t, `0x`, "<input>:1:3", "illegal hexadecimal number", Int)
testError(t, `0xg`, "<input>:1:3", "illegal hexadecimal number", Int) testError(t, `0xg`, "<input>:1:3", "illegal hexadecimal number", Int)
testError(t, `'aa'`, "<input>:1:4", "illegal char literal", Char) testError(t, `'aa'`, "<input>:1:4", "illegal char literal", Char)
testError(t, `1.5e`, "<input>:1:5", "illegal exponent", Float)
testError(t, `1.5E`, "<input>:1:5", "illegal exponent", Float)
testError(t, `1.5e+`, "<input>:1:6", "illegal exponent", Float)
testError(t, `1.5e-`, "<input>:1:6", "illegal exponent", Float)
testError(t, `'`, "<input>:1:2", "literal not terminated", Char) testError(t, `'`, "<input>:1:2", "literal not terminated", Char)
testError(t, `'`+"\n", "<input>:1:2", "literal not terminated", Char) testError(t, `'`+"\n", "<input>:1:2", "literal not terminated", Char)