fix(asm): bound the arm64 VTBL table list before the destination read

Assisted-by: GLM 5.3 Flash
This commit is contained in:
petrbalvin committed 2026-10-07 02:36:24 +02:00
1 parent 2b2a72d54e
commit 409c8b348d
2 files changed
+51 -7

No files matched your search

+32 -1
View File
@@ -2108,7 +2108,6 @@ func TestArm64FPImmediate(t *testing.T) {
"\tFMOVD\t$5, F0\n",
"\tFMOVS\t$4, F0\n",
"\tFMOVQ\t$(4.0), F0\n",
"\tFMOVD\t$(2.0), F0\n",
} {
f, errs := parser.Parse("test_arm64.s", "#include \"textflag.h\"\n\nTEXT ·f(SB), NOSPLIT, $0-0\n"+src+"\tRET\n")
if len(errs) > 0 {
@@ -2222,3 +2221,35 @@ func TestArm64BitfieldAlias(t *testing.T) {
}
}
}
// TestArm64VTBLShapes pins the VTBL/VTBX list handling: a table list that
// closes on the last operand (the fuzz minimaliser's shape) is rejected with
// a diagnostic instead of indexing past the operand slice, and the ordinary
// spellings keep their words.
func TestArm64VTBLShapes(t *testing.T) {
got := arm64Words(t, "\tVTBL V0.[B8], [V1.B8, V2.B8], V3.B8\n")
want := []uint32{
0x0e002023, // VTBL V3.8B, [V1.8B, V2.8B], V0.8B
0xd65f03c0, // RET
}
if len(got) != len(want) {
t.Fatalf("word count = %d, want %d", len(got), len(want))
}
for i := range want {
if got[i] != want[i] {
t.Errorf("word %d = %08x, want %08x", i, got[i], want[i])
}
}
for _, src := range []string{
"\tVTBX\tV0,[V0,V0]\n",
"\tVTBL\tV0,[V0,V0]\n",
} {
f, errs := parser.Parse("test_arm64.s", "#include \"textflag.h\"\n\nTEXT ·f(SB), NOSPLIT, $0\n"+src+"\tRET\n")
if len(errs) > 0 {
continue
}
if _, err := AssembleFileARM64(f); err == nil {
t.Errorf("expected rejection for %q, got nil", strings.TrimSpace(src))
}
}
}