Source file test/fixedbugs/issue80519.go

     1  // run
     2  
     3  // Copyright 2026 The Go Authors. All rights reserved.
     4  // Use of this source code is governed by a BSD-style
     5  // license that can be found in the LICENSE file.
     6  
     7  package main
     8  
     9  import (
    10  	"runtime"
    11  	"unsafe"
    12  )
    13  
    14  var aliased = [3][3]int{{9, 9, 9}, {1, 9, 9}, {9, 9, 9}}
    15  var unsafeAliased [3]unsafe.Pointer
    16  
    17  type unsafeFieldTarget struct {
    18  	array *[4]uintptr
    19  	pad   [3]uintptr
    20  }
    21  
    22  //go:noinline
    23  func clearAliased() {
    24  	keyp := &aliased[1][0]
    25  	for i := range 3 {
    26  		aliased[*keyp][i] = 0
    27  	}
    28  }
    29  
    30  //go:noinline
    31  func clearUnsafeAliased() {
    32  	target := (*[3]unsafe.Pointer)(unsafe.Pointer(&unsafeAliased[0]))
    33  	unsafeAliased[0] = unsafe.Pointer(target)
    34  	targetp := (**[3]unsafe.Pointer)(unsafe.Pointer(&unsafeAliased[0]))
    35  	for i := range 3 {
    36  		(**targetp)[i] = nil
    37  	}
    38  }
    39  
    40  //go:noinline
    41  func clearUnsafeField(t *unsafeFieldTarget) {
    42  	for i := range t.array {
    43  		t.array[i] = 0
    44  	}
    45  }
    46  
    47  //go:noinline
    48  func clearUnsafeSlice() {
    49  	var values []uintptr
    50  	values = unsafe.Slice((*uintptr)(unsafe.Pointer(&values)), 3)
    51  	for i := range values {
    52  		values[i] = 0
    53  	}
    54  }
    55  
    56  func main() {
    57  	want := [3][2]int{{0, 2}, {3, 0}, {5, 6}}
    58  
    59  	rows := [3][2]int{{1, 2}, {3, 4}, {5, 6}}
    60  	key := 2
    61  	for key = range 2 {
    62  		rows[key][key] = 0
    63  	}
    64  	if rows != want || key != 1 {
    65  		panic("range clear with assigned index variable")
    66  	}
    67  
    68  	rows = [3][2]int{{1, 2}, {3, 4}, {5, 6}}
    69  	for key := range 2 {
    70  		rows[key][key] = 0
    71  	}
    72  	if rows != want {
    73  		panic("range clear with declared index variable")
    74  	}
    75  
    76  	slices := [3][]int{{1, 2}, {3, 4}, {5, 6}}
    77  	key = 0
    78  	for key = range slices[key] {
    79  		slices[key][key] = 0
    80  	}
    81  	if slices[0][0] != 0 || slices[0][1] != 2 || slices[1][0] != 3 || slices[1][1] != 0 || key != 1 {
    82  		panic("range clear with index-dependent slice")
    83  	}
    84  
    85  	rows = [3][2]int{{1, 2}, {3, 4}, {5, 6}}
    86  	key = 0
    87  	keyp := &key
    88  	for key = range 2 {
    89  		rows[*keyp][key] = 0
    90  	}
    91  	if rows != want || key != 1 {
    92  		panic("range clear with indirect index dependency")
    93  	}
    94  
    95  	clearAliased()
    96  	if aliased != [3][3]int{{9, 0, 0}, {0, 9, 9}, {9, 9, 9}} {
    97  		panic("range clear target changed through cleared memory")
    98  	}
    99  
   100  	panicked := false
   101  	func() {
   102  		defer func() {
   103  			panicked = recover() != nil
   104  		}()
   105  		clearUnsafeAliased()
   106  	}()
   107  	if !panicked {
   108  		panic("range clear target changed through unsafe pointer")
   109  	}
   110  
   111  	fieldTarget := unsafeFieldTarget{}
   112  	fieldTarget.array = (*[4]uintptr)(unsafe.Pointer(&fieldTarget))
   113  	panicked = false
   114  	func() {
   115  		defer func() {
   116  			panicked = recover() != nil
   117  		}()
   118  		clearUnsafeField(&fieldTarget)
   119  	}()
   120  	if !panicked {
   121  		panic("range clear target changed through unsafe pointer field")
   122  	}
   123  
   124  	if runtime.GOARCH != "wasm" {
   125  		panicked = false
   126  		func() {
   127  			defer func() {
   128  				panicked = recover() != nil
   129  			}()
   130  			clearUnsafeSlice()
   131  		}()
   132  		if !panicked {
   133  			panic("range clear target changed through unsafe slice header")
   134  		}
   135  	}
   136  }
   137  

View as plain text