[RISCV] Fix decoding of invalid instruction with C extension enabled.
authorAna Pazos <apazos@codeaurora.org>
Thu, 13 Sep 2018 18:21:19 +0000 (18:21 +0000)
committerAna Pazos <apazos@codeaurora.org>
Thu, 13 Sep 2018 18:21:19 +0000 (18:21 +0000)
Summary:
The illegal instruction 0x00 0x00 is being wrongly decoded as
c.addi4spn with 0 immediate.

The invalid instruction 0x01 0x61 is being wrongly decoded as
c.addi16sp with 0 immediate.

This bug was uncovered by a LLVM MC Disassembler Protocol Buffer Fuzzer
for the RISC-V assembly language.

Reviewers: asb

Reviewed By: asb

Subscribers: rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, zzheng, edward-jones, mgrang, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, asb

Differential Revision: https://reviews.llvm.org/D51815

llvm-svn: 342159

llvm/lib/Target/RISCV/Disassembler/RISCVDisassembler.cpp
llvm/lib/Target/RISCV/RISCVInstrInfoC.td
llvm/test/MC/Disassembler/RISCV/invalid-instruction.txt [new file with mode: 0644]

index 69afa4b..d5b8b38 100644 (file)
@@ -212,6 +212,15 @@ static DecodeStatus decodeUImmOperand(MCInst &Inst, uint64_t Imm,
 }
 
 template <unsigned N>
+static DecodeStatus decodeUImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
+                                             int64_t Address,
+                                             const void *Decoder) {
+  if (Imm == 0)
+    return MCDisassembler::Fail;
+  return decodeUImmOperand<N>(Inst, Imm, Address, Decoder);
+}
+
+template <unsigned N>
 static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
                                       int64_t Address, const void *Decoder) {
   assert(isUInt<N>(Imm) && "Invalid immediate");
@@ -222,6 +231,15 @@ static DecodeStatus decodeSImmOperand(MCInst &Inst, uint64_t Imm,
 }
 
 template <unsigned N>
+static DecodeStatus decodeSImmNonZeroOperand(MCInst &Inst, uint64_t Imm,
+                                             int64_t Address,
+                                             const void *Decoder) {
+  if (Imm == 0)
+    return MCDisassembler::Fail;
+  return decodeSImmOperand<N>(Inst, Imm, Address, Decoder);
+}
+
+template <unsigned N>
 static DecodeStatus decodeSImmOperandAndLsl1(MCInst &Inst, uint64_t Imm,
                                              int64_t Address,
                                              const void *Decoder) {
index eae9441..c85a634 100644 (file)
@@ -167,7 +167,7 @@ def uimm10_lsb00nonzero : Operand<XLenVT>,
                           [{return isShiftedUInt<8, 2>(Imm) && (Imm != 0);}]> {
   let ParserMatchClass = UImmAsmOperand<10, "Lsb00NonZero">;
   let EncoderMethod = "getImmOpValue";
-  let DecoderMethod = "decodeUImmOperand<10>";
+  let DecoderMethod = "decodeUImmNonZeroOperand<10>";
   let MCOperandPredicate = [{
     int64_t Imm;
     if (!MCOp.evaluateAsConstantImm(Imm))
@@ -182,7 +182,7 @@ def simm10_lsb0000nonzero : Operand<XLenVT>,
                             [{return (Imm != 0) && isShiftedInt<6, 4>(Imm);}]> {
   let ParserMatchClass = SImmAsmOperand<10, "Lsb0000NonZero">;
   let EncoderMethod = "getImmOpValue";
-  let DecoderMethod = "decodeSImmOperand<10>";
+  let DecoderMethod = "decodeSImmNonZeroOperand<10>";
   let MCOperandPredicate = [{
     int64_t Imm;
     if (!MCOp.evaluateAsConstantImm(Imm))
diff --git a/llvm/test/MC/Disassembler/RISCV/invalid-instruction.txt b/llvm/test/MC/Disassembler/RISCV/invalid-instruction.txt
new file mode 100644 (file)
index 0000000..1bf033c
--- /dev/null
@@ -0,0 +1,13 @@
+# RUN: not llvm-mc -disassemble -triple=riscv32 -mattr=+c < %s 2>&1 | FileCheck %s
+# RUN: not llvm-mc -disassemble -triple=riscv64 -mattr=+c < %s 2>&1 | FileCheck %s
+#
+# Test generated by a LLVM MC Disassembler Protocol Buffer Fuzzer
+# for the RISC-V assembly language.
+
+# This should not decode as c.addi4spn with 0 imm when compression is enabled.
+[0x00 0x00]
+# CHECK: warning: invalid instruction encoding
+
+# This should not decode as c.addi16sp with 0 imm when compression is enabled.
+[0x01 0x61]
+# CHECK: warning: invalid instruction encoding