| // run |
| |
| // Copyright 2026 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| package main |
| |
| import ( |
| "runtime" |
| "unsafe" |
| ) |
| |
| var aliased = [3][3]int{{9, 9, 9}, {1, 9, 9}, {9, 9, 9}} |
| var unsafeAliased [3]unsafe.Pointer |
| |
| type unsafeFieldTarget struct { |
| array *[4]uintptr |
| pad [3]uintptr |
| } |
| |
| //go:noinline |
| func clearAliased() { |
| keyp := &aliased[1][0] |
| for i := range 3 { |
| aliased[*keyp][i] = 0 |
| } |
| } |
| |
| //go:noinline |
| func clearUnsafeAliased() { |
| target := (*[3]unsafe.Pointer)(unsafe.Pointer(&unsafeAliased[0])) |
| unsafeAliased[0] = unsafe.Pointer(target) |
| targetp := (**[3]unsafe.Pointer)(unsafe.Pointer(&unsafeAliased[0])) |
| for i := range 3 { |
| (**targetp)[i] = nil |
| } |
| } |
| |
| //go:noinline |
| func clearUnsafeField(t *unsafeFieldTarget) { |
| for i := range t.array { |
| t.array[i] = 0 |
| } |
| } |
| |
| //go:noinline |
| func clearUnsafeSlice() { |
| var values []uintptr |
| values = unsafe.Slice((*uintptr)(unsafe.Pointer(&values)), 3) |
| for i := range values { |
| values[i] = 0 |
| } |
| } |
| |
| func main() { |
| want := [3][2]int{{0, 2}, {3, 0}, {5, 6}} |
| |
| rows := [3][2]int{{1, 2}, {3, 4}, {5, 6}} |
| key := 2 |
| for key = range 2 { |
| rows[key][key] = 0 |
| } |
| if rows != want || key != 1 { |
| panic("range clear with assigned index variable") |
| } |
| |
| rows = [3][2]int{{1, 2}, {3, 4}, {5, 6}} |
| for key := range 2 { |
| rows[key][key] = 0 |
| } |
| if rows != want { |
| panic("range clear with declared index variable") |
| } |
| |
| slices := [3][]int{{1, 2}, {3, 4}, {5, 6}} |
| key = 0 |
| for key = range slices[key] { |
| slices[key][key] = 0 |
| } |
| if slices[0][0] != 0 || slices[0][1] != 2 || slices[1][0] != 3 || slices[1][1] != 0 || key != 1 { |
| panic("range clear with index-dependent slice") |
| } |
| |
| rows = [3][2]int{{1, 2}, {3, 4}, {5, 6}} |
| key = 0 |
| keyp := &key |
| for key = range 2 { |
| rows[*keyp][key] = 0 |
| } |
| if rows != want || key != 1 { |
| panic("range clear with indirect index dependency") |
| } |
| |
| clearAliased() |
| if aliased != [3][3]int{{9, 0, 0}, {0, 9, 9}, {9, 9, 9}} { |
| panic("range clear target changed through cleared memory") |
| } |
| |
| panicked := false |
| func() { |
| defer func() { |
| panicked = recover() != nil |
| }() |
| clearUnsafeAliased() |
| }() |
| if !panicked { |
| panic("range clear target changed through unsafe pointer") |
| } |
| |
| fieldTarget := unsafeFieldTarget{} |
| fieldTarget.array = (*[4]uintptr)(unsafe.Pointer(&fieldTarget)) |
| panicked = false |
| func() { |
| defer func() { |
| panicked = recover() != nil |
| }() |
| clearUnsafeField(&fieldTarget) |
| }() |
| if !panicked { |
| panic("range clear target changed through unsafe pointer field") |
| } |
| |
| if runtime.GOARCH != "wasm" { |
| panicked = false |
| func() { |
| defer func() { |
| panicked = recover() != nil |
| }() |
| clearUnsafeSlice() |
| }() |
| if !panicked { |
| panic("range clear target changed through unsafe slice header") |
| } |
| } |
| } |