mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-05-30 09:15:43 +08:00
classrecovery: avoid AddressOutOfBoundsException on non-pointer p-code constants
Add a best-effort tryToAddr helper that catches AddressOutOfBoundsException and filters unmapped addresses, and use it from getAssignedAddressFromPcode() to prevent RecoverClassesFromRTTIScript from aborting on invalid address candidates.
This commit is contained in:
committed by
ghidra007
parent
e31df74ca4
commit
f16f7b650e
+41
-24
@@ -20,6 +20,8 @@ import ghidra.app.decompiler.*;
|
||||
import ghidra.app.decompiler.component.DecompilerUtils;
|
||||
import ghidra.framework.plugintool.ServiceProvider;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressSpace;
|
||||
import ghidra.program.model.address.AddressOutOfBoundsException;
|
||||
import ghidra.program.model.data.DataType;
|
||||
import ghidra.program.model.data.ParameterDefinition;
|
||||
import ghidra.program.model.listing.Function;
|
||||
@@ -226,42 +228,32 @@ public class DecompilerScriptUtils {
|
||||
decompInterface.dispose();
|
||||
}
|
||||
|
||||
/**
|
||||
* Best-effort extraction of an address candidate from decompiler p-code.
|
||||
* Returns {@code null} if the candidate is invalid or not mapped in program memory.
|
||||
*/
|
||||
public Address getAssignedAddressFromPcode(Varnode storedValue) {
|
||||
|
||||
long addressOffset;
|
||||
if (storedValue.isConstant()) {
|
||||
addressOffset = storedValue.getOffset();
|
||||
Address possibleAddress = toAddr(addressOffset);
|
||||
if (possibleAddress == null || !program.getMemory().contains(possibleAddress)) {
|
||||
return null;
|
||||
}
|
||||
return possibleAddress;
|
||||
return tryToAddr(storedValue.getOffset());
|
||||
}
|
||||
|
||||
PcodeOp valuePcodeOp = storedValue.getDef();
|
||||
|
||||
if (valuePcodeOp == null) {
|
||||
PcodeOp op = storedValue.getDef();
|
||||
if (op == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (valuePcodeOp.getOpcode() == PcodeOp.CAST || valuePcodeOp.getOpcode() == PcodeOp.COPY) {
|
||||
|
||||
Varnode constantVarnode = valuePcodeOp.getInput(0);
|
||||
return getAssignedAddressFromPcode(constantVarnode);
|
||||
|
||||
int opcode = op.getOpcode();
|
||||
if (opcode == PcodeOp.CAST || opcode == PcodeOp.COPY) {
|
||||
return getAssignedAddressFromPcode(op.getInput(0));
|
||||
}
|
||||
else if (valuePcodeOp.getOpcode() != PcodeOp.PTRSUB) {
|
||||
|
||||
if (opcode != PcodeOp.PTRSUB) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// don't need to check isConst bc always is
|
||||
Varnode constantVarnode = valuePcodeOp.getInput(1);
|
||||
addressOffset = constantVarnode.getOffset();
|
||||
Address possibleAddress = toAddr(addressOffset);
|
||||
if (possibleAddress == null || !program.getMemory().contains(possibleAddress)) {
|
||||
return null;
|
||||
}
|
||||
return possibleAddress;
|
||||
// PTRSUB input(1) is always a constant offset (but may not represent a valid program address)
|
||||
return tryToAddr(op.getInput(1).getOffset());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -302,4 +294,29 @@ public class DecompilerScriptUtils {
|
||||
return program.getAddressFactory().getDefaultAddressSpace().getAddress(offset);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to convert the given offset to an {@link Address} in the default address space.
|
||||
* <p>
|
||||
* Decompiler pcode may surface non-pointer constants that heuristics attempt to interpret
|
||||
* as addresses; this method performs a best-effort conversion and safely ignores
|
||||
* invalid or unmapped candidates.
|
||||
* <p>
|
||||
* Unlike {@link #toAddr(long)}, this method returns {@code null} if the resulting address is not
|
||||
* contained in the program's memory or if the offset is out of bounds.
|
||||
*
|
||||
* @param offset the offset to convert
|
||||
* @return the address for the given offset, or {@code null} if the offset cannot be represented
|
||||
* as a valid address in the program's memory
|
||||
*/
|
||||
public final Address tryToAddr(long offset) {
|
||||
AddressSpace space = program.getAddressFactory().getDefaultAddressSpace();
|
||||
try {
|
||||
Address addr = space.getAddress(offset);
|
||||
return program.getMemory().contains(addr) ? addr : null;
|
||||
}
|
||||
catch (AddressOutOfBoundsException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user