NationalSecurityAgency/ghidra · error · RuntimeError

Cannot convert '{length}' to length

Error message

Cannot convert '{length}' to length

What it means

Raised by eval_range (commands.py:471-472) when util.parse_and_eval(length) throws any exception. The length is parsed independently of the address; failure to evaluate the length expression produces this RuntimeError.

Source

Thrown at Ghidra/Debug/Debugger-agent-x64dbg/src/main/py/src/ghidraxdbg/commands.py:472


def eval_address(address: Union[str, int]) -> int:
    try:
        result = util.parse_and_eval(address)
        if isinstance(result, int):
            return result
        raise ValueError(f"Value '{address}' does not evaluate to an int")
    except Exception:
        raise RuntimeError(f"Cannot convert '{address}' to address")


def eval_range(address: Union[str, int],
               length: Union[str, int]) -> Tuple[int, int]:
    start = eval_address(address)
    try:
        l = util.parse_and_eval(length)
    except Exception as e:
        raise RuntimeError(f"Cannot convert '{length}' to length")
    if not isinstance(l, int):
        raise ValueError(f"Value '{address}' does not evaluate to an int")
    end = start + l
    return start, end


def putmem(address: Union[str, int], length: Union[str, int],
           pages: bool = True, display_result: bool = True) -> Dict[str, int]:
    start, end = eval_range(address, length)
    return put_bytes(start, end, pages, display_result)


def ghidra_trace_putmem(address: Union[str, int], length: Union[str, int],
                        pages: bool = True) -> Dict[str, int]:
    """Record the given block of memory into the Ghidra trace."""

    STATE.require_tx()
    return putmem(address, length, pages, True)

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Pass a numeric length or a known-resolvable size expression, e.g. putmem(addr, 0x100).
  2. Validate the length expression with util.parse_and_eval first.
  3. Use a literal integer length to avoid evaluator dependency.

Example fix

// before
putmem(0x00400000, 'sizeof_unknown')  # -> Cannot convert 'sizeof_unknown' to length

// after
putmem(0x00400000, 0x100)
Defensive patterns

Strategy: try-catch

Validate before calling

def try_eval_length(length):
    try:
        l = util.parse_and_eval(length)
    except Exception:
        return int(length, 0) if isinstance(length, str) else int(length)
    return l

Type guard

def is_evaluatable_length(length) -> bool:
    try:
        util.parse_and_eval(length)
        return True
    except Exception:
        return isinstance(length, int)

Try / catch

try:
    putmem(address, length)
except RuntimeError as e:
    if 'Cannot convert' in str(e) and 'to length' in str(e):
        length = int(length, 0) if isinstance(length, str) else int(length)
        putmem(address, length)
    else:
        raise

Prevention

When it happens

Trigger: Calling eval_range / putmem / ghidra_trace_putmem / delmem / putmem_state with a length argument that parse_and_eval cannot resolve: an undefined symbol, malformed expression, or empty string for length.

Common situations: Passing a symbolic size that is not defined; a length field left blank or set to a non-numeric expression; querying memory ranges before symbols load.

Related errors


AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14). Data as JSON: /api/errors/b886328da562b1b3. Report an issue: GitHub.