Skip to content

cmd/compile: improve BCE to detect safe unbounded slicing #35483

Closed
@nhooyr

Description

@nhooyr

See #31586 (comment)

Core problem can be reduced to:

package scratch

import "encoding/binary"

func A1(b []byte) {
	key64 := uint64(1024)
	for len(b) >= 32 {
		v := binary.LittleEndian.Uint64(b)
		binary.LittleEndian.PutUint64(b, v^key64)
		v = binary.LittleEndian.Uint64(b[8:])
		binary.LittleEndian.PutUint64(b[8:], v^key64)
		v = binary.LittleEndian.Uint64(b[16:])
		binary.LittleEndian.PutUint64(b[16:], v^key64)
		v = binary.LittleEndian.Uint64(b[24:])
		binary.LittleEndian.PutUint64(b[24:], v^key64)
		b = b[32:]
	}
}

func A2(b []byte) {
	key64 := uint64(1024)
	for len(b) >= 32 {
		v := binary.LittleEndian.Uint64(b)
		binary.LittleEndian.PutUint64(b, v^key64)
		v = binary.LittleEndian.Uint64(b[8:16])
		binary.LittleEndian.PutUint64(b[8:16], v^key64)
		v = binary.LittleEndian.Uint64(b[16:24])
		binary.LittleEndian.PutUint64(b[16:24], v^key64)
		v = binary.LittleEndian.Uint64(b[24:32])
		binary.LittleEndian.PutUint64(b[24:32], v^key64)
		b = b[32:]
	}
}

BCE:

$ go build -gcflags="-d=ssa/check_bce/debug=1" scratch.go
# command-line-arguments
./scratch.go:10:34: Found IsInBounds
./scratch.go:12:34: Found IsInBounds
./scratch.go:14:34: Found IsInBounds

Bound checks remain in A1 even though they are not needed but are eliminated in A2 due to the explicit and not unbounded slices.

@renthraysk stated:

It was the _ = b[7] line in PutUint64() that was cause the bounds checks. The compiler failed to prove it's not needed with PutUint64(b[8:], x) however it does eliminate the first check in PutUint64(b, x).

I'm on 1.13.4 on macOS.

Metadata

Metadata

Assignees

No one assigned

    Labels

    FrozenDueToAgeNeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.Performance

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions