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
+34 -10
View File
@@ -210,17 +210,39 @@ func (p *state) parseText(line []token.Token) {
rest = rest[1:]
}
// Frame: $number ; optional args: -number. Whatever remains after the
// header is the body and is parsed by the caller.
// Frame: $[-]number ; optional args: -number. The Go runtime writes
// zero frames with an explicit sign ("$-0-24"), so the number may carry
// one. Whatever remains after the header is the body and is parsed by
// the caller.
if len(rest) > 0 && rest[0].Kind == token.Dollar {
text.Frame = parseOperand(rest[:2]) // "$" "number"
if len(rest) >= 4 && rest[2].Kind == token.Minus && rest[3].Kind == token.Number {
text.Args = &ast.Operand{
Kind: ast.OpImmediate,
Imm: ast.Immediate{Val: parseInt(rest[3].Text), HasVal: true},
Raw: "-" + rest[3].Text,
Pos: rest[2].Pos,
n := 1
neg := false
if n < len(rest) && (rest[n].Kind == token.Minus || rest[n].Kind == token.Plus) {
neg = rest[n].Kind == token.Minus
n++
}
if n < len(rest) && rest[n].Kind == token.Number {
val := parseInt(rest[n].Text)
if neg {
val = -val
}
text.Frame = &ast.Operand{
Kind: ast.OpImmediate,
Imm: ast.Immediate{Val: val, HasVal: true},
Raw: joinRaw(rest[:n+1]),
Pos: rest[0].Pos,
}
// The argument area: a minus sign followed by a number.
if n+2 < len(rest) && rest[n+1].Kind == token.Minus && rest[n+2].Kind == token.Number {
text.Args = &ast.Operand{
Kind: ast.OpImmediate,
Imm: ast.Immediate{Val: parseInt(rest[n+2].Text), HasVal: true},
Raw: "-" + rest[n+2].Text,
Pos: rest[n+1].Pos,
}
}
} else {
p.errorf(rest[0].Pos, "TEXT frame size must be a number after $")
}
}
@@ -234,8 +256,10 @@ func (p *state) parseGlobl(line []token.Token) *ast.Globl {
sym, n := parseSymbolPrefix(rest)
g.Name = sym
rest = skipComma(rest[n:])
// Flags are identifiers (RODATA, DUPOK) or legacy numeric constants
// (2, 8, 9, 10) from runtime/textflag.h.
for len(rest) > 0 && rest[0].Kind != token.Dollar {
if rest[0].Kind == token.Ident {
if rest[0].Kind == token.Ident || rest[0].Kind == token.Number {
g.Flags = append(g.Flags, rest[0].Text)
}
rest = rest[1:]