[llvm] f224425 - [BPF] Check jump and memory offsets to avoid truncation
Eduard Zingerman via llvm-commits
llvm-commits at lists.llvm.org
Sat Sep 23 09:52:58 PDT 2023
Author: Eduard Zingerman
Date: 2023-09-23T19:39:24+03:00
New Revision: f22442553b8e0840f2fb5345529172a345cfba7d
URL: https://github.com/llvm/llvm-project/commit/f22442553b8e0840f2fb5345529172a345cfba7d
DIFF: https://github.com/llvm/llvm-project/commit/f22442553b8e0840f2fb5345529172a345cfba7d.diff
LOG: [BPF] Check jump and memory offsets to avoid truncation
The following assembly code should issue two errors specifying that
both jump and load offsets are out of range:
if r1 > r2 goto +100500
r1 = *(u64 *)(r1 - 100500)
This commit updates BPFAsmParser to check that:
- offset specified for jump is either identifier (label) or a 16-bit
signed constant;
- offset specified for memory operations is a signed 16-bit constant.
(Which matches expectations in the BPFELFObjectWriter and
BPFMCCodeEmitter).
Differential Revision: https://reviews.llvm.org/D158425
Added:
llvm/test/MC/BPF/bad-offsets.s
llvm/test/MC/BPF/expr-offset.s
Modified:
llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
llvm/lib/Target/BPF/BPFInstrInfo.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index e92fc1a999104da..90697c6645be2f9 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -135,10 +135,14 @@ struct BPFOperand : public MCParsedAsmOperand {
return static_cast<const MCConstantExpr *>(Val)->getValue();
}
- bool isSImm12() const {
- return (isConstantImm() && isInt<12>(getConstantImm()));
+ bool isSImm16() const {
+ return (isConstantImm() && isInt<16>(getConstantImm()));
}
+ bool isSymbolRef() const { return isImm() && isa<MCSymbolRefExpr>(getImm()); }
+
+ bool isBrTarget() const { return isSymbolRef() || isSImm16(); }
+
/// getStartLoc - Gets location of the first token of this operand
SMLoc getStartLoc() const override { return StartLoc; }
/// getEndLoc - Gets location of the last token of this operand
@@ -332,6 +336,12 @@ bool BPFAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
}
return Error(ErrorLoc, "invalid operand for instruction");
+ case Match_InvalidBrTarget:
+ return Error(Operands[ErrorInfo]->getStartLoc(),
+ "operand is not an identifier or 16-bit signed integer");
+ case Match_InvalidSImm16:
+ return Error(Operands[ErrorInfo]->getStartLoc(),
+ "operand is not a 16-bit signed integer");
}
llvm_unreachable("Unknown match type detected!");
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index fd5a4dee295219e..305cbbd34d2707d 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -61,8 +61,17 @@ def BPFNoMovsx : Predicate<"!Subtarget->hasMovsx()">;
def BPFNoBswap : Predicate<"!Subtarget->hasBswap()">;
def BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">;
+class ImmediateAsmOperand<string name> : AsmOperandClass {
+ let Name = name;
+ let RenderMethod = "addImmOperands";
+ let DiagnosticType = !strconcat("Invalid", name);
+}
+
+def SImm16AsmOperand : ImmediateAsmOperand<"SImm16">;
+
def brtarget : Operand<OtherVT> {
let PrintMethod = "printBrTargetOperand";
+ let ParserMatchClass = ImmediateAsmOperand<"BrTarget">;
}
def calltarget : Operand<i64>;
@@ -70,6 +79,10 @@ def u64imm : Operand<i64> {
let PrintMethod = "printImm64Operand";
}
+def s16imm : Operand<i16> {
+ let ParserMatchClass = SImm16AsmOperand;
+}
+
def gpr_or_imm : Operand<i64>;
def i64immSExt32 : PatLeaf<(i64 imm),
@@ -92,7 +105,7 @@ def MEMri : Operand<i64> {
let PrintMethod = "printMemOperand";
let EncoderMethod = "getMemoryOpValue";
let DecoderMethod = "decodeMemoryOpValue";
- let MIOperandInfo = (ops GPR, i16imm);
+ let MIOperandInfo = (ops GPR, s16imm);
}
// Conditional code predicates - used for pattern matching for jump instructions
diff --git a/llvm/test/MC/BPF/bad-offsets.s b/llvm/test/MC/BPF/bad-offsets.s
new file mode 100644
index 000000000000000..cb5f87faa4cf9d4
--- /dev/null
+++ b/llvm/test/MC/BPF/bad-offsets.s
@@ -0,0 +1,33 @@
+# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \
+# RUN: | grep 'error: operand is not an identifier or 16-bit signed integer' \
+# RUN: | count 2
+# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \
+# RUN: | grep 'error: operand is not a 16-bit signed integer' \
+# RUN: | count 25
+ if r1 > r2 goto +70000
+ if r1 > r2 goto -70000
+ *(u64 *)(r1 + 70000) = 10
+ *(u32 *)(r1 - 70000) = 10
+ *(u16 *)(r1 - 70000) = 10
+ *(u8 *)(r1 - 70000) = 10
+ *(u64 *)(r1 + 70000) = r1
+ *(u32 *)(r1 - 70000) = r1
+ *(u16 *)(r1 - 70000) = r1
+ *(u8 *)(r1 - 70000) = r1
+ r1 = *(u64 *)(r1 + 70000)
+ r1 = *(u32 *)(r1 - 70000)
+ r1 = *(u16 *)(r1 - 70000)
+ r1 = *(u8 *)(r1 - 70000)
+ r1 = *(s32 *)(r1 + 70000)
+ r1 = *(s16 *)(r1 - 70000)
+ r1 = *(s8 *)(r1 - 70000)
+ lock *(u32*)(r1 + 70000) += w2
+ lock *(u32*)(r1 - 70000) &= w2
+ lock *(u32*)(r1 - 70000) |= w2
+ lock *(u32*)(r1 - 70000) ^= w2
+ r0 = atomic_fetch_add((u64 *)(r1 + 70000), r0)
+ r0 = atomic_fetch_and((u64 *)(r1 + 70000), r0)
+ r0 = atomic_fetch_xor((u64 *)(r1 + 70000), r0)
+ r0 = atomic_fetch_or((u64 *)(r1 + 70000), r0)
+ w0 = cmpxchg32_32(r1 + 70000, w0, w1)
+ r0 = cmpxchg_64(r1 + 70000, r0, r1)
diff --git a/llvm/test/MC/BPF/expr-offset.s b/llvm/test/MC/BPF/expr-offset.s
new file mode 100644
index 000000000000000..95575939c953b99
--- /dev/null
+++ b/llvm/test/MC/BPF/expr-offset.s
@@ -0,0 +1,12 @@
+# RUN: llvm-mc -triple bpfel -filetype=obj < %s \
+# RUN: | llvm-objdump --no-print-imm-hex --no-show-raw-insn -d - \
+# RUN: | FileCheck %s
+
+.equ foo, -1
+ if r1 > r2 goto foo + 2
+ exit
+ exit
+
+# CHECK: if r1 > r2 goto +1
+# CHECK: exit
+# CHECK: exit
More information about the llvm-commits
mailing list