github.com/code-reading/golang@v0.0.0-20220303082512-ba5bc0e589a3/go/src/bytes/boundary_test.go (about) 1 // Copyright 2017 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 // 5 //go:build linux 6 // +build linux 7 8 package bytes_test 9 10 import ( 11 . "bytes" 12 "syscall" 13 "testing" 14 ) 15 16 // This file tests the situation where byte operations are checking 17 // data very near to a page boundary. We want to make sure those 18 // operations do not read across the boundary and cause a page 19 // fault where they shouldn't. 20 21 // These tests run only on linux. The code being tested is 22 // not OS-specific, so it does not need to be tested on all 23 // operating systems. 24 25 // dangerousSlice returns a slice which is immediately 26 // preceded and followed by a faulting page. 27 func dangerousSlice(t *testing.T) []byte { 28 pagesize := syscall.Getpagesize() 29 b, err := syscall.Mmap(0, 0, 3*pagesize, syscall.PROT_READ|syscall.PROT_WRITE, syscall.MAP_ANONYMOUS|syscall.MAP_PRIVATE) 30 if err != nil { 31 t.Fatalf("mmap failed %s", err) 32 } 33 err = syscall.Mprotect(b[:pagesize], syscall.PROT_NONE) 34 if err != nil { 35 t.Fatalf("mprotect low failed %s\n", err) 36 } 37 err = syscall.Mprotect(b[2*pagesize:], syscall.PROT_NONE) 38 if err != nil { 39 t.Fatalf("mprotect high failed %s\n", err) 40 } 41 return b[pagesize : 2*pagesize] 42 } 43 44 func TestEqualNearPageBoundary(t *testing.T) { 45 t.Parallel() 46 b := dangerousSlice(t) 47 for i := range b { 48 b[i] = 'A' 49 } 50 for i := 0; i <= len(b); i++ { 51 Equal(b[:i], b[len(b)-i:]) 52 Equal(b[len(b)-i:], b[:i]) 53 } 54 } 55 56 func TestIndexByteNearPageBoundary(t *testing.T) { 57 t.Parallel() 58 b := dangerousSlice(t) 59 for i := range b { 60 idx := IndexByte(b[i:], 1) 61 if idx != -1 { 62 t.Fatalf("IndexByte(b[%d:])=%d, want -1\n", i, idx) 63 } 64 } 65 } 66 67 func TestIndexNearPageBoundary(t *testing.T) { 68 t.Parallel() 69 var q [64]byte 70 b := dangerousSlice(t) 71 if len(b) > 256 { 72 // Only worry about when we're near the end of a page. 73 b = b[len(b)-256:] 74 } 75 for j := 1; j < len(q); j++ { 76 q[j-1] = 1 // difference is only found on the last byte 77 for i := range b { 78 idx := Index(b[i:], q[:j]) 79 if idx != -1 { 80 t.Fatalf("Index(b[%d:], q[:%d])=%d, want -1\n", i, j, idx) 81 } 82 } 83 q[j-1] = 0 84 } 85 }