NationalSecurityAgency/ghidra · error · IllegalArgumentException
operandIndex
Error message
operandIndex
What it means
Thrown by DBTraceReferenceSpace.addMemoryReference when operandIndex < -1. In Ghidra's reference model the operand index identifies which instruction operand a reference attaches to: 0..N is an operand index and -1 means 'instruction-level / no specific operand'. Any value below -1 is therefore meaningless and rejected.
Source
Thrown at Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java:475
// NOTE: Always call with the write lock
for (DBTraceReferenceEntry ent : List.copyOf(referenceMapSpace
.reduce(TraceAddressSnapRangeQuery
.intersecting(new AddressRangeImpl(fromAddress, fromAddress), span))
.values())) {
if (!ent.toRange.equals(toRange) || ent.opIndex != operandIndex) {
continue;
}
// This sends events and updates primary. Do I want that here?
DBTraceUtils.makeWay(ent, span, (e, s) -> e.setLifespan(s), e -> e.ref.delete());
}
}
@Override
public DBTraceReference addMemoryReference(Lifespan lifespan, Address fromAddress,
AddressRange toRange, RefType refType, SourceType source, int operandIndex) {
if (operandIndex < -1) {
throw new IllegalArgumentException("operandIndex");
}
try (LockHold hold = LockHold.lock(lock.writeLock())) {
makeWay(lifespan, fromAddress, toRange, operandIndex);
DBTraceReferenceEntry entry = referenceMapSpace.put(fromAddress, lifespan, null);
entry.set(toRange, -1, refType, operandIndex, 0, false, TypeEnum.MEMORY, source);
DBTraceReference ref = TypeEnum.MEMORY.construct(entry);
entry.ref = ref;
manager.doAddXRef(entry);
return ref;
}
}
private boolean isExternalBlockAddress(Lifespan lifespan, Address addr) {
// TODO: Verify that this works for emulation
TraceMemoryRegion region =
trace.getMemoryManager().getRegionContaining(lifespan.lmin(), addr);
return region != null &&View on GitHub (pinned to d5f144c24d)
Solutions
- Pass -1 for instruction-level references, or a non-negative operand index.
- Clamp the computed index: int idx = Math.max(-1, computed);
- Trace where a negative-below-minus-one value originates and fix the upstream calculation.
Example fix
// before refMgr.addMemoryReference(span, from, toRange, RefType.DATA, SourceType.USER, computedIndex /* -2 */); // after int opIdx = computedIndex < 0 ? -1 : computedIndex; refMgr.addMemoryReference(span, from, toRange, RefType.DATA, SourceType.USER, opIdx);
Defensive patterns
Strategy: validation
Validate before calling
int opIdx = computedIndex < -1 ? -1 : computedIndex; // -1 = instruction-level refMgr.addMemoryReference(span, from, toRange, refType, source, opIdx);
Type guard
static boolean validOperandIndex(int opIdx) { return opIdx >= -1; } Prevention
- Use -1 for instruction-level references and a non-negative operand index otherwise.
- Route all add*Reference calls through one helper that clamps operandIndex to >= -1.
- Assert operandIndex at the importer boundary where foreign conventions enter.
When it happens
Trigger: Calling addMemoryReference(lifespan, fromAddress, toRange, refType, source, operandIndex) with operandIndex <= -2, often from a default-initialized int field, an uninitialised array element, or a computed index that underflows.
Common situations: Importers/parsers that compute operandIndex from a negative base; passing 0 then decrementing; misreading the API and sending a sentinel like -2; porting code that used a different sentinel convention.
Related errors
- Memory addresses cannot be associated with a thread
- Given namespace is not in this trace
- Given symbol is not in this trace
- max < min: min={min},max={max}
- name cannot be null
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/74c35b89df7e642a.
Report an issue: GitHub.