[lldb] lldb should reject invalid DW_OP_mod results instead of continuing with a void Scalar

Open Beginner friendly
#208,433 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
cpp

Research direction

Start with the DW_OP_mod handler in DWARFExpression.cpp and Scalar::operator% in Scalar.cpp, then compare the neighbouring DW_OP_div error checks. Done means invalid modulo results, including a zero divisor, produce an evaluator error instead of leaving a void Scalar on the DWARF stack and continuing.

Written by the indexing model from the issue text.

Description

accepts-invalid lldb

LLDB's DW_OP_mod evaluator stores the result of Scalar::operator% back onto the DWARF stack without checking whether it is valid. When the modulo is undefined — for example a zero divisor, which the accepted DWARF issue 250924.2 clarifies should raise an error, like division — operator% returns a Scalar of type e_void, and evaluation continues with that invalid entry on the stack. Later opcodes can then consume or discard it (e.g. DW_OP_drop), so the invalid intermediate is silently absorbed instead of being reported where it arose.

Source Evidence

operator% (in Scalar.cpp) returns a void Scalar when the modulo is undefined (zero divisor, or operands that do not promote to an integer):

const Scalar lldb_private::operator%(Scalar lhs, Scalar rhs) {
  Scalar result;
  if ((result.m_type = Scalar::PromoteToMaxType(lhs, rhs)) != Scalar::e_void) {
    if (!rhs.IsZero() && result.m_type == Scalar::e_int) {
      result.m_integer = lhs.m_integer % rhs.m_integer;
      return result;
    }
  }
  result.m_type = Scalar::e_void;
  return result;
}

The DW_OP_mod handler (in DWARFExpression.cpp) stores that result with no validity check:

case DW_OP_mod:
  tmp = stack.back();
  stack.pop_back();
  stack.back().GetScalar() = stack.back().GetScalar() % tmp.GetScalar();
  break;

The neighbouring DW_OP_div handler, by contrast, guards both the zero divisor and the result validity:

case DW_OP_div: {
  tmp = stack.back();
  if (tmp.GetScalar().IsZero())
    return llvm::createStringError("divide by zero");
  ...
  stack.back() = dividend / divisor;
  if (!stack.back().GetScalar().IsValid())
    return llvm::createStringError("divide failed");
} break;

DW_OP_shr and DW_OP_plus_uconst likewise return an evaluator error on failure. DW_OP_mod is the outlier that keeps the invalid Scalar and keeps going.

Dominant language
LLVM
Stars
40.6k
Forks
18.7k
Avg merge
18h 16m
Merged PRs (30d)
417

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from llvm/llvm-project

All issues in llvm/llvm-project

Similar issues

More Compilers issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.