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.
15 // This file tests the situation where byte operations are checking
16 // data very near to a page boundary. We want to make sure those
17 // operations do not read across the boundary and cause a page
18 // fault where they shouldn't.
20 // These tests run only on linux. The code being tested is
21 // not OS-specific, so it does not need to be tested on all
24 // dangerousSlice returns a slice which is immediately
25 // preceded and followed by a faulting page.
26 func dangerousSlice(t
*testing
.T
) []byte {
27 pagesize
:= syscall
.Getpagesize()
28 b
, err
:= syscall
.Mmap(0, 0, 3*pagesize
, syscall
.PROT_READ|syscall
.PROT_WRITE
, syscall
.MAP_ANONYMOUS|syscall
.MAP_PRIVATE
)
30 t
.Fatalf("mmap failed %s", err
)
32 err
= syscall
.Mprotect(b
[:pagesize
], syscall
.PROT_NONE
)
34 t
.Fatalf("mprotect low failed %s\n", err
)
36 err
= syscall
.Mprotect(b
[2*pagesize
:], syscall
.PROT_NONE
)
38 t
.Fatalf("mprotect high failed %s\n", err
)
40 return b
[pagesize
: 2*pagesize
]
43 func TestEqualNearPageBoundary(t
*testing
.T
) {
45 b
:= dangerousSlice(t
)
49 for i
:= 0; i
<= len(b
); i
++ {
50 Equal(b
[:i
], b
[len(b
)-i
:])
51 Equal(b
[len(b
)-i
:], b
[:i
])
55 func TestIndexByteNearPageBoundary(t
*testing
.T
) {
57 b
:= dangerousSlice(t
)
59 idx
:= IndexByte(b
[i
:], 1)
61 t
.Fatalf("IndexByte(b[%d:])=%d, want -1\n", i
, idx
)
66 func TestIndexNearPageBoundary(t
*testing
.T
) {
69 b
:= dangerousSlice(t
)
71 // Only worry about when we're near the end of a page.
74 for j
:= 1; j
< len(q
); j
++ {
75 q
[j
-1] = 1 // difference is only found on the last byte
77 idx
:= Index(b
[i
:], q
[:j
])
79 t
.Fatalf("Index(b[%d:], q[:%d])=%d, want -1\n", i
, j
, idx
)