]> Cypherpunks.ru repositories - gostls13.git/commit
cmd/compile: do not assume TST and TEQ set V on arm
authorJason A. Donenfeld <Jason@zx2c4.com>
Mon, 30 Nov 2020 09:41:46 +0000 (10:41 +0100)
committerJason A. Donenfeld <Jason@zx2c4.com>
Tue, 1 Dec 2020 22:59:34 +0000 (22:59 +0000)
commit4826abb6c2f391a9fb26c83d8ec4d6bc7cc6dc1a
tree0abd5c0d4eb9f242dbf96ffd2cf0da0b1903a1a5
parent283d65413db75edbc4691c4fecf23228509436f0
cmd/compile: do not assume TST and TEQ set V on arm

These replacement rules assume that TST and TEQ set V. But TST and
TEQ do not set V. This is a problem because instructions like LT are
actually checking for N!=V. But with TST and TEQ not setting V, LT
doesn't do anything meaningful. It's possible to construct trivial
miscompilations from this, such as:

    package main

    var x = [4]int32{-0x7fffffff, 0x7fffffff, 2, 4}

    func main() {
        if x[0] > x[1] {
            panic("fail 1")
        }
        if x[2]&x[3] < 0 {
            panic("fail 2") // Fails here
        }
    }

That first comparison sets V, via the CMP that subtracts the values
causing the overflow. Then the second comparison operation thinks that
it uses the result of TST, when it actually uses the V from CMP.

Before this fix:

    TST             R0, R1
    BLT             loc_6C164

After this fix:

    TST             R0, R1
    BMI             loc_6C164

The BMI instruction checks the N flag, which TST sets.  This commit
fixes the issue by using [LG][TE]noov instead of vanilla [LG][TE], and
also adds a test case for the direct issue.

Fixes #42876.

Change-Id: I13c62c88d18574247ad002b671b38d2d0b0fc6fa
Reviewed-on: https://go-review.googlesource.com/c/go/+/274026
Run-TryBot: Jason A. Donenfeld <Jason@zx2c4.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: Jason A. Donenfeld <Jason@zx2c4.com>
src/cmd/compile/internal/ssa/gen/ARM.rules
src/cmd/compile/internal/ssa/rewriteARM.go
test/fixedbugs/issue42876.go [new file with mode: 0644]