{"record":{"id":"74c35b89df7e642a","repo":"NationalSecurityAgency/ghidra","slug":"operandindex","errorCode":null,"errorMessage":"operandIndex","messagePattern":"operandIndex","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java","lineNumber":475,"sourceCode":"\t\t// NOTE: Always call with the write lock\n\t\tfor (DBTraceReferenceEntry ent : List.copyOf(referenceMapSpace\n\t\t\t\t.reduce(TraceAddressSnapRangeQuery\n\t\t\t\t\t\t.intersecting(new AddressRangeImpl(fromAddress, fromAddress), span))\n\t\t\t\t.values())) {\n\t\t\tif (!ent.toRange.equals(toRange) || ent.opIndex != operandIndex) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// This sends events and updates primary. Do I want that here?\n\t\t\tDBTraceUtils.makeWay(ent, span, (e, s) -> e.setLifespan(s), e -> e.ref.delete());\n\t\t}\n\t}\n\n\t@Override\n\tpublic DBTraceReference addMemoryReference(Lifespan lifespan, Address fromAddress,\n\t\t\tAddressRange toRange, RefType refType, SourceType source, int operandIndex) {\n\t\tif (operandIndex < -1) {\n\t\t\tthrow new IllegalArgumentException(\"operandIndex\");\n\t\t}\n\t\ttry (LockHold hold = LockHold.lock(lock.writeLock())) {\n\t\t\tmakeWay(lifespan, fromAddress, toRange, operandIndex);\n\n\t\t\tDBTraceReferenceEntry entry = referenceMapSpace.put(fromAddress, lifespan, null);\n\t\t\tentry.set(toRange, -1, refType, operandIndex, 0, false, TypeEnum.MEMORY, source);\n\t\t\tDBTraceReference ref = TypeEnum.MEMORY.construct(entry);\n\t\t\tentry.ref = ref;\n\t\t\tmanager.doAddXRef(entry);\n\t\t\treturn ref;\n\t\t}\n\t}\n\n\tprivate boolean isExternalBlockAddress(Lifespan lifespan, Address addr) {\n\t\t// TODO: Verify that this works for emulation\n\t\tTraceMemoryRegion region =\n\t\t\ttrace.getMemoryManager().getRegionContaining(lifespan.lmin(), addr);\n\t\treturn region != null &&","sourceCodeStart":457,"sourceCodeEnd":493,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Framework-TraceModeling/src/main/java/ghidra/trace/database/symbol/DBTraceReferenceSpace.java#L457-L493","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nrefMgr.addMemoryReference(span, from, toRange, RefType.DATA, SourceType.USER, computedIndex /* -2 */);\n\n// after\nint opIdx = computedIndex < 0 ? -1 : computedIndex;\nrefMgr.addMemoryReference(span, from, toRange, RefType.DATA, SourceType.USER, opIdx);","handlingStrategy":"validation","validationCode":"int opIdx = computedIndex < -1 ? -1 : computedIndex; // -1 = instruction-level\nrefMgr.addMemoryReference(span, from, toRange, refType, source, opIdx);","typeGuard":"static boolean validOperandIndex(int opIdx) { return opIdx >= -1; }","tryCatchPattern":null,"preventionTips":["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."],"tags":["ghidra","trace-modeling","reference","operand-index","illegal-argument"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}