summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCyrill Gorcunov <gorcunov@gmail.com>2014-12-14 22:44:54 +0300
committerCyrill Gorcunov <gorcunov@gmail.com>2014-12-14 22:44:54 +0300
commit9b05974022da69c12b8b190c6ad100402771e5ad (patch)
treef9f6fa0a0f853c4d6bd138e18c940b76c326dd1a
parent1cccb1e8d5618f054b509b6eaf9e1cee13985bc7 (diff)
downloadnasm-9b05974022da69c12b8b190c6ad100402771e5ad.tar.gz
ndisasm: Prevent nil dereference on registerd decoding
The sequence | 0x0F 0x1B 0x75 | get matched into one of BNDx instruction which register value 6 which is of course out of possible BND registers implemented in hardware at the moment leading to nil dereference. Instead lets use a macro in whichreg() helper which would test the registers bounds and force the caller to try another template if register is out of range. In the case above it simply means ndisasm instead of crashing outputs | 00000000 0F db 0x0f | 00000001 1B db 0x1b | 00000002 75 db 0x75 http://bugzilla.nasm.us/show_bug.cgi?id=3392289 Reported-by: Hanno Boeck <hanno@hboeck.de> Signed-off-by: Cyrill Gorcunov <gorcunov@gmail.com>
-rw-r--r--disasm.c36
1 files changed, 20 insertions, 16 deletions
diff --git a/disasm.c b/disasm.c
index 8ee0b1c3..161868d0 100644
--- a/disasm.c
+++ b/disasm.c
@@ -158,44 +158,48 @@ static enum reg_enum whichreg(opflags_t regflags, int regval, int rex)
if (regval < 0 || regval > (rex & REX_EV ? 31 : 15))
return 0;
+#define GET_REGISTER(__array, __index) \
+ ((__index) < ARRAY_SIZE(__array) ? __array[(__index)] : 0)
+
if (!(REG8 & ~regflags)) {
if (rex & (REX_P|REX_NH))
- return nasm_rd_reg8_rex[regval];
+ return GET_REGISTER(nasm_rd_reg8_rex, regval);
else
- return nasm_rd_reg8[regval];
+ return GET_REGISTER(nasm_rd_reg8, regval);
}
if (!(REG16 & ~regflags))
- return nasm_rd_reg16[regval];
+ return GET_REGISTER(nasm_rd_reg16, regval);
if (!(REG32 & ~regflags))
- return nasm_rd_reg32[regval];
+ return GET_REGISTER(nasm_rd_reg32, regval);
if (!(REG64 & ~regflags))
- return nasm_rd_reg64[regval];
+ return GET_REGISTER(nasm_rd_reg64, regval);
if (!(REG_SREG & ~regflags))
- return nasm_rd_sreg[regval & 7]; /* Ignore REX */
+ return GET_REGISTER(nasm_rd_sreg, regval & 7); /* Ignore REX */
if (!(REG_CREG & ~regflags))
- return nasm_rd_creg[regval];
+ return GET_REGISTER(nasm_rd_creg, regval);
if (!(REG_DREG & ~regflags))
- return nasm_rd_dreg[regval];
+ return GET_REGISTER(nasm_rd_dreg, regval);
if (!(REG_TREG & ~regflags)) {
if (regval > 7)
return 0; /* TR registers are ill-defined with rex */
- return nasm_rd_treg[regval];
+ return GET_REGISTER(nasm_rd_treg, regval);
}
if (!(FPUREG & ~regflags))
- return nasm_rd_fpureg[regval & 7]; /* Ignore REX */
+ return GET_REGISTER(nasm_rd_fpureg, regval & 7); /* Ignore REX */
if (!(MMXREG & ~regflags))
- return nasm_rd_mmxreg[regval & 7]; /* Ignore REX */
+ return GET_REGISTER(nasm_rd_mmxreg, regval & 7); /* Ignore REX */
if (!(XMMREG & ~regflags))
- return nasm_rd_xmmreg[regval];
+ return GET_REGISTER(nasm_rd_xmmreg, regval);
if (!(YMMREG & ~regflags))
- return nasm_rd_ymmreg[regval];
+ return GET_REGISTER(nasm_rd_ymmreg, regval);
if (!(ZMMREG & ~regflags))
- return nasm_rd_zmmreg[regval];
+ return GET_REGISTER(nasm_rd_zmmreg, regval);
if (!(OPMASKREG & ~regflags))
- return nasm_rd_opmaskreg[regval];
+ return GET_REGISTER(nasm_rd_opmaskreg, regval);
if (!(BNDREG & ~regflags))
- return nasm_rd_bndreg[regval];
+ return GET_REGISTER(nasm_rd_bndreg, regval);
+#undef GET_REGISTER
return 0;
}