NationalSecurityAgency/ghidra · error · RuntimeError

Cannot convert '{}' to length

Error message

Cannot convert '{}' to length

What it means

Thrown by eval_range in the drgn agent when int(length) fails to convert the length argument to an integer. This function is called by putmem and related memory-reading commands to compute the address range [start, start+length). Any non-integer length value triggers this RuntimeError.

Source

Thrown at Ghidra/Debug/Debugger-agent-drgn/src/main/py/src/ghidradrgn/commands.py:447

        base, addr = trace.extra.require_mm().map(nproc, start)
        if base != addr.space:
            trace.create_overlay_space(base, addr.space)
        count = trace.put_bytes(addr, buf)
        if display_result:
            print("Wrote {} bytes".format(count))
        if isinstance(count, Future):
            return {'count': -1}
        else:
            return {'count': count}
    return {'count': 0}


def eval_range(address: Union[str, int], length: Union[str, int]) -> Tuple[int, int]:
    start = int(address)
    try:
        end = start + int(length)
    except Exception as e:
        raise RuntimeError("Cannot convert '{}' to length".format(length))
    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 length as a base-10 integer or integer-valued string, e.g. 256 or '256'.
  2. If you have a hex value, convert it first: int(hexstr, 16) before passing.
  3. Ensure no whitespace or non-digit characters are in the length string.

Example fix

// before
ghidra_trace_putmem('0x7fff0000', '0x100')
// after
ghidra_trace_putmem('0x7fff0000', str(int('0x100', 16)))
Defensive patterns

Strategy: validation

Validate before calling

def parse_length(length) -> int:
    if isinstance(length, int):
        return length
    if isinstance(length, str):
        length = length.strip()
        if length.startswith('0x') or length.startswith('0X'):
            return int(length, 16)
        return int(length)
    raise ValueError(f"Cannot parse length: {length!r}")

# Use parsed value:
length_int = parse_length(length)

Type guard

def is_valid_length(length) -> bool:
    if isinstance(length, int):
        return length >= 0
    if isinstance(length, str):
        try:
            int(length)
            return True
        except ValueError:
            return False
    return False

Try / catch

try:
    ghidra_trace_putmem(address, length)
except RuntimeError as e:
    if 'Cannot convert' in str(e):
        print(f"Length '{length}' is not a valid integer. Pass a base-10 number.")
    raise

Prevention

When it happens

Trigger: Calling ghidra_trace_putmem(address, '0x10') with a hex string length, ghidra_trace_putmem(address, 'abc'), or passing a float string like '1.5' as the length. The int() call only accepts base-10 integer strings (or int type directly).

Common situations: Passing hex-formatted lengths (common in debugging contexts like '0x100'); passing a GDB/drgn Value object that is not directly int-convertible; accidental string concatenation producing '0x100 ' with trailing space.

Related errors


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