NationalSecurityAgency/ghidra · error · TraceRmiError

Cannot send TraceRmi message with excessive length

Error message

Cannot send TraceRmi message with excessive length

What it means

Intended to be raised as TraceRmiError by send_delimited() when a serialized protobuf message exceeds MAX_MSG_LENGTH (1<<16 = 64 KiB) before being placed on the socket. The guard exists to prevent oversized messages from being sent. IMPORTANT BUG: util.py raises 'TraceRmiError' but never imports or defines it, so if this line actually executes it throws NameError: name 'TraceRmiError' is not defined instead of the documented error.

Source

Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/py/src/ghidratrace/util.py:34

from concurrent.futures import Future
import socket
from typing import TypeVar

from google.protobuf import message as _message

M = TypeVar('M', bound=_message.Message)
MAX_MSG_LENGTH = 1 << 16 # Plenty and shouldn't cause OOM


def send_length(s: socket.socket, value: int) -> None:
    s.sendall(value.to_bytes(4, 'big'))


def send_delimited(s: socket.socket, msg: _message.Message) -> None:
    data = msg.SerializeToString()
    size = len(data)
    if size > MAX_MSG_LENGTH:
        raise TraceRmiError("Cannot send TraceRmi message with excessive length")
    send_length(s, size)
    s.sendall(data)


def recv_all(s, size: int) -> bytes:
    buf = b''
    while len(buf) < size:
        part = s.recv(size - len(buf))
        if len(part) == 0:
            return buf
        buf += part
    return buf
    # return s.recv(size, socket.MSG_WAITALL)


def recv_length(s: socket.socket) -> int:
    buf = recv_all(s, 4)
    if len(buf) < 4:

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Chunk large payloads into multiple smaller messages below 64 KiB each.
  2. For memory bytes, write/read in page-sized or smaller ranges instead of one giant buffer.
  3. If developing, fix the latent bug by importing/defining TraceRmiError in util.py so the guard is usable.

Example fix

# before
client.put_bytes(addr, huge_buffer)  # > 64KiB
# after
CHUNK = 32 * 1024
for off in range(0, len(huge_buffer), CHUNK):
    client.put_bytes(addr.add(off), huge_buffer[off:off+CHUNK])
Defensive patterns

Strategy: validation

Validate before calling

from ghidratrace.util import MAX_MSG_LENGTH
data = msg.SerializeToString()
if len(data) > MAX_MSG_LENGTH:
    raise ValueError(f'message {len(data)} > {MAX_MSG_LENGTH}; chunk it')

Try / catch

try:
    send_delimited(s, msg)
except (ValueError, NameError):
    # chunk payload below 64KiB and resend

Prevention

When it happens

Trigger: Serializing a Value carrying a very large bytes/string payload (e.g. put_bytes of a big memory region in a single message), a large object tree, or a method return with bulky data such that SerializeToString() exceeds 64 KiB.

Common situations: Bulk memory writes/reads done in one call rather than chunked; large symbol/module lists; transferring big blobs over TraceRMI.

Related errors


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