GP-2016 addressing code review suggestions

GP-2016_short_wide_character_format_strings
This commit is contained in:
James 2022-05-11 13:23:17 -04:00
parent 37a8ffb492
commit c6f174dffb
2 changed files with 52 additions and 49 deletions

View file

@ -99,8 +99,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
return true; return true;
} }
private void run(AddressSetView selection, TaskMonitor monitor) private void run(AddressSetView selection, TaskMonitor monitor) throws CancelledException {
throws CancelledException {
DefinedDataIterator dataIterator = DefinedDataIterator.definedStrings(currentProgram); DefinedDataIterator dataIterator = DefinedDataIterator.definedStrings(currentProgram);
Map<Address, Data> stringsByAddress = new HashMap<>(); Map<Address, Data> stringsByAddress = new HashMap<>();
@ -114,7 +113,8 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
FunctionIterator functionIterator = currentProgram.getListing().getFunctions(true); FunctionIterator functionIterator = currentProgram.getListing().getFunctions(true);
FunctionIterator externalIterator = currentProgram.getListing().getExternalFunctions(); FunctionIterator externalIterator = currentProgram.getListing().getExternalFunctions();
Iterator<Function> programFunctionIterator = IteratorUtils.chainedIterator(functionIterator,externalIterator); Iterator<Function> programFunctionIterator =
IteratorUtils.chainedIterator(functionIterator, externalIterator);
Map<String, List<DataType>> namesToParameters = new HashMap<>(); Map<String, List<DataType>> namesToParameters = new HashMap<>();
Map<String, DataType> namesToReturn = new HashMap<>(); Map<String, DataType> namesToReturn = new HashMap<>();
@ -124,22 +124,21 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
// Find variadic function names and their parameter data types // Find variadic function names and their parameter data types
for (Function function : IteratorUtils.asIterable(programFunctionIterator)) { for (Function function : IteratorUtils.asIterable(programFunctionIterator)) {
String name = function.getName().strip(); String name = function.getName().strip();
if (usesVariadicFormatString(function)) { if (usesVariadicFormatString(function)) {
for (String variadicSubstring : VARIADIC_SUBSTRINGS) { for (String variadicSubstring : VARIADIC_SUBSTRINGS) {
if (name.contains(variadicSubstring)) { if (name.contains(variadicSubstring)) {
variadicFunctionNames.add(name); variadicFunctionNames.add(name);
namesToParameters.put(name, getParameters(function)); namesToParameters.put(name, getParameters(function));
namesToReturn.put(name, function.getReturnType()); namesToReturn.put(name, function.getReturnType());
break; break;
} }
} }
} }
monitor.checkCanceled(); monitor.checkCanceled();
} }
Iterator<Function> functionsToSearchIterator = selection != null Iterator<Function> functionsToSearchIterator = selection != null
? currentProgram.getFunctionManager() ? currentProgram.getFunctionManager().getFunctionsOverlapping(selection)
.getFunctionsOverlapping(selection)
: currentProgram.getFunctionManager().getFunctionsNoStubs(true); : currentProgram.getFunctionManager().getFunctionsNoStubs(true);
// Find functions that call variadic functions // Find functions that call variadic functions
@ -157,14 +156,11 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
} }
decompile(currentProgram, monitor, stringsByAddress, variadicFunctionNames, decompile(currentProgram, monitor, stringsByAddress, variadicFunctionNames,
namesToParameters, namesToParameters, namesToReturn, toDecompile);
namesToReturn,
toDecompile);
} }
private void decompile(Program program, TaskMonitor monitor, private void decompile(Program program, TaskMonitor monitor,
Map<Address, Data> stringsByAddress, Map<Address, Data> stringsByAddress, Set<String> variadicFunctionNames,
Set<String> variadicFunctionNames,
Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn, Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn,
Set<Function> toDecompile) { Set<Function> toDecompile) {
@ -187,11 +183,9 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
} }
private DecompilerCallback<Void> initDecompilerCallback(Program program, private DecompilerCallback<Void> initDecompilerCallback(Program program,
Map<Address, Data> stringsByAddress, Map<Address, Data> stringsByAddress, Set<String> variadicFuncNames,
Set<String> variadicFuncNames, Map<String, List<DataType>> namesToParameters, Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn) {
Map<String, DataType> namesToReturn) { return new DecompilerCallback<>(program, new VariadicSignatureDecompileConfigurer()) {
return new DecompilerCallback<>(program,
new VariadicSignatureDecompileConfigurer()) {
@Override @Override
public Void process(DecompileResults results, TaskMonitor tMonitor) throws Exception { public Void process(DecompileResults results, TaskMonitor tMonitor) throws Exception {
if (results == null) { if (results == null) {
@ -211,8 +205,8 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
pcodeOpASTs.add(pcodeAST); pcodeOpASTs.add(pcodeAST);
} }
} }
List<FunctionCallData> functionCallDataList = pcodeParser.parseFunctionForCallData( List<FunctionCallData> functionCallDataList = pcodeParser
pcodeOpASTs, stringsByAddress, variadicFuncNames); .parseFunctionForCallData(pcodeOpASTs, stringsByAddress, variadicFuncNames);
if (functionCallDataList != null && functionCallDataList.size() > 0) { if (functionCallDataList != null && functionCallDataList.size() > 0) {
overrideCallList(program, function, functionCallDataList, namesToParameters, overrideCallList(program, function, functionCallDataList, namesToParameters,
namesToReturn); namesToReturn);
@ -256,7 +250,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
// DecompInterface allows for control of decompilation processes // DecompInterface allows for control of decompilation processes
@Override @Override
public void configure(DecompInterface decompiler) { public void configure(DecompInterface decompiler) {
decompiler.toggleCCode(true); // Produce C code decompiler.toggleCCode(false); //only need syntax tree
decompiler.toggleSyntaxTree(true); // Produce syntax tree decompiler.toggleSyntaxTree(true); // Produce syntax tree
decompiler.openProgram(currentProgram); decompiler.openProgram(currentProgram);
decompiler.setSimplificationStyle("normalize"); decompiler.setSimplificationStyle("normalize");
@ -266,8 +260,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
} }
} }
private ParameterDefinition[] parseParameters(Function function, private ParameterDefinition[] parseParameters(Function function, Address address,
Address address,
String callFunctionName, String formatString, String callFunctionName, String formatString,
Map<String, List<DataType>> namesToParameters) { Map<String, List<DataType>> namesToParameters) {
@ -347,8 +340,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
private void overrideFunctionCall(Program program, Function function, Address address, private void overrideFunctionCall(Program program, Function function, Address address,
String callFunctionName, String formatString, String callFunctionName, String formatString,
Map<String, List<DataType>> namesToParameters, Map<String, List<DataType>> namesToParameters, Map<String, DataType> namesToReturn) {
Map<String, DataType> namesToReturn) {
if (formatString == null) { if (formatString == null) {
return; return;
} }
@ -361,14 +353,14 @@ public class FormatStringAnalyzer extends AbstractAnalyzer {
try { try {
if (createBookmarksEnabled) { if (createBookmarksEnabled) {
BookmarkManager bookmark = program.getBookmarkManager(); BookmarkManager bookmark = program.getBookmarkManager();
bookmark.setBookmark(address, BookmarkType.ANALYSIS, bookmark.setBookmark(address, BookmarkType.ANALYSIS, "Function Signature Override",
"Function Signature Override",
"Override for call to function " + callFunctionName); "Override for call to function " + callFunctionName);
} }
HighFunctionDBUtil.writeOverride(function, address, functionSignature); HighFunctionDBUtil.writeOverride(function, address, functionSignature);
} }
catch (InvalidInputException e) { catch (InvalidInputException e) {
Msg.error(this, "Error: invalid input given to writeOverride()", e); Msg.warn(this,
"Error applying override to " + address.toString() + ": " + e.getMessage());
} }
} }

View file

@ -19,12 +19,12 @@ import java.util.*;
import ghidra.docking.settings.SettingsImpl; import ghidra.docking.settings.SettingsImpl;
import ghidra.program.model.address.Address; import ghidra.program.model.address.Address;
import ghidra.program.model.data.StringDataInstance; import ghidra.program.model.data.*;
import ghidra.program.model.data.StringDataType;
import ghidra.program.model.listing.*; import ghidra.program.model.listing.*;
import ghidra.program.model.mem.MemoryBufferImpl; import ghidra.program.model.mem.MemoryBufferImpl;
import ghidra.program.model.pcode.PcodeOpAST; import ghidra.program.model.pcode.PcodeOpAST;
import ghidra.program.model.pcode.Varnode; import ghidra.program.model.pcode.Varnode;
import ghidra.program.model.symbol.SourceType;
/** /**
* Class for parsing functions' Pcode representations and finding variadic * Class for parsing functions' Pcode representations and finding variadic
@ -84,7 +84,7 @@ public class PcodeFunctionParser {
boolean hasDefinedFormatString = searchForVariadicCallData(ast, boolean hasDefinedFormatString = searchForVariadicCallData(ast,
addressToCandidateData, functionCallDataList, functionName); addressToCandidateData, functionCallDataList, functionName);
if (!hasDefinedFormatString) { if (!hasDefinedFormatString) {
searchForHiddenFormatStrings(ast, functionCallDataList, functionName); searchForHiddenFormatStrings(ast, functionCallDataList, function);
} }
} }
} }
@ -116,20 +116,28 @@ public class PcodeFunctionParser {
// If addrToCandidateData doesn't have format String data for this call // If addrToCandidateData doesn't have format String data for this call
// and we are calling a variadic function, parse the String to determine // and we are calling a variadic function, parse the String to determine
// whether it's a format String. // whether it's a format String.
private void searchForHiddenFormatStrings(PcodeOpAST ast, private void searchForHiddenFormatStrings(PcodeOpAST callOp,
List<FunctionCallData> functionCallDataList, String functionName) { List<FunctionCallData> functionCallDataList, Function function) {
Varnode[] inputs = ast.getInputs(); Varnode[] inputs = callOp.getInputs();
// Initialize i = 1 to skip first input // Initialize i = 1 to skip first input, which is the call target
for (int i = 1; i < inputs.length; ++i) { for (int i = 1; i < inputs.length; ++i) {
Varnode v = inputs[i]; Varnode v = inputs[i];
String formatStringCandidate = findFormatString(v.getAddress()); Parameter param = function.getParameter(i - 1);
if (param == null || param.getSource().equals(SourceType.DEFAULT)) {
continue;
}
DataType type = param.getDataType();
if ((type == null) || !(type instanceof Pointer)) {
continue;
}
String formatStringCandidate = findFormatString(v.getAddress(), (Pointer) type);
if (formatStringCandidate == null) { if (formatStringCandidate == null) {
continue; continue;
} }
if (formatStringCandidate.contains("%")) { if (formatStringCandidate.contains("%")) {
functionCallDataList.add(new FunctionCallData(ast.getSeqnum().getTarget(), functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(),
functionName, formatStringCandidate)); function.getName(), formatStringCandidate));
} }
break; break;
} }
@ -145,9 +153,10 @@ public class PcodeFunctionParser {
* Looks at bytes at given address and converts to format String * Looks at bytes at given address and converts to format String
* *
* @param address Address of format String * @param address Address of format String
* @param pointer Pointer "type" of string
* @return format String * @return format String
*/ */
private String findFormatString(Address address) { private String findFormatString(Address address, Pointer pointer) {
if (!address.getAddressSpace().isConstantSpace()) { if (!address.getAddressSpace().isConstantSpace()) {
return null; return null;
@ -159,9 +168,11 @@ public class PcodeFunctionParser {
MemoryBufferImpl memoryBuffer = MemoryBufferImpl memoryBuffer =
new MemoryBufferImpl(this.program.getMemory(), ramSpaceAddress); new MemoryBufferImpl(this.program.getMemory(), ramSpaceAddress);
StringDataInstance stringDataInstance = StringDataInstance DataType charType = pointer.getDataType();
.getStringDataInstance(new StringDataType(), memoryBuffer, SettingsImpl.NO_SETTINGS, //StringDataInstace.getStringDataInstance checks that charType is appropriate
BUFFER_LENGTH); //and returns StringDataInstace.NULL_INSTANCE if not
StringDataInstance stringDataInstance = StringDataInstance.getStringDataInstance(charType,
memoryBuffer, SettingsImpl.NO_SETTINGS, BUFFER_LENGTH);
String stringValue = stringDataInstance.getStringValue(); String stringValue = stringDataInstance.getStringValue();
if (stringValue == null) { if (stringValue == null) {
return null; return null;