fix(verify): isolate smoke and abi sweeps in a child process
Assisted-by: GLM 5.3
This commit is contained in:
@@ -7,8 +7,11 @@ import (
|
||||
"bytes"
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -237,3 +240,55 @@ func TestCmdArgErrors(t *testing.T) {
|
||||
t.Errorf("cmdParse() code = %d, want 2", code)
|
||||
}
|
||||
}
|
||||
|
||||
// TestVerifySmokeCrashIsolation checks that a function faulting on its
|
||||
// zeroed smoke arguments is reported as CRASH by a child process instead of
|
||||
// killing `gasm verify` itself.
|
||||
func TestVerifySmokeCrashIsolation(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("builds the gasm binary")
|
||||
}
|
||||
if runtime.GOARCH != "amd64" {
|
||||
t.Skip("amd64 JIT only")
|
||||
}
|
||||
bin := filepath.Join(t.TempDir(), "gasm")
|
||||
if out, err := exec.Command("go", "build", "-o", bin, ".").CombinedOutput(); err != nil {
|
||||
t.Fatalf("build gasm: %v\n%s", err, out)
|
||||
}
|
||||
src := filepath.Join(t.TempDir(), "crash_amd64.s")
|
||||
kernel := "#include \"textflag.h\"\n" +
|
||||
"\n" +
|
||||
"// func Fault(x []byte) int\n" +
|
||||
"TEXT ·Fault(SB), NOSPLIT, $0-32\n" +
|
||||
"\tMOVQ\tx+0(FP), AX\n" +
|
||||
"\tMOVQ\t(AX), AX // faults on the zeroed nil pointer\n" +
|
||||
"\tMOVQ\tAX, ret+24(FP)\n" +
|
||||
"\tRET\n"
|
||||
if err := os.WriteFile(src, []byte(kernel), 0o644); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cmd := exec.Command(bin, "verify", "-smoke", src)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err == nil {
|
||||
t.Fatalf("expected a failure report, got success:\n%s", out)
|
||||
}
|
||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||
if ws, ok := exitErr.Sys().(syscall.WaitStatus); ok && ws.Signaled() {
|
||||
t.Fatalf("verify died from %v — the crash was not isolated:\n%s", ws.Signal(), out)
|
||||
}
|
||||
}
|
||||
if !strings.Contains(string(out), "CRASH") {
|
||||
t.Errorf("output does not report CRASH:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSweepCheckLines(t *testing.T) {
|
||||
out := []byte("crash_amd64.s: 1 functions JIT-loaded\n" +
|
||||
" Fault: 21 bytes, args=32, frame=0 NOSPLIT\n" +
|
||||
" smoke: OK\n" +
|
||||
" abi: clean (10 varied inputs)\n")
|
||||
want := " smoke: OK\n abi: clean (10 varied inputs)"
|
||||
if got := sweepCheckLines(out); got != want {
|
||||
t.Errorf("sweepCheckLines = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user