Black Lives Matter. Support the Equal Justice Initiative.

Source file src/bytes/boundary_test.go

Documentation: bytes

     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  }
    86  

View as plain text