fix(verify): arm64 stack save, adaptive canary and host gating
Assisted-by: GLM 5.3
This commit is contained in:
+17
-4
@@ -5,7 +5,6 @@ package verify
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"runtime"
|
||||
|
||||
@@ -101,6 +100,9 @@ func (k *Kernel) FuncNames() []string {
|
||||
// The arg block is the raw bytes of the function's argument/result area
|
||||
// (as declared by the TEXT $frame-args suffix). Returns the arg block
|
||||
// after the call (with any results written back by the function).
|
||||
//
|
||||
// Not safe for concurrent use: only one JIT call may be in flight at a
|
||||
// time, the trampolines keep the saved registers in package globals.
|
||||
func (k *Kernel) CallFunc(name string, args []byte) ([]byte, error) {
|
||||
idx, ok := k.funcs[name]
|
||||
if !ok {
|
||||
@@ -116,7 +118,12 @@ func (k *Kernel) CallFunc(name string, args []byte) ([]byte, error) {
|
||||
|
||||
// CallFuncChecked invokes the named function with ABI sentinels and a
|
||||
// red-zone canary, returning the argument block and an ABIReport that
|
||||
// records any callee-saved register or red-zone violations.
|
||||
// records any callee-saved register or red-zone violations. The canary
|
||||
// gap is sized from the function's declared frame, so legal frame writes
|
||||
// do not count as violations.
|
||||
//
|
||||
// Not safe for concurrent use: only one JIT call may be in flight at a
|
||||
// time, the trampolines keep the saved registers in package globals.
|
||||
func (k *Kernel) CallFuncChecked(name string, args []byte) ([]byte, ABIReport, error) {
|
||||
idx, ok := k.funcs[name]
|
||||
if !ok {
|
||||
@@ -127,11 +134,14 @@ func (k *Kernel) CallFuncChecked(name string, args []byte) ([]byte, ABIReport, e
|
||||
return nil, ABIReport{}, fmt.Errorf("verify: %s: arg block too small: got %d, need %d", name, len(args), fl.Args)
|
||||
}
|
||||
fnAddr := k.exec.FuncAddr(fl.Offset)
|
||||
return CallChecked(fnAddr, args)
|
||||
return CallCheckedFrame(fnAddr, args, fl.Frame)
|
||||
}
|
||||
|
||||
// FuzzFuncCheckedByName is like FuzzFuncChecked but extracts the signature
|
||||
// from the source code internally.
|
||||
//
|
||||
// Not safe for concurrent use: only one JIT call may be in flight at a
|
||||
// time, the trampolines keep the saved registers in package globals.
|
||||
func (k *Kernel) FuzzFuncCheckedByName(name, src string, iterations int, seed int64) FuzzResult {
|
||||
result := FuzzResult{Func: name, Iterations: iterations}
|
||||
sig, ok := ExtractSignatures(src)[name]
|
||||
@@ -146,9 +156,12 @@ func (k *Kernel) FuzzFuncCheckedByName(name, src string, iterations int, seed in
|
||||
// FuzzFuncChecked combines fuzzing with ABI checks: it generates varied
|
||||
// inputs and verifies that callee-saved registers and the red zone are
|
||||
// preserved even on deep execution paths (not just early exits).
|
||||
//
|
||||
// Not safe for concurrent use: only one JIT call may be in flight at a
|
||||
// time, the trampolines keep the saved registers in package globals.
|
||||
func (k *Kernel) FuzzFuncChecked(name string, sig funcSig, iterations int, seed int64) FuzzResult {
|
||||
result := FuzzResult{Func: name, Iterations: iterations}
|
||||
rng := rand.New(rand.NewSource(seed))
|
||||
rng := newRNG(seed)
|
||||
|
||||
fl, err := k.Func(name)
|
||||
if err != nil {
|
||||
|
||||
Reference in New Issue
Block a user