mirror of
https://github.com/golang/go
synced 2024-11-19 17:44:43 -07:00
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>
This commit is contained in:
parent
bb1fd3b5ff
commit
3043c355f4
80
src/bytes/boundary_test.go
Normal file
80
src/bytes/boundary_test.go
Normal file
@ -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
|
||||
}
|
||||
}
|
@ -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])
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user