]> Cypherpunks repositories - gostls13.git/commitdiff
strconv: revert ParseFloat/ParseComplex error on incorrect bitSize
authorBen Hoyt <benhoyt@gmail.com>
Tue, 3 Nov 2020 21:13:42 +0000 (10:13 +1300)
committerIan Lance Taylor <iant@golang.org>
Tue, 3 Nov 2020 23:05:51 +0000 (23:05 +0000)
This is a partial revert of https://go-review.googlesource.com/c/go/+/248219
because we found that a non-trivial amount of code erroneously calls
ParseFloat(s, 10) or even ParseFloat(s, 0) and expects it to work --
before that change was merged, ParseFloat accepted a bitSize of
anything other than 32 or 64 to mean 64 (and ParseComplex was similar).

So revert that behavior to avoid breaking people's code, and add tests
for this.

I may add a vet check to flag ParseFloat(s, not_32_or_64) in a later
change.

See #42297 for more details.

Change-Id: I4bc0156bd74f67a39d5561b6e5fde3f2d20bd622
Reviewed-on: https://go-review.googlesource.com/c/go/+/267319
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/strconv/atoc.go
src/strconv/atoc_test.go
src/strconv/atof.go
src/strconv/atof_test.go

index 52cb5908b273e0dc088d2bc0c326358b4f575303..85c7bafefa4f3c7b88e5a3e2a1ed96954b75233d 100644 (file)
@@ -40,10 +40,10 @@ func convErr(err error, s string) (syntax, range_ error) {
 // away from the largest floating point number of the given component's size,
 // ParseComplex returns err.Err = ErrRange and c = ±Inf for the respective component.
 func ParseComplex(s string, bitSize int) (complex128, error) {
-       if bitSize != 64 && bitSize != 128 {
-               return 0, bitSizeError(fnParseComplex, s, bitSize)
+       size := 64
+       if bitSize == 64 {
+               size = 32 // complex64 uses float32 parts
        }
-       size := bitSize >> 1
 
        orig := s
 
index aecc09d247c54434aa59e0196a865681fbb7521e..4c1aad090001f69c86a77221ef5d3e6d3066a36e 100644 (file)
@@ -212,13 +212,18 @@ func TestParseComplex(t *testing.T) {
        }
 }
 
-func TestParseComplexInvalidBitSize(t *testing.T) {
-       _, err := ParseComplex("1+2i", 100)
-       const want = `strconv.ParseComplex: parsing "1+2i": invalid bit size 100`
-       if err == nil {
-               t.Fatalf("got nil error, want %q", want)
-       }
-       if err.Error() != want {
-               t.Fatalf("got error %q, want %q", err, want)
+// Issue 42297: allow ParseComplex(s, not_32_or_64) for legacy reasons
+func TestParseComplexIncorrectBitSize(t *testing.T) {
+       const s = "1.5e308+1.0e307i"
+       const want = 1.5e308 + 1.0e307i
+
+       for _, bitSize := range []int{0, 10, 100, 256} {
+               c, err := ParseComplex(s, bitSize)
+               if err != nil {
+                       t.Fatalf("ParseComplex(%q, %d) gave error %s", s, bitSize, err)
+               }
+               if c != want {
+                       t.Fatalf("ParseComplex(%q, %d) = %g (expected %g)", s, bitSize, c, want)
+               }
        }
 }
index a04f5621f6341259cf5da55662aa693250c35d82..9010a66ca8910bff4f3f886f3649aaab9edbcb59 100644 (file)
@@ -688,9 +688,6 @@ func atof64(s string) (f float64, n int, err error) {
 // ParseFloat recognizes the strings "NaN", and the (possibly signed) strings "Inf" and "Infinity"
 // as their respective special floating point values. It ignores case when matching.
 func ParseFloat(s string, bitSize int) (float64, error) {
-       if bitSize != 32 && bitSize != 64 {
-               return 0, bitSizeError(fnParseFloat, s, bitSize)
-       }
        f, n, err := parseFloatPrefix(s, bitSize)
        if err == nil && n != len(s) {
                return 0, syntaxError(fnParseFloat, s)
index cf43903506315357ef45668ed44d51d47583b982..3c058b9be5adc223414a498d6b27e812a0fba08d 100644 (file)
@@ -634,14 +634,20 @@ func TestRoundTrip32(t *testing.T) {
        t.Logf("tested %d float32's", count)
 }
 
-func TestParseFloatInvalidBitSize(t *testing.T) {
-       _, err := ParseFloat("3.14", 100)
-       const want = `strconv.ParseFloat: parsing "3.14": invalid bit size 100`
-       if err == nil {
-               t.Fatalf("got nil error, want %q", want)
-       }
-       if err.Error() != want {
-               t.Fatalf("got error %q, want %q", err, want)
+// Issue 42297: a lot of code in the wild accidentally calls ParseFloat(s, 10)
+// or ParseFloat(s, 0), so allow bitSize values other than 32 and 64.
+func TestParseFloatIncorrectBitSize(t *testing.T) {
+       const s = "1.5e308"
+       const want = 1.5e308
+
+       for _, bitSize := range []int{0, 10, 100, 128} {
+               f, err := ParseFloat(s, bitSize)
+               if err != nil {
+                       t.Fatalf("ParseFloat(%q, %d) gave error %s", s, bitSize, err)
+               }
+               if f != want {
+                       t.Fatalf("ParseFloat(%q, %d) = %g (expected %g)", s, bitSize, f, want)
+               }
        }
 }