]> Cypherpunks repositories - gostls13.git/commitdiff
sync/atomic: make unaligned 64-bit atomics crash on 386
authorRuss Cox <rsc@golang.org>
Mon, 11 Mar 2013 16:21:46 +0000 (12:21 -0400)
committerRuss Cox <rsc@golang.org>
Mon, 11 Mar 2013 16:21:46 +0000 (12:21 -0400)
R=golang-dev, bradfitz, dvyukov
CC=golang-dev
https://golang.org/cl/7702043

src/pkg/sync/atomic/asm_386.s
src/pkg/sync/atomic/atomic_test.go

index 7a98a61d8017d1b695a1dd85ff15c0a04c5e6584..19d129bcb74ac2cc1f33ee24f13421909c5718a7 100644 (file)
@@ -28,6 +28,9 @@ TEXT ·CompareAndSwapInt64(SB),7,$0
 
 TEXT ·CompareAndSwapUint64(SB),7,$0
        MOVL    addr+0(FP), BP
+       TESTL   $7, BP
+       JZ      2(PC)
+       MOVL    0, AX // crash with nil ptr deref
        MOVL    old+4(FP), AX
        MOVL    old+8(FP), DX
        MOVL    new+12(FP), BX
@@ -61,6 +64,9 @@ TEXT ·AddInt64(SB),7,$0
 TEXT ·AddUint64(SB),7,$0
        // no XADDQ so use CMPXCHG8B loop
        MOVL    addr+0(FP), BP
+       TESTL   $7, BP
+       JZ      2(PC)
+       MOVL    0, AX // crash with nil ptr deref
        // DI:SI = delta
        MOVL    delta+4(FP), SI
        MOVL    delta+8(FP), DI
@@ -105,6 +111,9 @@ TEXT ·LoadInt64(SB),7,$0
 
 TEXT ·LoadUint64(SB),7,$0
        MOVL    addr+0(FP), AX
+       TESTL   $7, AX
+       JZ      2(PC)
+       MOVL    0, AX // crash with nil ptr deref
        // MOVQ and EMMS were introduced on the Pentium MMX.
        // MOVQ (%EAX), %MM0
        BYTE $0x0f; BYTE $0x6f; BYTE $0x00
@@ -133,6 +142,9 @@ TEXT ·StoreInt64(SB),7,$0
 
 TEXT ·StoreUint64(SB),7,$0
        MOVL    addr+0(FP), AX
+       TESTL   $7, AX
+       JZ      2(PC)
+       MOVL    0, AX // crash with nil ptr deref
        // MOVQ and EMMS were introduced on the Pentium MMX.
        // MOVQ 0x8(%ESP), %MM0
        BYTE $0x0f; BYTE $0x6f; BYTE $0x44; BYTE $0x24; BYTE $0x08
index 3e105561c4efcc679c861a0fc536194693140c5b..72f303040fe8b1b49e76c42f249d46acf0dd0446 100644 (file)
@@ -1177,3 +1177,29 @@ func TestStoreLoadRelAcq64(t *testing.T) {
        <-c
        <-c
 }
+
+func shouldPanic(t *testing.T, name string, f func()) {
+       defer func() {
+               if recover() == nil {
+                       t.Errorf("%s did not panic", name)
+               }
+       }()
+       f()
+}
+
+func TestUnaligned64(t *testing.T) {
+       // Unaligned 64-bit atomics on 32-bit systems are
+       // a continual source of pain. Test that on 386 they crash
+       // instead of failing silently.
+       if runtime.GOARCH != "386" {
+               t.Skip("test only runs on 386")
+       }
+
+       x := make([]uint32, 4)
+       p := (*uint64)(unsafe.Pointer(&x[1])) // misaligned
+
+       shouldPanic(t, "LoadUint64", func() { LoadUint64(p) })
+       shouldPanic(t, "StoreUint64", func() { StoreUint64(p, 1) })
+       shouldPanic(t, "CompareAndSwapUint64", func() { CompareAndSwapUint64(p, 1, 2) })
+       shouldPanic(t, "AddUint64", func() { AddUint64(p, 3) })
+}