https://github.com/ABWI-Y created https://github.com/llvm/llvm-project/pull/213536
This fixes issue #213415. If a user writes something like '1 / 0' or '1 % 0' in assembly, the compiler will now show a normal error message instead of crashing completely. Fixes #213415 >From 734b25526b4a45077dc4d0d344520c75ff3853c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=99=88=E7=BA=AA=E5=85=83?= <[email protected]> Date: Sun, 2 Aug 2026 20:30:59 +0800 Subject: [PATCH] [X86][AsmParser] Fix compiler crash on division by zero in MS inline asm This fixes issue #213415. If a user writes something like '1 / 0' or '1 % 0' in assembly, the compiler will now show a normal error message instead of crashing completely. Fixes #213415 --- clang/test/Parser/ms-inline-asm-div-by-zero.c | 5 ++ .../lib/Target/X86/AsmParser/X86AsmParser.cpp | 75 ++++++++++++++----- llvm/test/MC/X86/intel-expr-div-by-zero.s | 7 ++ 3 files changed, 68 insertions(+), 19 deletions(-) create mode 100644 clang/test/Parser/ms-inline-asm-div-by-zero.c create mode 100644 llvm/test/MC/X86/intel-expr-div-by-zero.s diff --git a/clang/test/Parser/ms-inline-asm-div-by-zero.c b/clang/test/Parser/ms-inline-asm-div-by-zero.c new file mode 100644 index 0000000000000..14de3b905735e --- /dev/null +++ b/clang/test/Parser/ms-inline-asm-div-by-zero.c @@ -0,0 +1,5 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fms-extensions -fasm-blocks -fsyntax-only -verify %s + +void foo() { // expected-note {{to match this '{'}} + __asm { return 1 / 0; } // expected-error {{division by zero in assembly expression}} +} // expected-error {{expected '}'}} diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp index 54edcba34a7e9..fc777b2ebabe7 100644 --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -268,7 +268,7 @@ class X86AsmParser : public MCTargetAsmParser { InfixOperatorStack.push_back(Op); } - int64_t execute() { + bool execute(int64_t &Result, StringRef &ErrMsg) { // Push any remaining operators onto the postfix stack. while (!InfixOperatorStack.empty()) { InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val(); @@ -276,8 +276,10 @@ class X86AsmParser : public MCTargetAsmParser { PostfixStack.push_back(std::make_pair(StackOp, 0)); } - if (PostfixStack.empty()) - return 0; + if (PostfixStack.empty()) { + Result = 0; + return false; + } SmallVector<ICToken, 16> OperandStack; for (const ICToken &Op : PostfixStack) { @@ -325,13 +327,20 @@ class X86AsmParser : public MCTargetAsmParser { case IC_DIVIDE: assert (Op1.first == IC_IMM && Op2.first == IC_IMM && "Divide operation with an immediate and a register!"); - assert (Op2.second != 0 && "Division by zero!"); + if (Op2.second == 0) { + ErrMsg = "division by zero"; + return true; + } Val = Op1.second / Op2.second; OperandStack.push_back(std::make_pair(IC_IMM, Val)); break; case IC_MOD: assert (Op1.first == IC_IMM && Op2.first == IC_IMM && "Modulo operation with an immediate and a register!"); + if (Op2.second == 0) { + ErrMsg = "division by zero"; + return true; + } Val = Op1.second % Op2.second; OperandStack.push_back(std::make_pair(IC_IMM, Val)); break; @@ -407,7 +416,8 @@ class X86AsmParser : public MCTargetAsmParser { } } assert (OperandStack.size() == 1 && "Expected a single result."); - return OperandStack.pop_back_val().second; + Result = OperandStack.pop_back_val().second; + return false; } }; @@ -489,7 +499,13 @@ class X86AsmParser : public MCTargetAsmParser { unsigned getSize() const { return CurType.Size; } unsigned getElementSize() const { return CurType.ElementSize; } unsigned getLength() const { return CurType.Length; } - int64_t getImm() { return Imm + IC.execute(); } + bool getImm(int64_t &Result, StringRef &ErrMsg) { + int64_t ICResult; + if (IC.execute(ICResult, ErrMsg)) + return true; + Result = Imm + ICResult; + return false; + } bool isValidEndState() const { return State == IES_RBRAC || State == IES_RPAREN || State == IES_INTEGER || State == IES_REGISTER || @@ -890,6 +906,29 @@ class X86AsmParser : public MCTargetAsmParser { default: State = IES_ERROR; break; + case IES_DIVIDE: + case IES_MOD: { + auto HasError = [&ErrMsg](IntelExprState IES, int64_t TmpInt) { + if (TmpInt != 0) + return false; + switch (IES) { + case IES_DIVIDE: + ErrMsg = "division by zero in assembly expression"; + break; + case IES_MOD: + ErrMsg = "modulo by zero in assembly expression"; + break; + default: + llvm_unreachable("unreachable"); + } + return true; + }; + if (HasError(State, TmpInt)) { + State = IES_ERROR; + return true; + } + [[fallthrough]]; + } case IES_PLUS: case IES_MINUS: case IES_NOT: @@ -904,8 +943,6 @@ class X86AsmParser : public MCTargetAsmParser { case IES_GE: case IES_LSHIFT: case IES_RSHIFT: - case IES_DIVIDE: - case IES_MOD: case IES_MULTIPLY: case IES_LPAREN: case IES_INIT: @@ -1190,7 +1227,7 @@ class X86AsmParser : public MCTargetAsmParser { bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM, bool &ParseError, SMLoc &End); void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start, - SMLoc End); + SMLoc End, int64_t Imm); bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End); bool ParseIntelInlineAsmIdentifier(const MCExpr *&Val, StringRef &Identifier, InlineAsmIdentifierInfo &Info, @@ -2246,7 +2283,8 @@ bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) { } void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM, - SMLoc Start, SMLoc End) { + SMLoc Start, SMLoc End, + int64_t Imm) { SMLoc Loc = Start; unsigned ExprLen = End.getPointer() - Start.getPointer(); // Skip everything before a symbol displacement (if we have one) @@ -2258,7 +2296,7 @@ void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM, ExprLen = End.getPointer() - (SymName.data() + SymName.size()); // If we have only a symbol than there's no need for complex rewrite, // simply skip everything after it - if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) { + if (!(SM.getBaseReg() || SM.getIndexReg() || Imm)) { if (ExprLen) InstInfo->AsmRewrites->emplace_back(AOK_Skip, Loc, ExprLen); return; @@ -2276,7 +2314,7 @@ void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM, OffsetNameStr = SM.getSymName(); // Emit it IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), OffsetNameStr, - SM.getImm(), SM.isMemExpr()); + Imm, SM.isMemExpr()); InstInfo->AsmRewrites->emplace_back(Loc, ExprLen, Expr); } @@ -2717,10 +2755,14 @@ bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) { if (ParseIntelExpression(SM, End)) return true; + StringRef ErrMsg; + int64_t Imm; + if (SM.getImm(Imm, ErrMsg)) + return Error(Start, ErrMsg); + if (isParsingMSInlineAsm()) - RewriteIntelExpression(SM, Start, Tok.getLoc()); + RewriteIntelExpression(SM, Start, Tok.getLoc(), Imm); - int64_t Imm = SM.getImm(); const MCExpr *Disp = SM.getSym(); const MCExpr *ImmDisp = MCConstantExpr::create(Imm, getContext()); if (Disp && Imm) @@ -2747,7 +2789,6 @@ bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) { return false; } - StringRef ErrMsg; MCRegister BaseReg = SM.getBaseReg(); MCRegister IndexReg = SM.getIndexReg(); if (IndexReg && BaseReg == X86::RIP) @@ -3647,10 +3688,6 @@ bool X86AsmParser::parseInstruction(ParseInstructionInfo &Info, StringRef Name, Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); } - // Parse condtional flags after mnemonic. - if ((Name.starts_with("ccmp") || Name.starts_with("ctest")) && - parseCFlagsOp(Operands)) - return true; // This does the actual operand parsing. Don't parse any more if we have a // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we diff --git a/llvm/test/MC/X86/intel-expr-div-by-zero.s b/llvm/test/MC/X86/intel-expr-div-by-zero.s new file mode 100644 index 0000000000000..7cf4ed04336c7 --- /dev/null +++ b/llvm/test/MC/X86/intel-expr-div-by-zero.s @@ -0,0 +1,7 @@ +# RUN: not llvm-mc -triple x86_64-unknown-unknown -x86-asm-syntax=intel %s 2>&1 | FileCheck %s + +# CHECK: error: division by zero +mov eax, 1 / 0 + +# CHECK: error: division by zero +mov eax, 1 % 0 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
