]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/gc: do not reuse bool temporaries for composite equality.
authorRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 1 Apr 2013 19:01:50 +0000 (21:01 +0200)
committerRémy Oudompheng <oudomphe@phare.normalesup.org>
Mon, 1 Apr 2013 19:01:50 +0000 (21:01 +0200)
Reusing it when multiple comparisons occurred in the same
function call led to bad overwriting.

Fixes #5162.

R=golang-dev, daniel.morsing
CC=golang-dev
https://golang.org/cl/8174047

src/cmd/gc/walk.c
test/fixedbugs/issue5162.go [new file with mode: 0644]

index 50e05fc3cf7fd069f1cfdffd1fd2d1d36ceb7d13..4e42b182fe062ab35088ca6d7d48454289c94140 100644 (file)
@@ -2856,11 +2856,19 @@ walkcompare(Node **np, NodeList **init)
        typecheck(&call, Etop);
        walkstmt(&call);
        *init = list(*init, call);
-       
-       if(n->op == OEQ)
-               r = tempbool;
-       else
-               r = nod(ONOT, tempbool, N);
+
+       // tempbool cannot be used directly as multiple comparison
+       // expressions may exist in the same statement. Create another
+       // temporary to hold the value (its address is not taken so it can
+       // be optimized away).
+       r = temp(types[TBOOL]);
+       a = nod(OAS, r, tempbool);
+       typecheck(&a, Etop);
+       walkstmt(&a);
+       *init = list(*init, a);
+
+       if(n->op != OEQ)
+               r = nod(ONOT, r, N);
        typecheck(&r, Erv);
        walkexpr(&r, init);
        *np = r;
diff --git a/test/fixedbugs/issue5162.go b/test/fixedbugs/issue5162.go
new file mode 100644 (file)
index 0000000..b14eae7
--- /dev/null
@@ -0,0 +1,88 @@
+// runoutput
+
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// issue 5162: bad array equality when multiple comparisons
+// happen in the same expression.
+
+package main
+
+import (
+       "fmt"
+       "strings"
+)
+
+const template = `
+func CheckEqNNN_TTT() {
+       onesA := [NNN]ttt{ONES}
+       onesB := [NNN]ttt{ONES}
+       twos := [NNN]ttt{TWOS}
+       if onesA != onesB {
+               println("onesA != onesB in CheckEqNNN_TTT")
+       }
+       if onesA == twos {
+               println("onesA == twos in CheckEqNNN_TTT")
+       }
+       if onesB == twos {
+               println("onesB == twos in CheckEqNNN_TTT")
+       }
+       if s := fmt.Sprint(onesA == onesB, onesA != twos, onesB != twos); s != "true true true" {
+               println("fail in CheckEqNNN_TTT:", s)
+       }
+}
+
+func CheckEqNNN_TTTExtraVar() {
+       onesA := [NNN]ttt{ONES}
+       onesB := [NNN]ttt{ONES}
+       twos := [NNN]ttt{TWOS}
+       onesX := onesA
+       if onesA != onesB {
+               println("onesA != onesB in CheckEqNNN_TTTExtraVar")
+       }
+       if onesA == twos {
+               println("onesA == twos in CheckEqNNN_TTTExtraVar")
+       }
+       if onesB == twos {
+               println("onesB == twos in CheckEqNNN_TTTExtraVar")
+       }
+       if s := fmt.Sprint(onesA == onesB, onesA != twos, onesB != twos); s != "true true true" {
+               println("fail in CheckEqNNN_TTTExtraVar:", s)
+       }
+       if s := fmt.Sprint(onesB == onesX); s != "true" {
+               println("extra var fail in CheckEqNNN_TTTExtraVar")
+       }
+}
+`
+
+func main() {
+       fmt.Print("// run\n\n")
+       fmt.Print("// THIS FILE IS AUTO-GENERATED\n\n")
+       fmt.Print("package main\n\n")
+       fmt.Println(`import "fmt"`)
+
+       types := []string{
+               "int", "int8", "int16", "int32", "int64",
+               "uint", "uint8", "uint16", "uint32", "uint64",
+               "float32", "float64"}
+       tocall := make([]string, 0, 32*len(types))
+       for i := 1; i <= 32; i++ {
+               for _, typ := range types {
+                       src := template
+                       src = strings.Replace(src, "NNN", fmt.Sprint(i), -1)
+                       src = strings.Replace(src, "TTT", strings.Title(typ), -1)
+                       src = strings.Replace(src, "ttt", typ, -1)
+                       src = strings.Replace(src, "ONES", "1"+strings.Repeat(", 1", i-1), -1)
+                       src = strings.Replace(src, "TWOS", "2"+strings.Repeat(", 2", i-1), -1)
+                       fmt.Print(src)
+                       tocall = append(tocall, fmt.Sprintf("CheckEq%d_%s", i, strings.Title(typ)))
+               }
+       }
+       fmt.Println("func main() {")
+       for _, fun := range tocall {
+               fmt.Printf("\t%s()\n", fun)
+               fmt.Printf("\t%sExtraVar()\n", fun)
+       }
+       fmt.Println("}")
+}