diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java index a49acf89d0..9a8019a74f 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/FormatStringAnalyzer.java @@ -99,8 +99,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { return true; } - private void run(AddressSetView selection, TaskMonitor monitor) - throws CancelledException { + private void run(AddressSetView selection, TaskMonitor monitor) throws CancelledException { DefinedDataIterator dataIterator = DefinedDataIterator.definedStrings(currentProgram); Map stringsByAddress = new HashMap<>(); @@ -114,7 +113,8 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { FunctionIterator functionIterator = currentProgram.getListing().getFunctions(true); FunctionIterator externalIterator = currentProgram.getListing().getExternalFunctions(); - Iterator programFunctionIterator = IteratorUtils.chainedIterator(functionIterator,externalIterator); + Iterator programFunctionIterator = + IteratorUtils.chainedIterator(functionIterator, externalIterator); Map> namesToParameters = new HashMap<>(); Map namesToReturn = new HashMap<>(); @@ -124,22 +124,21 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { // Find variadic function names and their parameter data types for (Function function : IteratorUtils.asIterable(programFunctionIterator)) { String name = function.getName().strip(); - if (usesVariadicFormatString(function)) { - for (String variadicSubstring : VARIADIC_SUBSTRINGS) { - if (name.contains(variadicSubstring)) { - variadicFunctionNames.add(name); - namesToParameters.put(name, getParameters(function)); - namesToReturn.put(name, function.getReturnType()); - break; - } - } - } + if (usesVariadicFormatString(function)) { + for (String variadicSubstring : VARIADIC_SUBSTRINGS) { + if (name.contains(variadicSubstring)) { + variadicFunctionNames.add(name); + namesToParameters.put(name, getParameters(function)); + namesToReturn.put(name, function.getReturnType()); + break; + } + } + } monitor.checkCanceled(); } Iterator functionsToSearchIterator = selection != null - ? currentProgram.getFunctionManager() - .getFunctionsOverlapping(selection) + ? currentProgram.getFunctionManager().getFunctionsOverlapping(selection) : currentProgram.getFunctionManager().getFunctionsNoStubs(true); // Find functions that call variadic functions @@ -157,14 +156,11 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { } decompile(currentProgram, monitor, stringsByAddress, variadicFunctionNames, - namesToParameters, - namesToReturn, - toDecompile); + namesToParameters, namesToReturn, toDecompile); } private void decompile(Program program, TaskMonitor monitor, - Map stringsByAddress, - Set variadicFunctionNames, + Map stringsByAddress, Set variadicFunctionNames, Map> namesToParameters, Map namesToReturn, Set toDecompile) { @@ -187,11 +183,9 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { } private DecompilerCallback initDecompilerCallback(Program program, - Map stringsByAddress, - Set variadicFuncNames, Map> namesToParameters, - Map namesToReturn) { - return new DecompilerCallback<>(program, - new VariadicSignatureDecompileConfigurer()) { + Map stringsByAddress, Set variadicFuncNames, + Map> namesToParameters, Map namesToReturn) { + return new DecompilerCallback<>(program, new VariadicSignatureDecompileConfigurer()) { @Override public Void process(DecompileResults results, TaskMonitor tMonitor) throws Exception { if (results == null) { @@ -211,8 +205,8 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { pcodeOpASTs.add(pcodeAST); } } - List functionCallDataList = pcodeParser.parseFunctionForCallData( - pcodeOpASTs, stringsByAddress, variadicFuncNames); + List functionCallDataList = pcodeParser + .parseFunctionForCallData(pcodeOpASTs, stringsByAddress, variadicFuncNames); if (functionCallDataList != null && functionCallDataList.size() > 0) { overrideCallList(program, function, functionCallDataList, namesToParameters, namesToReturn); @@ -256,7 +250,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { // DecompInterface allows for control of decompilation processes @Override 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.openProgram(currentProgram); decompiler.setSimplificationStyle("normalize"); @@ -266,8 +260,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { } } - private ParameterDefinition[] parseParameters(Function function, - Address address, + private ParameterDefinition[] parseParameters(Function function, Address address, String callFunctionName, String formatString, Map> namesToParameters) { @@ -347,8 +340,7 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { private void overrideFunctionCall(Program program, Function function, Address address, String callFunctionName, String formatString, - Map> namesToParameters, - Map namesToReturn) { + Map> namesToParameters, Map namesToReturn) { if (formatString == null) { return; } @@ -361,14 +353,14 @@ public class FormatStringAnalyzer extends AbstractAnalyzer { try { if (createBookmarksEnabled) { BookmarkManager bookmark = program.getBookmarkManager(); - bookmark.setBookmark(address, BookmarkType.ANALYSIS, - "Function Signature Override", + bookmark.setBookmark(address, BookmarkType.ANALYSIS, "Function Signature Override", "Override for call to function " + callFunctionName); } HighFunctionDBUtil.writeOverride(function, address, functionSignature); } catch (InvalidInputException e) { - Msg.error(this, "Error: invalid input given to writeOverride()", e); + Msg.warn(this, + "Error applying override to " + address.toString() + ": " + e.getMessage()); } } diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/PcodeFunctionParser.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/PcodeFunctionParser.java index 573f35a6be..5dd6069e78 100644 --- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/PcodeFunctionParser.java +++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/string/variadic/PcodeFunctionParser.java @@ -19,12 +19,12 @@ import java.util.*; import ghidra.docking.settings.SettingsImpl; import ghidra.program.model.address.Address; -import ghidra.program.model.data.StringDataInstance; -import ghidra.program.model.data.StringDataType; +import ghidra.program.model.data.*; import ghidra.program.model.listing.*; import ghidra.program.model.mem.MemoryBufferImpl; import ghidra.program.model.pcode.PcodeOpAST; import ghidra.program.model.pcode.Varnode; +import ghidra.program.model.symbol.SourceType; /** * Class for parsing functions' Pcode representations and finding variadic @@ -84,7 +84,7 @@ public class PcodeFunctionParser { boolean hasDefinedFormatString = searchForVariadicCallData(ast, addressToCandidateData, functionCallDataList, functionName); 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 // and we are calling a variadic function, parse the String to determine // whether it's a format String. - private void searchForHiddenFormatStrings(PcodeOpAST ast, - List functionCallDataList, String functionName) { + private void searchForHiddenFormatStrings(PcodeOpAST callOp, + List functionCallDataList, Function function) { - Varnode[] inputs = ast.getInputs(); - // Initialize i = 1 to skip first input + Varnode[] inputs = callOp.getInputs(); + // Initialize i = 1 to skip first input, which is the call target for (int i = 1; i < inputs.length; ++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) { continue; } if (formatStringCandidate.contains("%")) { - functionCallDataList.add(new FunctionCallData(ast.getSeqnum().getTarget(), - functionName, formatStringCandidate)); + functionCallDataList.add(new FunctionCallData(callOp.getSeqnum().getTarget(), + function.getName(), formatStringCandidate)); } break; } @@ -145,9 +153,10 @@ public class PcodeFunctionParser { * Looks at bytes at given address and converts to format String * * @param address Address of format String + * @param pointer Pointer "type" of string * @return format String */ - private String findFormatString(Address address) { + private String findFormatString(Address address, Pointer pointer) { if (!address.getAddressSpace().isConstantSpace()) { return null; @@ -159,9 +168,11 @@ public class PcodeFunctionParser { MemoryBufferImpl memoryBuffer = new MemoryBufferImpl(this.program.getMemory(), ramSpaceAddress); - StringDataInstance stringDataInstance = StringDataInstance - .getStringDataInstance(new StringDataType(), memoryBuffer, SettingsImpl.NO_SETTINGS, - BUFFER_LENGTH); + DataType charType = pointer.getDataType(); + //StringDataInstace.getStringDataInstance checks that charType is appropriate + //and returns StringDataInstace.NULL_INSTANCE if not + StringDataInstance stringDataInstance = StringDataInstance.getStringDataInstance(charType, + memoryBuffer, SettingsImpl.NO_SETTINGS, BUFFER_LENGTH); String stringValue = stringDataInstance.getStringValue(); if (stringValue == null) { return null;