From f2a4cb0a0edc95ae74816275e82b4ade71c6f37a Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Mon, 16 May 2016 05:10:21 +0200 Subject: [PATCH] x86-asm: Reject some invalid arith imm8 instruction There were two errors in the arithmetic imm8 instruction. They accept only REGW, and in case the user write a xxxb opcode that variant needs to be rejected as well (it's not automatically rejected by REGW in case the destination is memory). --- i386-asm.c | 7 +++++++ i386-asm.h | 2 +- tests/asmtest.S | 16 ++++++++++++++++ x86_64-asm.h | 2 +- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/i386-asm.c b/i386-asm.c index 8baad47f..b25bd428 100644 --- a/i386-asm.c +++ b/i386-asm.c @@ -552,7 +552,14 @@ ST_FUNC void asm_opcode(TCCState *s1, int opcode) continue; s = (opcode - pa->sym) % NBWLX; if ((pa->instr_type & OPC_BWLX) == OPC_WLX) + { + /* We need to reject the xxxb opcodes that we accepted above. + Note that pa->sym for WLX opcodes is the 'w' token, + to get the 'b' token subtract one. */ + if (((opcode - pa->sym + 1) % NBWLX) == 0) + continue; s++; + } } else if (pa->instr_type & OPC_SHIFT) { if (!(opcode >= pa->sym && opcode < pa->sym + 7*NBWLX)) continue; diff --git a/i386-asm.h b/i386-asm.h index ae7d8999..5b81c111 100644 --- a/i386-asm.h +++ b/i386-asm.h @@ -157,7 +157,7 @@ ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32)) ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX)) -ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REG)) +ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW)) ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) diff --git a/tests/asmtest.S b/tests/asmtest.S index a2211267..fd0629cc 100644 --- a/tests/asmtest.S +++ b/tests/asmtest.S @@ -158,6 +158,22 @@ addl $0x123, %eax add $0x123, %ebx add $-16, %ecx add $-0x123, %esi +add $1, %bx +add $1, %ebx +add $-1, %bx +add $-1, %ebx +add $127, %bx +addl $127, %ebx +addl $-128, %ebx +addl $-128, %ebx +addl $-129, %ebx +addl $128, %ebx +addl $255, %ebx +addl $256, %ebx +andb $0xf, %ah +andb $-15, %cl +xorb $127, %dh +cmpb $42, (%eax) addl $0x123, 0x100 addl $0x123, 0x100(%ebx) addl $0x123, 0x100(%ebx,%edx,2) diff --git a/x86_64-asm.h b/x86_64-asm.h index c6c74e7b..71e7c1ab 100644 --- a/x86_64-asm.h +++ b/x86_64-asm.h @@ -166,7 +166,7 @@ ALT(DEF_ASM_OP2(lgs, 0x0fb5, 0, OPC_MODRM, OPT_EA, OPT_REG32)) ALT(DEF_ASM_OP2(addb, 0x00, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG)) /* XXX: use D bit ? */ ALT(DEF_ASM_OP2(addb, 0x02, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_EA | OPT_REG, OPT_REG)) ALT(DEF_ASM_OP2(addb, 0x04, 0, OPC_ARITH | OPC_BWLX, OPT_IM, OPT_EAX)) -ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REG)) +ALT(DEF_ASM_OP2(addw, 0x83, 0, OPC_ARITH | OPC_MODRM | OPC_WLX, OPT_IM8S, OPT_EA | OPT_REGW)) ALT(DEF_ASM_OP2(addb, 0x80, 0, OPC_ARITH | OPC_MODRM | OPC_BWLX, OPT_IM, OPT_EA | OPT_REG)) ALT(DEF_ASM_OP2(testb, 0x84, 0, OPC_MODRM | OPC_BWLX, OPT_REG, OPT_EA | OPT_REG))