aboutsummaryrefslogtreecommitdiff
path: root/src/bytes
diff options
context:
space:
mode:
authorKeith Randall <keithr@alum.mit.edu>2017-11-03 10:30:14 -0700
committerKeith Randall <khr@golang.org>2017-11-03 18:51:51 +0000
commit3043c355f430bb304bc0d09d8162632baa028a83 (patch)
tree8442fb1c4cad90ac8de5e1175087c5cb9989fc69 /src/bytes
parentbb1fd3b5ff10eb9ad1a40b5bf7c7f35bd20e626f (diff)
downloadgo-3043c355f430bb304bc0d09d8162632baa028a83.tar.xz
bytes: add more page boundary tests
Make sure Index and IndexByte don't read past the queried byte slice. Hopefully will be helpful for CL 33597. Also remove the code which maps/unmaps the Go heap. Much safer to play with protection bits off-heap. Change-Id: I50d73e879b2d83285e1bc7c3e810efe4c245fe75 Reviewed-on: https://go-review.googlesource.com/75890 Reviewed-by: Ian Lance Taylor <iant@golang.org>
Diffstat (limited to 'src/bytes')
-rw-r--r--src/bytes/boundary_test.go80
-rw-r--r--src/bytes/equal_test.go47
2 files changed, 80 insertions, 47 deletions
diff --git a/src/bytes/boundary_test.go b/src/bytes/boundary_test.go
new file mode 100644
index 0000000000..f9e20e36c7
--- /dev/null
+++ b/src/bytes/boundary_test.go
@@ -0,0 +1,80 @@
+// Copyright 2017 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.
+//
+// +build linux
+
+package bytes_test
+
+import (
+ . "bytes"
+ "syscall"
+ "testing"
+)
+
+// This file tests the situation where byte operations are checking
+// data very near to a page boundary. We want to make sure those
+// operations do not read across the boundary and cause a page
+// fault where they shouldn't.
+
+// These tests run only on linux. The code being tested is
+// not OS-specific, so it does not need to be tested on all
+// operating systems.
+
+// dangerousSlice returns a slice which is immediately
+// preceded and followed by a faulting page.
+func dangerousSlice(t *testing.T) []byte {
+ pagesize := syscall.Getpagesize()
+ b, err := syscall.Mmap(0, 0, 3*pagesize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANONYMOUS|syscall.MAP_PRIVATE)
+ if err != nil {
+ t.Fatalf("mmap failed %s", err)
+ }
+ err = syscall.Mprotect(b[:pagesize], syscall.PROT_NONE)
+ if err != nil {
+ t.Fatalf("mprotect low failed %s\n", err)
+ }
+ err = syscall.Mprotect(b[2*pagesize:], syscall.PROT_NONE)
+ if err != nil {
+ t.Fatalf("mprotect high failed %s\n", err)
+ }
+ return b[pagesize : 2*pagesize]
+}
+
+func TestEqualNearPageBoundary(t *testing.T) {
+ t.Parallel()
+ b := dangerousSlice(t)
+ for i := range b {
+ b[i] = 'A'
+ }
+ for i := 0; i <= len(b); i++ {
+ Equal(b[:i], b[len(b)-i:])
+ Equal(b[len(b)-i:], b[:i])
+ }
+}
+
+func TestIndexByteNearPageBoundary(t *testing.T) {
+ t.Parallel()
+ b := dangerousSlice(t)
+ for i := range b {
+ idx := IndexByte(b[i:], 1)
+ if idx != -1 {
+ t.Fatalf("IndexByte(b[%d:])=%d, want -1\n", i, idx)
+ }
+ }
+}
+
+func TestIndexNearPageBoundary(t *testing.T) {
+ t.Parallel()
+ var q [64]byte
+ b := dangerousSlice(t)
+ for j := 1; j < len(q); j++ {
+ q[j-1] = 1 // difference is only found on the last byte
+ for i := range b {
+ idx := Index(b[i:], q[:j])
+ if idx != -1 {
+ t.Fatalf("Index(b[%d:], q[:%d])=%d, want -1\n", i, j, idx)
+ }
+ }
+ q[j-1] = 0
+ }
+}
diff --git a/src/bytes/equal_test.go b/src/bytes/equal_test.go
deleted file mode 100644
index 9fdead8a60..0000000000
--- a/src/bytes/equal_test.go
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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.
-//
-// +build linux
-
-package bytes_test
-
-import (
- . "bytes"
- "syscall"
- "testing"
- "unsafe"
-)
-
-// This file tests the situation where memeq is checking
-// data very near to a page boundary. We want to make sure
-// equal does not read across the boundary and cause a page
-// fault where it shouldn't.
-
-// This test runs only on linux. The code being tested is
-// not OS-specific, so it does not need to be tested on all
-// operating systems.
-
-func TestEqualNearPageBoundary(t *testing.T) {
- pagesize := syscall.Getpagesize()
- b := make([]byte, 4*pagesize)
- i := pagesize
- for ; uintptr(unsafe.Pointer(&b[i]))%uintptr(pagesize) != 0; i++ {
- }
- syscall.Mprotect(b[i-pagesize:i], 0)
- syscall.Mprotect(b[i+pagesize:i+2*pagesize], 0)
- defer syscall.Mprotect(b[i-pagesize:i], syscall.PROT_READ|syscall.PROT_WRITE)
- defer syscall.Mprotect(b[i+pagesize:i+2*pagesize], syscall.PROT_READ|syscall.PROT_WRITE)
-
- // both of these should fault
- //pagesize += int(b[i-1])
- //pagesize += int(b[i+pagesize])
-
- for j := 0; j < pagesize; j++ {
- b[i+j] = 'A'
- }
- for j := 0; j <= pagesize; j++ {
- Equal(b[i:i+j], b[i+pagesize-j:i+pagesize])
- Equal(b[i+pagesize-j:i+pagesize], b[i:i+j])
- }
-}