Source file test/fixedbugs/issue79874.go
1 // run 2 3 //go:build (linux || darwin) && !(386 || arm || mips || mipsle) 4 5 // Copyright 2026 The Go Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 9 package main 10 11 import ( 12 "encoding/binary" 13 "fmt" 14 "syscall" 15 "unsafe" 16 ) 17 18 const l = 1 << 34 19 20 //go:noinline 21 func bug(s []byte) []byte { 22 if len(s) < l+8 { 23 panic("too short") 24 } 25 return s[min(l, len(s)):] 26 } 27 28 func main() { 29 // This code is a bit tricky because I have two contradictory constraints: 30 // 1. I need a slice >4GB big, ideally more (to test with non byte size element). 31 // 2. I can't allocate 4GB of ram in a test, let alone the 16GB I ended up using for real. 32 pageSize := syscall.Getpagesize() 33 34 // Allocate a bunch of zeros, because this MAP_ANON mapping lack the PROT_WRITE permission 35 // the kernel will use a single shared aliased zero page to back up this memory. 36 // We still pay on the order of 32MB for the page table entries but it's acceptable. 37 s, err := syscall.Mmap(-1, 0, l+pageSize, syscall.PROT_READ, syscall.MAP_ANON|syscall.MAP_PRIVATE) 38 if err != nil { 39 panic(err) 40 } 41 42 // Make the tail page writable. Use unsafe.Slice rather than s[l:] because s[l:] goes through the slicemask path under test. 43 if err := syscall.Mprotect(unsafe.Slice(&s[l], pageSize), syscall.PROT_READ|syscall.PROT_WRITE); err != nil { 44 panic(err) 45 } 46 47 // Write without using s[l:] otherwise the same bug happens here and in bug making the test pass even if the bug is present. 48 const sentinel uint64 = 0x1122334455667788 49 for i := 0; i < 8; i++ { 50 s[l+i] = byte(sentinel >> (8 * i)) 51 } 52 53 // Finally test the bug. 54 if v := binary.LittleEndian.Uint64(bug(s)); v != sentinel { 55 panic(fmt.Sprintf("got %x, want %x", v, sentinel)) 56 } 57 } 58