mirror of
git://repo.or.cz/tinycc.git
synced 2026-06-20 11:54:18 +08:00
arm64-asm.c: validate operand types before encoding
Multiple instruction handlers were extracting op->reg without checking that the operand was actually a register. When parse_operand() failed to recognize a token, it set op->reg = -1, which when masked with 0x1F became 31 (xzr/sp), silently encoding wrong instructions. Now each handler validates operand types before extraction: - asm_shift: validates op1 and op2 are registers - asm_data_proc: validates op1, op2, and op3 are registers - asm_ldst: validates op1 is register, op2 is address - asm_ldst_pair: validates op1 and op2 are registers, op3 is address This implements fail-fast behavior to catch typos and invalid operands immediately rather than producing silently incorrect code.
This commit is contained in:
parent
a1bf1d187d
commit
5497f87f59
41
arm64-asm.c
41
arm64-asm.c
@ -692,6 +692,16 @@ static void asm_shift(TCCState *s1, int token)
|
||||
parse_operand(s1, &op1);
|
||||
if (tok == ',') next();
|
||||
parse_operand(s1, &op2);
|
||||
|
||||
if (!(op1.type & OP_REG)) {
|
||||
tcc_error("expected register in first operand");
|
||||
return;
|
||||
}
|
||||
if (!(op2.type & OP_REG)) {
|
||||
tcc_error("expected register in second operand");
|
||||
return;
|
||||
}
|
||||
|
||||
rd = op1.reg;
|
||||
rn = op2.reg;
|
||||
|
||||
@ -872,6 +882,16 @@ static void asm_data_proc(TCCState *s1, int token)
|
||||
parse_operand(s1, &op1);
|
||||
if (tok == ',') next();
|
||||
parse_operand(s1, &op2);
|
||||
|
||||
if (!(op1.type & OP_REG)) {
|
||||
tcc_error("expected register in first operand");
|
||||
return;
|
||||
}
|
||||
if (!(op2.type & OP_REG)) {
|
||||
tcc_error("expected register in second operand");
|
||||
return;
|
||||
}
|
||||
|
||||
rd = op1.reg;
|
||||
rn = op2.reg;
|
||||
|
||||
@ -889,6 +909,10 @@ static void asm_data_proc(TCCState *s1, int token)
|
||||
else
|
||||
tcc_error("immediate operand not valid for this instruction");
|
||||
} else {
|
||||
if (!(op3.type & OP_REG)) {
|
||||
tcc_error("expected register in third operand");
|
||||
return;
|
||||
}
|
||||
rm = op3.reg;
|
||||
is_64bit = (op1.reg_type & REG_X);
|
||||
if (is_64bit != !!(op2.reg_type & REG_X) || is_64bit != !!(op3.reg_type & REG_X))
|
||||
@ -916,6 +940,15 @@ static void asm_ldst(TCCState *s1, int token)
|
||||
if (tok == ',') next();
|
||||
parse_operand(s1, &op2);
|
||||
|
||||
if (!(op1.type & OP_REG)) {
|
||||
tcc_error("expected register in first operand");
|
||||
return;
|
||||
}
|
||||
if (op2.type != OP_ADDR) {
|
||||
tcc_error("expected address operand in second operand");
|
||||
return;
|
||||
}
|
||||
|
||||
rt = op1.reg;
|
||||
rn = op2.reg;
|
||||
offset = op2.e.v;
|
||||
@ -991,6 +1024,14 @@ static void asm_ldst_pair(TCCState *s1, int token)
|
||||
next();
|
||||
parse_operand(s1, &op3);
|
||||
|
||||
if (!(op1.type & OP_REG)) {
|
||||
tcc_error("expected register in first operand");
|
||||
return;
|
||||
}
|
||||
if (!(op2.type & OP_REG)) {
|
||||
tcc_error("expected register in second operand");
|
||||
return;
|
||||
}
|
||||
if (!(op3.type & OP_ADDR))
|
||||
tcc_error("pair load/store requires an address operand");
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user