NationalSecurityAgency/ghidra · error · AddressOutOfBoundsException

Range [%s:%x+%x] entirely exceeds space min

Error message

Range [%s:%x+%x] entirely exceeds space min

What it means

Thrown by OpenTrace.toRange when translating a client-supplied AddrRange into an AddressRange. The method clamps a range whose start or end partially falls outside the address space, but if the range's computed end (offset+extend) is strictly below the space's minimum address offset, the whole range is entirely below the space and cannot be represented, so it throws AddressOutOfBoundsException. The %s:%x+%x placeholders report the space name, offset, and extend length of the offending range.

Source

Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/OpenTrace.java:174

		 */
		long minOffset = range.getOffset();
		if (Long.compareUnsigned(minOffset, space.getMinAddress().getOffset()) < 0) {
			Msg.warn(this, "Range [%s:%x+%x] partially exceeds space min. Clamping."
					.formatted(range.getSpace(), range.getOffset(), range.getExtend()));
			minOffset = space.getMinAddress().getOffset();
		}
		else if (Long.compareUnsigned(minOffset, space.getMaxAddress().getOffset()) > 0) {
			throw new AddressOutOfBoundsException("Range [%s:%x+%x] entirely exceeds space max"
					.formatted(range.getSpace(), range.getOffset(), range.getExtend()));
		}
		long maxOffset = range.getOffset() + range.getExtend(); // Use the requested offset, not adjusted
		if (Long.compareUnsigned(maxOffset, space.getMaxAddress().getOffset()) > 0) {
			Msg.warn(this, "Range [%s:%x+%x] partially exceeds space max. Clamping."
					.formatted(range.getSpace(), range.getOffset(), range.getExtend()));
			maxOffset = space.getMaxAddress().getOffset();
		}
		else if (Long.compareUnsigned(maxOffset, space.getMinAddress().getOffset()) < 0) {
			throw new AddressOutOfBoundsException("Range [%s:%x+%x] entirely exceeds space min"
					.formatted(range.getSpace(), range.getOffset(), range.getExtend()));
		}
		Address min = space.getAddress(minOffset);
		Address max = space.getAddress(maxOffset);
		return new AddressRangeImpl(min, max);
	}

	public Register getRegister(String name, boolean required) {
		Register register = trace.getBaseLanguage().getRegister(name);
		if (required && register == null) {
			throw new InvalidRegisterError(name);
		}
		return register;
	}
}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Validate offset and extend against the space bounds before sending the range: ensure offset+extend (unsigned) >= space min and offset (unsigned) <= space max.
  2. Guard against extend that would make offset+extend wrap around unsigned; cap extend at the space's max address minus the offset.
  3. Confirm the AddressSpace name sent by the client exists in the trace's language/compiler spec and that its min/max match the backend's view.
  4. Check that you are not passing a zero or negative extend length when the space minimum is above zero.

Example fix

// before
long maxOffset = offset + extend; // can wrap
AddrRange range = AddrRange.newBuilder().setSpace("ram").setOffset(offset).setExtend(extend).build();

// after
long spaceMin = space.getMinAddress().getOffset();
long spaceMax = space.getMaxAddress().getOffset();
if (Long.compareUnsigned(offset, spaceMin) < 0 ||
    Long.compareUnsigned(offset + extend, spaceMin) < 0 ||
    Long.compareUnsigned(offset, spaceMax) > 0) {
    throw new IllegalArgumentException("range outside space bounds");
}
Defensive patterns

Strategy: validation

Validate before calling

long spaceMin = space.getMinAddress().getOffset();
long spaceMax = space.getMaxAddress().getOffset();
long minOffset = range.getOffset();
long maxOffset = range.getOffset() + range.getExtend();
if (Long.compareUnsigned(minOffset, spaceMax) > 0 ||
    Long.compareUnsigned(maxOffset, spaceMin) < 0) {
    throw new IllegalArgumentException(
        "range entirely outside space " + range.getSpace());
}

Try / catch

try {
    AddressRange r = openTrace.toRange(range, true);
} catch (AddressOutOfBoundsException e) {
    // range entirely outside the space; reject or skip the operation
}

Prevention

When it happens

Trigger: A TraceRmi client sends a memory/register range (e.g. via a setValue, putBytes, or memory-state request) whose offset+extend, treated as unsigned, is less than the target AddressSpace.getMinAddress().getOffset(). This can occur when the extend causes a 64-bit unsigned wrap-around (overflow) or when the client sends a near-zero offset for a space whose minimum is high.

Common situations: Client computes extend incorrectly and wraps past zero; a debugger backend reports a range for an address space whose bounds differ from the trace's language definition; mismatched register/memory space between backend and Ghidra language; using a negative extend or zero-length range that lands below the space floor.

Related errors


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