{"record":{"id":"e1a8e2048a5ec796","repo":"NationalSecurityAgency/ghidra","slug":"range-s-x-x-entirely-exceeds-space-max","errorCode":null,"errorMessage":"Range [%s:%x+%x] entirely exceeds space max","messagePattern":"Range \\[(.+?):%x\\+%x\\] entirely exceeds space max","errorType":"exception","errorClass":"AddressOutOfBoundsException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/OpenTrace.java","lineNumber":164,"sourceCode":"\t}\n\n\t@Override\n\tpublic AddressRange toRange(AddrRange range, boolean required) {\n\t\tAddressSpace space = getSpace(range.getSpace(), required);\n\t\tif (space == null) {\n\t\t\treturn null;\n\t\t}\n\t\t/**\n\t\t * Clamp to only the valid addresses, but do at least warn.\n\t\t */\n\t\tlong minOffset = range.getOffset();\n\t\tif (Long.compareUnsigned(minOffset, space.getMinAddress().getOffset()) < 0) {\n\t\t\tMsg.warn(this, \"Range [%s:%x+%x] partially exceeds space min. Clamping.\"\n\t\t\t\t\t.formatted(range.getSpace(), range.getOffset(), range.getExtend()));\n\t\t\tminOffset = space.getMinAddress().getOffset();\n\t\t}\n\t\telse if (Long.compareUnsigned(minOffset, space.getMaxAddress().getOffset()) > 0) {\n\t\t\tthrow new AddressOutOfBoundsException(\"Range [%s:%x+%x] entirely exceeds space max\"\n\t\t\t\t\t.formatted(range.getSpace(), range.getOffset(), range.getExtend()));\n\t\t}\n\t\tlong maxOffset = range.getOffset() + range.getExtend(); // Use the requested offset, not adjusted\n\t\tif (Long.compareUnsigned(maxOffset, space.getMaxAddress().getOffset()) > 0) {\n\t\t\tMsg.warn(this, \"Range [%s:%x+%x] partially exceeds space max. Clamping.\"\n\t\t\t\t\t.formatted(range.getSpace(), range.getOffset(), range.getExtend()));\n\t\t\tmaxOffset = space.getMaxAddress().getOffset();\n\t\t}\n\t\telse if (Long.compareUnsigned(maxOffset, space.getMinAddress().getOffset()) < 0) {\n\t\t\tthrow new AddressOutOfBoundsException(\"Range [%s:%x+%x] entirely exceeds space min\"\n\t\t\t\t\t.formatted(range.getSpace(), range.getOffset(), range.getExtend()));\n\t\t}\n\t\tAddress min = space.getAddress(minOffset);\n\t\tAddress max = space.getAddress(maxOffset);\n\t\treturn new AddressRangeImpl(min, max);\n\t}\n\n\tpublic Register getRegister(String name, boolean required) {","sourceCodeStart":146,"sourceCodeEnd":182,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/service/tracermi/OpenTrace.java#L146-L182","documentation":"Thrown as AddressOutOfBoundsException by OpenTrace.toRange when the range's minimum offset is strictly greater than the address space's maximum address — i.e., the entire requested range lies beyond the high end of the space. This is distinct from the partial-overflow case, which only warns and clamps. The unsigned comparison means 64-bit offsets are compared correctly.","triggerScenarios":"A remote Trace RMI command specifies an AddrRange whose offset (in the given space) is beyond the space's max address. For example, an offset of 0x100000000 in a 32-bit space, or any range whose start exceeds the space ceiling. The min/max comparison is unsigned.","commonSituations":"64-bit address passed against a 32-bit address space definition; arithmetic overflow producing a wrapped/huge offset; the wrong address space name used for the target; a target with a non-standard memory layout the trace language doesn't model correctly.","solutions":["Verify the address space name in the range matches the target's actual memory space.","Ensure offsets fit within the space's bit-width (e.g., < 2^32 for a 32-bit space).","Check for arithmetic that may have overflowed or sign-extended a 32-bit value into 64 bits."],"exampleFix":"// before\n// range offset 0x1_0000_0000 in a 32-bit space -> throws\n\n// after\n// use an offset within the space, e.g. 0x0040_0000\nrange = AddrRange.newBuilder().setSpace(\"ram\").setOffset(0x00400000).setExtend(0x100).build();","handlingStrategy":"validation","validationCode":"AddressSpace space = trace.getBaseAddressFactory().getAddressSpace(range.getSpace());\nlong min = range.getOffset();\nif (Long.compareUnsigned(min, space.getMaxAddress().getOffset()) > 0) {\n    throw new IllegalArgumentException(\"Range start beyond space max\");\n}","typeGuard":"boolean isRangeWithinSpace(AddrRange range, AddressSpace space) {\n    long min = range.getOffset();\n    long max = range.getOffset() + range.getExtend();\n    return Long.compareUnsigned(min, space.getMinAddress().getOffset()) >= 0\n        && Long.compareUnsigned(max, space.getMaxAddress().getOffset()) <= 0;\n}","tryCatchPattern":null,"preventionTips":["Validate offsets fit the address space bit-width before sending ranges.","Guard against arithmetic overflow/sign-extension when computing offsets.","Use the correct address space name for the target's memory layout."],"tags":["address-validation","memory","address-space","tracermi","ghidra-debug"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}