aboutsummaryrefslogtreecommitdiffstats
path: root/device/peer_test.go
diff options
context:
space:
mode:
authorDavid Anderson <danderson@tailscale.com>2020-03-01 00:39:24 -0800
committerJason A. Donenfeld <Jason@zx2c4.com>2020-05-02 01:44:58 -0600
commit3dce460c88a84922fdeab246a1b3ebddf796093d (patch)
tree5dce6888bf00812cc501afae45cbdac707fc352e /device/peer_test.go
parentrwcancel: no-op builds for windows and darwin (diff)
downloadwireguard-go-3dce460c88a84922fdeab246a1b3ebddf796093d.tar.xz
wireguard-go-3dce460c88a84922fdeab246a1b3ebddf796093d.zip
device: add test to ensure Peer fields are safe for atomic access on 32-bit
Adds a test that will fail consistently on 32-bit platforms if the struct ever changes again to violate the rules. This is likely not needed because unaligned access crashes reliably, but this will reliably fail even if tests accidentally pass due to lucky alignment. Signed-Off-By: David Anderson <danderson@tailscale.com>
Diffstat (limited to 'device/peer_test.go')
-rw-r--r--device/peer_test.go43
1 files changed, 43 insertions, 0 deletions
diff --git a/device/peer_test.go b/device/peer_test.go
new file mode 100644
index 0000000..b389f1e
--- /dev/null
+++ b/device/peer_test.go
@@ -0,0 +1,43 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package device
+
+import (
+ "reflect"
+ "testing"
+ "unsafe"
+)
+
+func checkAlignment(t *testing.T, name string, offset uintptr) {
+ t.Helper()
+ if offset%8 != 0 {
+ t.Errorf("offset of %q within struct is %d bytes, which does not align to 64-bit word boundaries (missing %d bytes). Atomic operations will crash on 32-bit systems.", name, offset, 8-(offset%8))
+ }
+}
+
+// TestPeerAlignment checks that atomically-accessed fields are
+// aligned to 64-bit boundaries, as required by the atomic package.
+//
+// Unfortunately, violating this rule on 32-bit platforms results in a
+// hard segfault at runtime.
+func TestPeerAlignment(t *testing.T) {
+ var p Peer
+
+ typ := reflect.TypeOf(p)
+ t.Logf("Peer type size: %d, with fields:", typ.Size())
+ for i := 0; i < typ.NumField(); i++ {
+ field := typ.Field(i)
+ t.Logf("\t%30s\toffset=%3v\t(type size=%3d, align=%d)",
+ field.Name,
+ field.Offset,
+ field.Type.Size(),
+ field.Type.Align(),
+ )
+ }
+
+ checkAlignment(t, "Peer.stats", unsafe.Offsetof(p.stats))
+ checkAlignment(t, "Peer.isRunning", unsafe.Offsetof(p.isRunning))
+}