From a992d950480be3aa7287fb2dade7b6e372ba371f Mon Sep 17 00:00:00 2001 From: Nguyen Anh Quynh <aquynh@gmail.com> Date: Mon, 30 May 2016 00:28:11 +0800 Subject: [PATCH] x86: report unsupported instructions in encodeInstruction(). this fixes c-crashes/crash-24-x64-not-is16bitmemoperand.c --- bindings/nodejs/consts/keystone.js | 1 + bindings/python/keystone/keystone_const.py | 1 + .../lib/keystone/keystone_const.rb | 1 + include/keystone/keystone.h | 1 + llvm/keystone/ks.cpp | 4 ++ .../X86/MCTargetDesc/X86MCCodeEmitter.cpp | 40 ++++++++++++++----- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/bindings/nodejs/consts/keystone.js b/bindings/nodejs/consts/keystone.js index 3bd3f55..3b9f940 100644 --- a/bindings/nodejs/consts/keystone.js +++ b/bindings/nodejs/consts/keystone.js @@ -70,6 +70,7 @@ module.exports.ERR_ASM_ESC_OCTAL = 153 module.exports.ERR_ASM_ESC_SEQUENCE = 154 module.exports.ERR_ASM_ESC_STR = 155 module.exports.ERR_ASM_TOKEN_INVALID = 156 +module.exports.ERR_ASM_INSN_UNSUPPORTED = 157 module.exports.ERR_ASM_INVALIDOPERAND = 512 module.exports.ERR_ASM_MISSINGFEATURE = 513 module.exports.ERR_ASM_MNEMONICFAIL = 514 diff --git a/bindings/python/keystone/keystone_const.py b/bindings/python/keystone/keystone_const.py index a737859..82d04a6 100644 --- a/bindings/python/keystone/keystone_const.py +++ b/bindings/python/keystone/keystone_const.py @@ -70,6 +70,7 @@ KS_ERR_ASM_ESC_OCTAL = 153 KS_ERR_ASM_ESC_SEQUENCE = 154 KS_ERR_ASM_ESC_STR = 155 KS_ERR_ASM_TOKEN_INVALID = 156 +KS_ERR_ASM_INSN_UNSUPPORTED = 157 KS_ERR_ASM_INVALIDOPERAND = 512 KS_ERR_ASM_MISSINGFEATURE = 513 KS_ERR_ASM_MNEMONICFAIL = 514 diff --git a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb index 1d45192..19ebc85 100644 --- a/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb +++ b/bindings/ruby/keystone_gem/lib/keystone/keystone_const.rb @@ -72,6 +72,7 @@ module Keystone KS_ERR_ASM_ESC_SEQUENCE = 154 KS_ERR_ASM_ESC_STR = 155 KS_ERR_ASM_TOKEN_INVALID = 156 + KS_ERR_ASM_INSN_UNSUPPORTED = 157 KS_ERR_ASM_INVALIDOPERAND = 512 KS_ERR_ASM_MISSINGFEATURE = 513 KS_ERR_ASM_MNEMONICFAIL = 514 diff --git a/include/keystone/keystone.h b/include/keystone/keystone.h index f9e5aff..1e4f085 100644 --- a/include/keystone/keystone.h +++ b/include/keystone/keystone.h @@ -126,6 +126,7 @@ typedef enum ks_err { KS_ERR_ASM_ESC_SEQUENCE, // invalid escape sequence (unrecognized character) KS_ERR_ASM_ESC_STR, // broken escape string KS_ERR_ASM_TOKEN_INVALID, // invalid token + KS_ERR_ASM_INSN_UNSUPPORTED, // this instruction is unsupported in this mode // generic input assembly errors - architecture specific KS_ERR_ASM_INVALIDOPERAND = KS_ERR_ASM_ARCH, diff --git a/llvm/keystone/ks.cpp b/llvm/keystone/ks.cpp index 35c7527..b0209a7 100644 --- a/llvm/keystone/ks.cpp +++ b/llvm/keystone/ks.cpp @@ -124,6 +124,10 @@ const char *ks_strerror(ks_err code) return "Invalid escape string (KS_ERR_ASM_ESC_STR)"; case KS_ERR_ASM_TOKEN_INVALID: // invalid token from input assembly return "Invalid input token (KS_ERR_ASM_TOKEN_INVALID)"; + case KS_ERR_ASM_INSN_UNSUPPORTED: + return "Instruction is unsupported in this mode (KS_ERR_ASM_INSN_UNSUPPORTED)"; + case KS_ERR_ASM_DIRECTIVE_UNKNOWN: + return "Unknown directive (KS_ERR_ASM_DIRECTIVE_UNKNOWN)"; } } diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp index 0be48c3..2309c8a 100644 --- a/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp +++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp @@ -1290,14 +1290,26 @@ encodeInstruction(MCInst &MI, raw_ostream &OS, } else if (MemoryOperand < 0) { need_address_override = false; } else if (is64BitMode(STI)) { - assert(!Is16BitMemOperand(MI, MemoryOperand, STI)); + //assert(!Is16BitMemOperand(MI, MemoryOperand, STI)); + if (Is16BitMemOperand(MI, MemoryOperand, STI)) { + KsError = KS_ERR_ASM_INSN_UNSUPPORTED; + return; + } need_address_override = Is32BitMemOperand(MI, MemoryOperand); } else if (is32BitMode(STI)) { - assert(!Is64BitMemOperand(MI, MemoryOperand)); + //assert(!Is64BitMemOperand(MI, MemoryOperand)); + if (Is64BitMemOperand(MI, MemoryOperand)) { + KsError = KS_ERR_ASM_INSN_UNSUPPORTED; + return; + } need_address_override = Is16BitMemOperand(MI, MemoryOperand, STI); } else { - assert(is16BitMode(STI)); - assert(!Is64BitMemOperand(MI, MemoryOperand)); + //assert(is16BitMode(STI)); + //assert(!Is64BitMemOperand(MI, MemoryOperand)); + if (!is16BitMode(STI) || Is64BitMemOperand(MI, MemoryOperand)) { + KsError = KS_ERR_ASM_INSN_UNSUPPORTED; + return; + } need_address_override = !Is16BitMemOperand(MI, MemoryOperand, STI); } @@ -1323,10 +1335,16 @@ encodeInstruction(MCInst &MI, raw_ostream &OS, case X86II::RawFrmDstSrc: { //printf(">> aa\n"); unsigned siReg = MI.getOperand(1).getReg(); - assert(((siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) || - (siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) || - (siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) && - "SI and DI register sizes do not match"); + //assert(((siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) || + // (siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) || + // (siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) && + // "SI and DI register sizes do not match"); + if (!(siReg == X86::SI && MI.getOperand(0).getReg() == X86::DI) && + !(siReg == X86::ESI && MI.getOperand(0).getReg() == X86::EDI) && + !(siReg == X86::RSI && MI.getOperand(0).getReg() == X86::RDI)) { + KsError = KS_ERR_ASM_INSN_UNSUPPORTED; + return; + } // Emit segment override opcode prefix as needed (not for %ds). if (MI.getOperand(2).getReg() != X86::DS) EmitSegmentOverridePrefix(CurByte, 2, MI, OS); @@ -1572,7 +1590,11 @@ encodeInstruction(MCInst &MI, raw_ostream &OS, const MCOperand &MIMM = MI.getOperand(CurOp++); if (MIMM.isImm()) { unsigned Val = MIMM.getImm(); - assert(Val < 16 && "Immediate operand value out of range"); + // assert(Val < 16 && "Immediate operand value out of range"); + if (Val >= 16) { + KsError = KS_ERR_ASM_INSN_UNSUPPORTED; + return; + } RegNum |= Val; } } -- GitLab