NationalSecurityAgency/ghidra · error · IllegalArgumentException

Return address must be in {}

Error message

Return address must be in {}

What it means

AbstractUnwoundFrame.setReturnAddress() writes the return address into the frame's program counter. It validates that the supplied address belongs to the frame's code address space (codeSpace) — i.e. the executable space — because the PC register must live there. An address from any other space (stack, register, external, etc.) is rejected with IllegalArgumentException("Return address must be in " + codeSpace).

Source

Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java:342

			}

			@Override
			protected ByteBuffer catenate(int total, ByteBuffer value, ByteBuffer piece, int size) {
				return value;
			}

			@Override
			public ByteBuffer evaluateStorage(Program program, VariableStorage storage) {
				return evaluateStorage(program, storage, buf);
			}
		}.evaluateStorage(program, storage);
		return fence.ready();
	}

	@Override
	public CompletableFuture<Void> setReturnAddress(StateEditor editor, Address addr) {
		if (addr.getAddressSpace() != codeSpace) {
			throw new IllegalArgumentException("Return address must be in " + codeSpace);
		}
		BytesPcodeArithmetic bytesArithmetic = BytesPcodeArithmetic.forLanguage(language);
		byte[] bytes = bytesArithmetic.fromConst(addr.getOffset(), pc.getNumBytes());
		return editor.setVariable(computeAddressOfReturnAddress(), bytes);
	}

	@Override
	public T zext(T value, int length) {
		PcodeArithmetic<T> arithmetic = state.getArithmetic();
		return arithmetic.unaryOp(PcodeOp.INT_ZEXT, length, (int) arithmetic.sizeOf(value), value);
	}
}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Pass an address in the frame's code space: verify addr.getAddressSpace().equals(codeSpace) first.
  2. If you hold an offset, resolve it into the code space via the language's code address space before calling.
  3. For non-code 'return' targets, reconsider whether setReturnAddress is the right API.

Example fix

// before
frame.setReturnAddress(editor, stackAddr); // throws: stackAddr not in codeSpace

// after
AddressSpace codeSpace = frame.getLanguage().getDefaultSpace(); // the code space
if (!addr.getAddressSpace().equals(codeSpace)) {
    throw new IllegalArgumentException("return address must be in code space");
}
frame.setReturnAddress(editor, addr);
Defensive patterns

Strategy: validation

Validate before calling

if (!addr.getAddressSpace().equals(codeSpace)) {
    throw new IllegalArgumentException("return address must be in code space " + codeSpace);
}
frame.setReturnAddress(editor, addr);

Type guard

public static boolean isInCodeSpace(Address addr, AddressSpace codeSpace) {
    return addr != null && codeSpace != null && addr.getAddressSpace().equals(codeSpace);
}

Try / catch

try {
    frame.setReturnAddress(editor, addr);
} catch (IllegalArgumentException e) {
    if (e.getMessage().contains("Return address must be in")) {
        // resolve addr into the code space and retry
    } else throw e;
}

Prevention

When it happens

Trigger: Passing a stack address, a register-space address, or a constant/external-space address to setReturnAddress. Using an address from a different program/address space than the one the frame's language defines as code.

Common situations: Scripts that hand a computed stack pointer or a raw offset into setReturnAddress. Confusing the return-address location (code) with the return-value/stack location. Languages with non-standard code spaces.

Related errors


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