NationalSecurityAgency/ghidra · error · IllegalStateException

Input %s conflicts: 0x%s != 0x%s

Error message

Input %s conflicts: 0x%s != 0x%s

What it means

Thrown by InputInitializer.checkConflicts after input initialization when an emulator read-back of an input's storage disagrees with the value the row claims it set. A conflict means two or more inputs map to overlapping storage (registers or stack offsets), so assigning one clobbered another.

Source

Thrown at Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/gui/emulation/DebuggerEmulateFunctionDialog.java:1114

			doInitialize(input);
		}

		public void initializeDependencies(InputRow input) {
			for (String dep : input.depsByName) {
				initializeDependency(dep);
			}
		}

		public String toHex(byte[] value, int length) {
			return Utils.bytesToBigInteger(value, length, language.isBigEndian(), false)
					.toString(16);
		}

		public void checkConflicts() {
			for (InputRow r : inputs) {
				LocAndVal value = eval.readVariable(r.storage);
				if (!(Arrays.equals(value.value(), r.value))) {
					throw new IllegalStateException("Input %s conflicts: 0x%s != 0x%s".formatted(
						r.storage, toHex(r.value, r.length), toHex(value.value(), r.length)));
				}
			}
		}
	}

	protected void initializeInputs(Eval eval) {
		InputInitializer initializer = new InputInitializer(eval, inputsTableModel.getModelData());
		initializer.initializeInputs();
		initializer.checkConflicts();
		eval.commit();
	}

	protected void captureOutputs(Eval eval, List<ProbeOut> probesOut) {
		for (OutputRow r : outputsTableModel.copyModelData()) {
			if (r.name.startsWith(PREFIX_PROBE)) {
				outputsTableModel.delete(r);
			}

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Inspect the function's calling convention / parameter storage assignments for overlaps using the Decompiler or the Function signature editor.
  2. Remove or merge the conflicting input rows so no two inputs share storage.
  3. Re-derive inputs from the function signature rather than manual entry so VarStorage is computed consistently.
  4. Check that a custom calling convention does not assign the same register to two parameters.

Example fix

// before
initializer.initializeInputs();
initializer.checkConflicts(); // IllegalStateException on overlap

// after - detect overlaps before initializing
Set<VarStorage> seen = new HashSet<>();
for (InputRow r : inputs) {
    if (!seen.add(r.storage)) {
        Msg.warn(this, "Overlapping input storage: " + r.storage);
    }
}
Defensive patterns

Strategy: validation

Validate before calling

Set<VarStorage> seen = new HashSet<>();
for (InputRow r : inputs) if (!seen.add(r.storage)) { /* overlap */ }

Type guard

static boolean inputsOverlap(List<InputRow> rows) {
    Set<VarStorage> s = new HashSet<>();
    for (InputRow r : rows) if (!s.add(r.storage)) return true;
    return false;
}

Try / catch

try {
    initializer.checkConflicts();
} catch (IllegalStateException e) {
    Msg.showError(this, null, "Input Conflict", e.getMessage());
}

Prevention

When it happens

Trigger: initializeInputs() followed by checkConflicts(): for each InputRow, eval.readVariable(r.storage) returns bytes that differ from r.value, indicating overlapping/conflicting input storage assignments within the function signature or user-edited inputs.

Common situations: Functions where a struct passed in registers overlaps individual field inputs; ABI collisions (e.g., a varargs area overlapping named arguments); user-edited emulator inputs that alias the same register; compiler quirks mapping multiple parameters to one storage location.

Related errors


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