NationalSecurityAgency/ghidra · error · IllegalArgumentException

DataType %s has dynamic length

Error message

DataType %s has dynamic length

What it means

Thrown by InputsTableModel.addPointerVars when the data type pointed to by a pointer argument reports length -1, meaning it is dynamically sized. The function emulator needs a concrete byte count to allocate (and dereference) pointer destination storage; variable-length types like strings or zero-terminated structures cannot be allocated to a fixed size.

Source

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

		byte[] addrToBytes(Address address, int length) {
			return Utils.longToBytes(address.getOffset(), length, language.isBigEndian());
		}

		void allocate(int length) {
			// Extension point
		}

		abstract T newRow(String name, VarStorage storage, DataType type);

		public void addPointerVars(int count) {
			if (!(getBaseDataType(from.getType()) instanceof Pointer ptr)) {
				return;
			}
			DataType dest = ptr.getDataType();
			int length = dest.getLength();
			int alignedLen = dest.getAlignedLength();
			if (length == -1) {
				throw new IllegalArgumentException(
					"DataType %s has dynamic length".formatted(dest));
			}
			allocate((alignedLen * (count - 1)) + length);

			AddressSpace space = function.getProgram().getLanguage().getDefaultDataSpace();
			int offset = 0;

			if (!(DataTypeUtilities.getBaseDataType(dest) instanceof Composite composite)) {
				for (int i = 0; i < count; i++) {
					VarStorage deref = from.getStorage().deref(language, space, offset, length);
					String name = count == 1 // LATER: Cull unnecessary ()s?
							? "*(%s)".formatted(from.name)
							: "(%s)[%d]".formatted(from.name, i);
					findRow(into, name).ifPresent(into::delete);
					T row = newRow(name, deref, dest);
					into.add(row);
					added.add(row);

View on GitHub (pinned to d5f144c24d)

Solutions

  1. Change the argument's declared type from a dynamic type to a fixed-length equivalent (e.g., char* -> a fixed-size byte array type) before emulation.
  2. Resolve the pointer destination to a concrete DataType with a known length in the program's data type manager.
  3. Avoid enabling pointer-variable allocation (the 'count > 0' path) for inputs whose target type is dynamic.
  4. Replace a dynamic string type with a fixed char[ N ] array type for the emulation session.

Example fix

// before
DataType dest = ptr.getDataType();
int length = dest.getLength(); // -1 for dynamic types
// allocate((alignedLen*(count-1))+length) -> underflows / throws

// after
DataType dest = ptr.getDataType();
if (dest.getLength() == -1) {
    Msg.warn(this, "Skipping dynamic-length pointer dest: " + dest);
    return;
}
Defensive patterns

Strategy: validation

Validate before calling

DataType dest = ((Pointer) DataTypeUtilities.getBaseDataType(from.getType())).getDataType();
boolean ok = dest.getLength() != -1;

Type guard

static boolean hasFixedLength(Pointer p) {
    return p.getDataType() != null && p.getDataType().getLength() != -1;
}

Try / catch

try {
    tableModel.addPointerVars(count);
} catch (IllegalArgumentException e) {
    Msg.showWarn(this, null, "Cannot add pointer vars", e.getMessage());
}

Prevention

When it happens

Trigger: Calling addPointerVars(count) on an input row whose base data type is a Pointer, where ptr.getDataType().getLength() returns -1 (e.g., the pointer targets a char* / TerminatedStringDataType, or a variable-length structure).

Common situations: Functions taking char*/string arguments; pointers to forward-declared or undefined types Ghidra treats as dynamic; pointer destinations to variable-length composites.

Related errors


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