fix(verify): arm64 stack save, adaptive canary and host gating
Assisted-by: GLM 5.3
This commit is contained in:
+50
-11
@@ -20,7 +20,11 @@ type BufSpec struct {
|
||||
}
|
||||
|
||||
// ParseBufSpec parses a "name:size:pattern[,name:size:pattern]" spec string
|
||||
// into individual buffer specs. Empty input yields an empty slice.
|
||||
// into individual buffer specs. Empty input yields an empty slice. The
|
||||
// size must be a plain decimal number over the whole field and the pattern
|
||||
// must be a known name or a valid hex blob, so typos fail here with the
|
||||
// offending spec in the message rather than silently allocating a zeroed
|
||||
// buffer.
|
||||
func ParseBufSpec(spec string) ([]BufSpec, error) {
|
||||
if spec == "" {
|
||||
return nil, nil
|
||||
@@ -31,15 +35,38 @@ func ParseBufSpec(spec string) ([]BufSpec, error) {
|
||||
if len(fields) != 3 {
|
||||
return nil, fmt.Errorf("verify: invalid buffer spec %q (expected name:size:pattern)", part)
|
||||
}
|
||||
var size int
|
||||
if _, err := fmt.Sscanf(fields[1], "%d", &size); err != nil || size <= 0 {
|
||||
// strconv.Atoi parses the whole field, unlike fmt.Sscanf which
|
||||
// accepts trailing garbage ("1024abc" parsed as 1024).
|
||||
size, err := strconv.Atoi(fields[1])
|
||||
if err != nil || size <= 0 {
|
||||
return nil, fmt.Errorf("verify: invalid buffer size %q in %q", fields[1], part)
|
||||
}
|
||||
if err := validPattern(fields[2]); err != nil {
|
||||
return nil, fmt.Errorf("verify: invalid pattern %q in %q: %v", fields[2], part, err)
|
||||
}
|
||||
out = append(out, BufSpec{Name: fields[0], Size: size, Pattern: fields[2]})
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// validPattern checks one buffer pattern: a known name, or a non-empty hex
|
||||
// blob. fillBuffer enforces the same rule again at fill time for specs
|
||||
// that were not built by ParseBufSpec.
|
||||
func validPattern(pattern string) error {
|
||||
switch pattern {
|
||||
case "zero", "ones", "seq":
|
||||
return nil
|
||||
}
|
||||
data, err := hex.DecodeString(pattern)
|
||||
if err != nil {
|
||||
return fmt.Errorf("not a known pattern (zero, ones, seq) and not hex: %w", err)
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return fmt.Errorf("not a known pattern (zero, ones, seq) and the hex blob is empty")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// allocatedBuf is one live buffer in a pool.
|
||||
type allocatedBuf struct {
|
||||
spec BufSpec
|
||||
@@ -60,11 +87,15 @@ type BufPool struct {
|
||||
}
|
||||
|
||||
// Alloc allocates and fills the buffers described by specs. The returned
|
||||
// pool must be kept alive until every call using it has returned.
|
||||
// pool must be kept alive until every call using it has returned. An
|
||||
// unknown pattern name or invalid hex blob is an error rather than a
|
||||
// silently zeroed buffer.
|
||||
func (p *BufPool) Alloc(specs []BufSpec) error {
|
||||
for _, s := range specs {
|
||||
data := make([]byte, s.Size+safetyMargin)
|
||||
fillBuffer(data, s.Pattern)
|
||||
if err := fillBuffer(data, s.Pattern); err != nil {
|
||||
return fmt.Errorf("verify: buffer %q: %w", s.Name, err)
|
||||
}
|
||||
p.bufs = append(p.bufs, allocatedBuf{spec: s, data: data})
|
||||
}
|
||||
return nil
|
||||
@@ -128,8 +159,10 @@ func (p *BufPool) matchBuf(name string) *allocatedBuf {
|
||||
}
|
||||
|
||||
// fillBuffer fills buf with the named pattern: "zero" (no-op, already zeroed),
|
||||
// "ones" (0xFF), "seq" (i mod 256), or a hex blob repeated to fill.
|
||||
func fillBuffer(buf []byte, pattern string) {
|
||||
// "ones" (0xFF), "seq" (i mod 256), or a hex blob repeated to fill. An
|
||||
// unknown pattern name or undecodable hex returns an error instead of
|
||||
// leaving the buffer silently zeroed.
|
||||
func fillBuffer(buf []byte, pattern string) error {
|
||||
switch pattern {
|
||||
case "zero":
|
||||
// Already zeroed by make.
|
||||
@@ -142,12 +175,18 @@ func fillBuffer(buf []byte, pattern string) {
|
||||
buf[i] = byte(i)
|
||||
}
|
||||
default:
|
||||
if data, err := hex.DecodeString(pattern); err == nil && len(data) > 0 {
|
||||
for i := range buf {
|
||||
buf[i] = data[i%len(data)]
|
||||
}
|
||||
data, err := hex.DecodeString(pattern)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unknown pattern (want zero, ones, seq or hex): %w", err)
|
||||
}
|
||||
if len(data) == 0 {
|
||||
return fmt.Errorf("unknown pattern (want zero, ones, seq or hex): empty hex blob")
|
||||
}
|
||||
for i := range buf {
|
||||
buf[i] = data[i%len(data)]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ApplyScalarArgs writes user-supplied scalar argument values into an ABI0
|
||||
|
||||
Reference in New Issue
Block a user