fix(parser): reject malformed TEXT frames and parse signed frame sizes

This commit is contained in:
2026-09-14 18:22:00 +02:00
parent 22226d59a5
commit f5fc22d390
2 changed files with 97 additions and 10 deletions
+63
View File
@@ -253,3 +253,66 @@ func TestDataWidthAndStatic(t *testing.T) {
t.Errorf("mask24 DATA should be static, got %+v", datas[2].Name)
}
}
// TestTruncatedFrameDollar is a regression test for a TEXT directive whose
// frame size is missing after the $: the parser used to slice past the end
// of the token slice and panic. It must report a diagnostic instead.
func TestTruncatedFrameDollar(t *testing.T) {
for _, src := range []string{
"TEXT $\n",
"TEXT \u00b7foo(SB), $\n",
"TEXT \u00b7foo(SB), NOSPLIT, $\n",
} {
var file *ast.File
func() {
defer func() {
if r := recover(); r != nil {
t.Fatalf("Parse(%q) panicked: %v", src, r)
}
}()
file, _ = Parse("t.s", src)
}()
if file == nil {
t.Fatalf("Parse(%q) returned no file", src)
}
if len(file.Decls) != 1 {
t.Fatalf("Parse(%q) decls = %d, want 1", src, len(file.Decls))
}
txt := file.Decls[0].(*ast.Text)
if txt.Frame != nil {
t.Errorf("Parse(%q) frame = %v, want nil", src, txt.Frame)
}
}
}
// TestFrameAndArgs parses a well-formed TEXT header and checks that the
// frame and args operands are picked up.
func TestFrameAndArgs(t *testing.T) {
file, errs := Parse("t.s", "TEXT \u00b7foo(SB), $32-16\n\tRET\n")
if len(errs) > 0 {
t.Fatalf("parse errors: %v", errs)
}
txt := file.Decls[0].(*ast.Text)
if txt.Frame == nil || !txt.Frame.Imm.HasVal || txt.Frame.Imm.Val != 32 {
t.Errorf("frame = %+v, want $32", txt.Frame)
}
if txt.Args == nil || !txt.Args.Imm.HasVal || txt.Args.Imm.Val != 16 {
t.Errorf("args = %+v, want -16", txt.Args)
}
}
// TestSignedZeroFrame covers the Go runtime's "$-0-24" spelling: a zero
// frame with an explicit sign plus the argument area.
func TestSignedZeroFrame(t *testing.T) {
file, errs := Parse("t.s", "TEXT \u00b7foo<ABIInternal>(SB), NOSPLIT, $-0-24\n\tRET\n")
if len(errs) > 0 {
t.Fatalf("parse errors: %v", errs)
}
txt := file.Decls[0].(*ast.Text)
if txt.Frame == nil || !txt.Frame.Imm.HasVal || txt.Frame.Imm.Val != 0 {
t.Errorf("frame = %+v, want $-0", txt.Frame)
}
if txt.Args == nil || !txt.Args.Imm.HasVal || txt.Args.Imm.Val != 24 {
t.Errorf("args = %+v, want -24", txt.Args)
}
}