diff --git a/src/strconv/atof.go b/src/strconv/atof.go index 190b25fbf57..23de70b1c9b 100644 --- a/src/strconv/atof.go +++ b/src/strconv/atof.go @@ -84,7 +84,7 @@ func (b *decimal) set(s string) (ok bool) { for ; i < len(s); i++ { switch { case s[i] == '_': - // underscoreOK already called + // readFloat already checked underscores continue case s[i] == '.': if sawdot { @@ -140,7 +140,7 @@ func (b *decimal) set(s string) (ok bool) { e := 0 for ; i < len(s) && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ { if s[i] == '_' { - // underscoreOK already called + // readFloat already checked underscores continue } if e < 10000 { @@ -159,10 +159,11 @@ func (b *decimal) set(s string) (ok bool) { } // readFloat reads a decimal mantissa and exponent from a float -// string representation. It returns ok==false if the number could -// not fit return types or is invalid. +// string representation. It returns ok==false if the number +// is invalid. func readFloat(s string) (mantissa uint64, exp int, neg, trunc, hex, ok bool) { i := 0 + underscores := false // optional sign if i >= len(s) { @@ -195,7 +196,7 @@ func readFloat(s string) (mantissa uint64, exp int, neg, trunc, hex, ok bool) { for ; i < len(s); i++ { switch c := s[i]; true { case c == '_': - // underscoreOK already called + underscores = true continue case c == '.': @@ -271,7 +272,7 @@ func readFloat(s string) (mantissa uint64, exp int, neg, trunc, hex, ok bool) { e := 0 for ; i < len(s) && ('0' <= s[i] && s[i] <= '9' || s[i] == '_'); i++ { if s[i] == '_' { - // underscoreOK already called + underscores = true continue } if e < 10000 { @@ -291,6 +292,11 @@ func readFloat(s string) (mantissa uint64, exp int, neg, trunc, hex, ok bool) { if mantissa != 0 { exp = dp - ndMant } + + if underscores && !underscoreOK(s) { + return + } + ok = true return } @@ -554,12 +560,16 @@ func atof32(s string) (f float32, err error) { } mantissa, exp, neg, trunc, hex, ok := readFloat(s) - if hex && ok { + if !ok { + return 0, syntaxError(fnParseFloat, s) + } + + if hex { f, err := atofHex(s, &float32info, mantissa, exp, neg, trunc) return float32(f), err } - if optimize && ok { + if optimize { // Try pure floating-point arithmetic conversion. if !trunc { if f, ok := atof32exact(mantissa, exp, neg); ok { @@ -597,11 +607,15 @@ func atof64(s string) (f float64, err error) { } mantissa, exp, neg, trunc, hex, ok := readFloat(s) - if hex && ok { + if !ok { + return 0, syntaxError(fnParseFloat, s) + } + + if hex { return atofHex(s, &float64info, mantissa, exp, neg, trunc) } - if optimize && ok { + if optimize { // Try pure floating-point arithmetic conversion. if !trunc { if f, ok := atof64exact(mantissa, exp, neg); ok { @@ -658,9 +672,6 @@ func atof64(s string) (f float64, err error) { // ParseFloat recognizes the strings "NaN", "+Inf", and "-Inf" as their // respective special floating point values. It ignores case when matching. func ParseFloat(s string, bitSize int) (float64, error) { - if !underscoreOK(s) { - return 0, syntaxError(fnParseFloat, s) - } if bitSize == 32 { f, err := atof32(s) return float64(f), err diff --git a/src/strconv/atoi.go b/src/strconv/atoi.go index e811bc4df1a..131b088e31b 100644 --- a/src/strconv/atoi.go +++ b/src/strconv/atoi.go @@ -58,7 +58,7 @@ const maxUint64 = 1<<64 - 1 func ParseUint(s string, base int, bitSize int) (uint64, error) { const fnParseUint = "ParseUint" - if s == "" || !underscoreOK(s) { + if s == "" { return 0, syntaxError(fnParseUint, s) } @@ -113,12 +113,13 @@ func ParseUint(s string, base int, bitSize int) (uint64, error) { maxVal := uint64(1)<