{"record":{"id":"83c3d38fb6b4a4d6","repo":"NationalSecurityAgency/ghidra","slug":"return-address-must-be-in","errorCode":null,"errorMessage":"Return address must be in {}","messagePattern":"Return address must be in (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java","lineNumber":342,"sourceCode":"\t\t\t}\n\n\t\t\t@Override\n\t\t\tprotected ByteBuffer catenate(int total, ByteBuffer value, ByteBuffer piece, int size) {\n\t\t\t\treturn value;\n\t\t\t}\n\n\t\t\t@Override\n\t\t\tpublic ByteBuffer evaluateStorage(Program program, VariableStorage storage) {\n\t\t\t\treturn evaluateStorage(program, storage, buf);\n\t\t\t}\n\t\t}.evaluateStorage(program, storage);\n\t\treturn fence.ready();\n\t}\n\n\t@Override\n\tpublic CompletableFuture<Void> setReturnAddress(StateEditor editor, Address addr) {\n\t\tif (addr.getAddressSpace() != codeSpace) {\n\t\t\tthrow new IllegalArgumentException(\"Return address must be in \" + codeSpace);\n\t\t}\n\t\tBytesPcodeArithmetic bytesArithmetic = BytesPcodeArithmetic.forLanguage(language);\n\t\tbyte[] bytes = bytesArithmetic.fromConst(addr.getOffset(), pc.getNumBytes());\n\t\treturn editor.setVariable(computeAddressOfReturnAddress(), bytes);\n\t}\n\n\t@Override\n\tpublic T zext(T value, int length) {\n\t\tPcodeArithmetic<T> arithmetic = state.getArithmetic();\n\t\treturn arithmetic.unaryOp(PcodeOp.INT_ZEXT, length, (int) arithmetic.sizeOf(value), value);\n\t}\n}\n","sourceCodeStart":324,"sourceCodeEnd":355,"githubUrl":"https://github.com/NationalSecurityAgency/ghidra/blob/d5f144c24d6bc53c9cbf4448c6d11143e7696206/Ghidra/Debug/Debugger/src/main/java/ghidra/app/plugin/core/debug/stack/AbstractUnwoundFrame.java#L324-L355","documentation":"AbstractUnwoundFrame.setReturnAddress() writes the return address into the frame's program counter. It validates that the supplied address belongs to the frame's code address space (codeSpace) — i.e. the executable space — because the PC register must live there. An address from any other space (stack, register, external, etc.) is rejected with IllegalArgumentException(\"Return address must be in \" + codeSpace).","triggerScenarios":"Passing a stack address, a register-space address, or a constant/external-space address to setReturnAddress. Using an address from a different program/address space than the one the frame's language defines as code.","commonSituations":"Scripts that hand a computed stack pointer or a raw offset into setReturnAddress. Confusing the return-address location (code) with the return-value/stack location. Languages with non-standard code spaces.","solutions":["Pass an address in the frame's code space: verify addr.getAddressSpace().equals(codeSpace) first.","If you hold an offset, resolve it into the code space via the language's code address space before calling.","For non-code 'return' targets, reconsider whether setReturnAddress is the right API."],"exampleFix":"// before\nframe.setReturnAddress(editor, stackAddr); // throws: stackAddr not in codeSpace\n\n// after\nAddressSpace codeSpace = frame.getLanguage().getDefaultSpace(); // the code space\nif (!addr.getAddressSpace().equals(codeSpace)) {\n    throw new IllegalArgumentException(\"return address must be in code space\");\n}\nframe.setReturnAddress(editor, addr);","handlingStrategy":"validation","validationCode":"if (!addr.getAddressSpace().equals(codeSpace)) {\n    throw new IllegalArgumentException(\"return address must be in code space \" + codeSpace);\n}\nframe.setReturnAddress(editor, addr);","typeGuard":"public static boolean isInCodeSpace(Address addr, AddressSpace codeSpace) {\n    return addr != null && codeSpace != null && addr.getAddressSpace().equals(codeSpace);\n}","tryCatchPattern":"try {\n    frame.setReturnAddress(editor, addr);\n} catch (IllegalArgumentException e) {\n    if (e.getMessage().contains(\"Return address must be in\")) {\n        // resolve addr into the code space and retry\n    } else throw e;\n}","preventionTips":["Always pass a code-space address to setReturnAddress; the PC register lives there.","Resolve raw offsets into the language's code space before calling.","Distinguish return-address (code) from stack/value locations."],"tags":["stack-unwinding","validation","address-space","registers"],"backgroundTag":null,"analyzedSha":"d5f144c24d6bc53c9cbf4448c6d11143e7696206","analyzedAt":"2026-08-14T01:00:57.564Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}