From 15ed7ec5aab8de283b2cfc9b674b5382024c1da1 Mon Sep 17 00:00:00 2001 From: Prakhar Bahuguna Date: Tue, 16 Aug 2016 10:41:52 +0000 Subject: [Thumb] Validate branch target for CBZ/CBNZ instructions. Summary: The assembler currently does not check the branch target for CBZ/CBNZ instructions, which only permit branching forwards with a positive offset. This adds validation for the branch target to ensure negative PC-relative offsets are not encoded into the instruction, whether specified as a literal or as an assembler symbol. Reviewers: rengolin, t.p.northover Subscribers: llvm-commits, rengolin Differential Revision: https://reviews.llvm.org/D23312 llvm-svn: 278788 --- llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 6 ++++++ llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp | 5 +++++ 2 files changed, 11 insertions(+) (limited to 'llvm/lib/Target') diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index b9b665fc1ea..c011c792bff 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6684,6 +6684,12 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, return Error(Operands[Op]->getStartLoc(), "branch target out of range"); break; } + case ARM::tCBZ: + case ARM::tCBNZ: { + if (!static_cast(*Operands[2]).isUnsignedOffset<6, 1>()) + return Error(Operands[2]->getStartLoc(), "branch target out of range"); + break; + } case ARM::MOVi16: case ARM::t2MOVi16: case ARM::t2MOVTi16: diff --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp index 26f96ab77fe..5ac2d65a89e 100644 --- a/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp +++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMAsmBackend.cpp @@ -578,6 +578,11 @@ unsigned ARMAsmBackend::adjustFixupValue(const MCFixup &Fixup, uint64_t Value, // Offset by 4, and don't encode the low two bits. return ((Value - 4) >> 2) & 0xff; case ARM::fixup_arm_thumb_cb: { + // CB instructions can only branch to offsets in [0, 126] in multiples of 2 + if (Ctx && ((int64_t)Value < 0 || Value > 0x3e || Value & 1)) { + Ctx->reportError(Fixup.getLoc(), "out of range pc-relative fixup value"); + return 0; + } // Offset by 4 and don't encode the lower bit, which is always 0. // FIXME: diagnose if no Thumb2 uint32_t Binary = (Value - 4) >> 1; -- cgit v1.2.3