From dc1b9ae900092dfcaf0e4314fdf0bc28a1078a0a Mon Sep 17 00:00:00 2001
From: d-millar <33498836+d-millar@users.noreply.github.com>
Date: Wed, 15 Jan 2025 16:59:51 -0500
Subject: [PATCH] GP-5238: from review GP-5238: adding a sanity check GP-5238:
allow switching between frames GP-5238: comments GP-5238: fix for hv matches
GP-5238: chooser for cutsom query GP-5238: delta working? GP-5238: first pass
at delta GP-5238: oops GP-5238: key bindings GP-5238: better options + docs
---
.../DecompilerTaint/DecompilerTaint.html | 19 +++-
.../decompiler/taint/AbstractTaintState.java | 99 +++++++++++++++----
.../core/decompiler/taint/TaintLabel.java | 7 +-
.../core/decompiler/taint/TaintOptions.java | 35 ++++---
.../core/decompiler/taint/TaintPlugin.java | 69 +++++++++++--
.../core/decompiler/taint/TaintProvider.java | 29 +++---
.../decompiler/taint/TaintQueryResult.java | 17 ++--
.../core/decompiler/taint/TaintService.java | 4 +-
.../core/decompiler/taint/TaintState.java | 10 +-
.../actions/TaintAbstractQueryAction.java | 6 +-
.../taint/actions/TaintQueryAction.java | 4 +-
.../taint/actions/TaintQueryCustomAction.java | 7 +-
.../actions/TaintQueryDefaultAction.java | 7 +-
.../taint/ctadl/TaintStateCTADL.java | 22 ++++-
.../SarifTaintCodeFlowResultHandler.java | 6 +-
.../taint/sarif/SarifTaintResultHandler.java | 76 +++++++++++++-
.../decompiler/taint/DecompilerTaintTest.java | 5 +-
.../src/main/java/sarif/SarifPlugin.java | 6 +-
.../Sarif/src/main/java/sarif/SarifUtils.java | 41 +++++---
.../main/java/sarif/model/SarifDataFrame.java | 50 +++++-----
20 files changed, 393 insertions(+), 126 deletions(-)
diff --git a/Ghidra/Features/DecompilerDependent/src/main/help/help/topics/DecompilerTaint/DecompilerTaint.html b/Ghidra/Features/DecompilerDependent/src/main/help/help/topics/DecompilerTaint/DecompilerTaint.html
index 3868a263b4..994eec89de 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/help/help/topics/DecompilerTaint/DecompilerTaint.html
+++ b/Ghidra/Features/DecompilerDependent/src/main/help/help/topics/DecompilerTaint/DecompilerTaint.html
@@ -124,6 +124,17 @@
+
+
+
+ May be "forward", "backward", "all", or blank. Forward computes all source-to-sink
+ slices, backward sink-to-source slices, and all both. Blank chooses source-to-sink
+ or sink-to-source based on whether the number of sources or the number of sinks is
+ greater.
+
+
+
@@ -144,15 +155,17 @@
- Currently always "sarif+all".
+ Describes the output set. Currently default to "sarif+all", which should be appropriate
+ for most cases. Other options are "sarif" (output paths only), "sarif+instructions"
+ (output paths and instructions), and "sarif+graphs" (output paths and graphs).
- Use all access paths for sink/source variables.
+ Use all access paths, including field references, for sink/source variables.
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java
index 15ed6489aa..725821c531 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/AbstractTaintState.java
@@ -51,7 +51,9 @@ public abstract class AbstractTaintState implements TaintState {
private AddressSet taintAddressSet = new AddressSet();
private Map> taintVarnodeMap = new HashMap<>();
- /// private QueryDataFrame currentQueryData;
+ private AddressSet deltaAddressSet = new AddressSet();
+ private Map> deltaVarnodeMap = new HashMap<>();
+
private SarifSchema210 currentQueryData;
protected TaintOptions taintOptions;
@@ -59,6 +61,8 @@ public abstract class AbstractTaintState implements TaintState {
private boolean cancellation;
+ private TaskType taskType;
+
public AbstractTaintState(TaintPlugin plugin) {
this.plugin = plugin;
}
@@ -281,10 +285,15 @@ public abstract class AbstractTaintState implements TaintState {
if (queryType.equals(QueryType.SRCSINK) || queryType.equals(QueryType.CUSTOM)) {
// The datalog that specifies the query.
- if (queryType.equals(QueryType.CUSTOM)) {
+ if (queryType.equals(QueryType.CUSTOM)) {
Path queryPath = Path.of(taintOptions.getTaintOutputDirectory(),
taintOptions.getTaintQueryDLName());
- queryFile = queryPath.toFile();
+ GhidraFileChooser chooser = new GhidraFileChooser(plugin.getProvider().getComponent());
+ chooser.setCurrentDirectory(queryPath.toFile());
+ queryFile = chooser.getSelectedFile();
+ if (queryFile == null) {
+ return false;
+ }
}
param_list.add(queryFile.getAbsolutePath());
}
@@ -296,12 +305,8 @@ public abstract class AbstractTaintState implements TaintState {
pb.redirectError(Redirect.INHERIT);
Process p = pb.start();
- switch (taintOptions.getTaintOutputForm()) {
- case "sarif+all":
- readQueryResultsIntoDataFrame(program, p.getInputStream());
- break;
- default:
- }
+ readQueryResultsIntoDataFrame(program, p.getInputStream());
+
// We wait for the process to finish after starting to read the input stream,
// otherwise waitFor() might wait for a running process trying to write to
// a filled output buffer. This causes waitFor() to wait indefinitely.
@@ -401,25 +406,54 @@ public abstract class AbstractTaintState implements TaintState {
@Override
public void setTaintAddressSet(AddressSet aset) {
- taintAddressSet = aset;
+ switch (taskType) {
+ case SET_TAINT -> taintAddressSet = aset;
+ case SET_DELTA -> deltaAddressSet = aset;
+ case APPLY_DELTA -> {
+ // Empty
+ }
+ }
}
@Override
public AddressSet getTaintAddressSet() {
- return taintAddressSet;
+ return switch(taskType) {
+ case SET_TAINT -> taintAddressSet;
+ case SET_DELTA -> deltaAddressSet;
+ case APPLY_DELTA -> taintAddressSet.subtract(deltaAddressSet);
+ default -> new AddressSet();
+ };
+ }
+
+ @Override
+ public void setTaskType(TaskType taskType) {
+ this.taskType = taskType;
}
@Override
public void augmentAddressSet(ClangToken token) {
Address addr = token.getMinAddress();
- if (addr != null) {
- taintAddressSet.add(addr);
+ if (addr == null) {
+ return;
+ }
+ switch (taskType) {
+ case SET_TAINT -> taintAddressSet.add(addr);
+ case SET_DELTA -> deltaAddressSet.add(addr);
+ case APPLY_DELTA -> {
+ if (!deltaAddressSet.contains(addr)) {
+ taintAddressSet.add(addr);
+ }
+ }
}
}
@Override
- public void setTaintVarnodeMap(Map> vmap) {
- taintVarnodeMap = vmap;
+ public void setTaintVarnodeMap(Map> vmap, TaskType delta) {
+ switch (delta) {
+ case SET_TAINT -> taintVarnodeMap = vmap;
+ case SET_DELTA -> deltaVarnodeMap = vmap;
+ case APPLY_DELTA -> taintVarnodeMap = vmap;
+ }
}
@Override
@@ -427,11 +461,42 @@ public abstract class AbstractTaintState implements TaintState {
return taintVarnodeMap;
}
+ @Override
+ public Set getQuerySet(Address key) {
+ Set set = new HashSet<>();
+ switch (taskType) {
+ case SET_TAINT -> set = taintVarnodeMap.get(key);
+ case SET_DELTA -> set = deltaVarnodeMap.get(key);
+ case APPLY_DELTA -> {
+ Set A = taintVarnodeMap.get(key);
+ if (A != null) {
+ set.addAll(A);
+ }
+ Set B = deltaVarnodeMap.get(key);
+ if (A != null) {
+ set.removeAll(B);
+ }
+ }
+ }
+ return set;
+ }
+
@Override
public void clearTaint() {
Msg.info(this, "TaintState: clearTaint() - clearing address set");
- taintAddressSet.clear();
- taintVarnodeMap.clear();
+ switch (taskType) {
+ case SET_TAINT -> {
+ taintAddressSet.clear();
+ taintVarnodeMap.clear();
+ }
+ case SET_DELTA -> {
+ deltaAddressSet.clear();
+ deltaVarnodeMap.clear();
+ }
+ case APPLY_DELTA -> {
+ // EMPTY
+ }
+ }
}
@Override
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintLabel.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintLabel.java
index 25a3be343a..c7c8bd90a3 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintLabel.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintLabel.java
@@ -51,8 +51,11 @@ public class TaintLabel {
}
Varnode exactSpot = token.getVarnode();
- if (exactSpot != null) { // The user pointed at a particular usage, not just the vardecl
- highVar = hfun.splitOutMergeGroup(exactSpot.getHigh(), exactSpot);
+ if (exactSpot != null) { // The user pointed at a particular usage, not just the vardecl
+ HighVariable high = exactSpot.getHigh();
+ if (high instanceof HighLocal) {
+ highVar = hfun.splitOutMergeGroup(high, exactSpot);
+ }
}
String fn = token instanceof ClangFuncNameToken ftoken ? ftoken.getText()
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java
index d9f3b26f6c..1f32ddf8b6 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintOptions.java
@@ -18,7 +18,7 @@ package ghidra.app.plugin.core.decompiler.taint;
import java.awt.Color;
import generic.theme.GColor;
-import ghidra.app.plugin.core.decompiler.taint.TaintPlugin.Highlighter;
+import ghidra.app.plugin.core.decompiler.taint.TaintPlugin.*;
import ghidra.app.util.HelpTopics;
import ghidra.framework.options.ToolOptions;
import ghidra.framework.plugintool.Plugin;
@@ -45,12 +45,13 @@ public class TaintOptions {
/* The default name of the index database file. */
public final static String OP_KEY_TAINT_DB = "Taint.Query.Index";
+ public final static String OP_KEY_TAINT_QUERY_DIRECTION = "Taint.Force Direction";
public final static String OP_KEY_TAINT_QUERY_OUTPUT_FORM = "Taint.Output Format";
/* Color used in the decompiler to highlight taint. */
public final static String TAINT_HIGHLIGHT = "Taint.Highlight Color";
/* How to apply highlight taint. */
public final static String TAINT_HIGHLIGHT_STYLE = "Taint.Highlight Style";
- public final static String TAINT_ALL_ACCESS = "Taint.Use all access paths";
+ public final static String TAINT_ALL_ACCESS = "Taint.Match on Fields";
private final static Boolean TAINT_ALL_ACCESS_PATHS = true;
public final static String DEFAULT_TAINT_ENGINE_PATH = "";
@@ -60,7 +61,6 @@ public class TaintOptions {
/* this is the text code that contains the datalog query the plugin writes. */
public final static String DEFAULT_TAINT_QUERY = "taintquery.dl";
public final static String DEFAULT_TAINT_DB = "ctadlir.db";
- public final static String DEFAULT_TAINT_OUTPUT_FORM = "sarif+all";
public final static Boolean DEFAULT_GET_PATHS = true;
@@ -75,7 +75,8 @@ public class TaintOptions {
private String taintQuery;
private String taintDB;
- private String taintQueryOutputForm;
+ private TaintDirection taintQueryDirection;
+ private TaintFormat taintQueryOutputForm;
private Highlighter taintHighlightStyle;
private Color taintHighlightColor;
@@ -110,7 +111,8 @@ public class TaintOptions {
taintOutputDir = DEFAULT_TAINT_OUTPUT_DIR;
taintQuery = DEFAULT_TAINT_QUERY;
taintDB = DEFAULT_TAINT_DB;
- taintQueryOutputForm = DEFAULT_TAINT_OUTPUT_FORM;
+ taintQueryOutputForm = TaintFormat.ALL;
+ taintQueryDirection = TaintDirection.DEFAULT;
taintUseAllAccess = TAINT_ALL_ACCESS_PATHS;
}
@@ -125,7 +127,7 @@ public class TaintOptions {
*/
public void registerOptions(Plugin ownerPlugin, ToolOptions opt, Program program) {
- opt.registerOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, DEFAULT_TAINT_OUTPUT_FORM,
+ opt.registerOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, TaintFormat.ALL,
new HelpLocation(HelpTopics.DECOMPILER, "Taint Output Type"),
"The type of Source-Sink query output (e.g., sarif, summary, text");
@@ -181,7 +183,8 @@ public class TaintOptions {
taintOutputDir = opt.getString(OP_KEY_TAINT_OUTPUT_DIR, "");
taintDB = opt.getString(OP_KEY_TAINT_DB, "");
- taintQueryOutputForm = opt.getString(OP_KEY_TAINT_QUERY_OUTPUT_FORM, "");
+ taintQueryDirection = opt.getEnum(OP_KEY_TAINT_QUERY_DIRECTION, TaintDirection.DEFAULT);
+ taintQueryOutputForm = opt.getEnum(OP_KEY_TAINT_QUERY_OUTPUT_FORM, TaintFormat.ALL);
taintHighlightStyle = opt.getEnum(TAINT_HIGHLIGHT_STYLE, TAINT_HIGHLIGHT_STYLE_DEFAULT);
taintHighlightColor = opt.getColor(TAINT_HIGHLIGHT, TAINT_HIGHLIGHT_COLOR);
@@ -189,7 +192,7 @@ public class TaintOptions {
}
- public String getTaintOutputForm() {
+ public TaintFormat getTaintOutputForm() {
return taintQueryOutputForm;
}
@@ -233,13 +236,17 @@ public class TaintOptions {
return taintHighlightStyle;
}
+ public TaintDirection getTaintDirection() {
+ return taintQueryDirection;
+ }
+
public Boolean getTaintUseAllAccess() {
return taintUseAllAccess;
}
- public void setTaintOutputForm(String form) {
+ public void setTaintOutputForm(TaintFormat form) {
this.taintQueryOutputForm = form;
- taintProvider.setOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, form);
+ taintProvider.setOption(OP_KEY_TAINT_QUERY_OUTPUT_FORM, form.getOptionString());
}
public void setTaintFactsDirectory(String path) {
@@ -269,12 +276,16 @@ public class TaintOptions {
public void setTaintHighlightStyle(Highlighter style) {
this.taintHighlightStyle = style;
- taintProvider.setOption(TAINT_HIGHLIGHT_STYLE, style.name());
+ taintProvider.setOption(TAINT_HIGHLIGHT_STYLE, style.getOptionString());
taintProvider.changeHighlighter(style);
}
+ public void setTaintDirection(TaintDirection direction) {
+ this.taintQueryDirection = direction;
+ taintProvider.setOption(OP_KEY_TAINT_QUERY_DIRECTION, direction.getOptionString());
+ }
+
public void setTaintAllAccess(Boolean allAccess) {
this.taintUseAllAccess = allAccess;
- taintProvider.setAllAccess(TAINT_ALL_ACCESS, allAccess);
}
}
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintPlugin.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintPlugin.java
index 6fb111c88f..00e7ba157e 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintPlugin.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintPlugin.java
@@ -34,6 +34,7 @@ import ghidra.app.plugin.PluginCategoryNames;
import ghidra.app.plugin.ProgramPlugin;
import ghidra.app.plugin.core.decompile.DecompilerProvider;
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
+import ghidra.app.plugin.core.decompiler.taint.TaintState.TaskType;
import ghidra.app.script.GhidraScript;
import ghidra.app.script.GhidraState;
import ghidra.app.services.ConsoleService;
@@ -89,16 +90,66 @@ public class TaintPlugin extends ProgramPlugin implements TaintService {
private TaintDecompilerMarginProvider taintDecompMarginProvider;
public static enum Highlighter {
- ALL("Taint Variables"), LABELS("Taint Labels"), DEFAULT("Default");
+ ALL("all", "variables"), LABELS("labels", "labels"), DEFAULT("default", "default");
- private String name;
+ private String label;
+ private String optionString;
- private Highlighter(String name) {
- this.name = name;
+ private Highlighter(String optString, String label) {
+ this.label = label;
+ this.optionString = optString;
}
- public String getName() {
- return this.name;
+ public String getOptionString() {
+ return optionString;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+ }
+
+ public static enum TaintFormat {
+ ALL("all", "sarif+all"), GRAPHS("graphs", "sarif+graphs"),
+ INSTS("insts", "sarif+instructions"), PATHS("paths", "sarif");
+
+ private String label;
+ private String optionString;
+
+ private TaintFormat(String optString, String label) {
+ this.label = label;
+ this.optionString = optString;
+ }
+
+ public String getOptionString() {
+ return optionString;
+ }
+
+ @Override
+ public String toString() {
+ return label;
+ }
+ }
+
+ public static enum TaintDirection {
+ BOTH("all", "both"), FORWARD("fwd", "forward"), BACKWARD("bwd", "backward"), DEFAULT("auto", "auto");
+
+ private String label;
+ private String optionString;
+
+ private TaintDirection(String optString, String label) {
+ this.label = label;
+ this.optionString = optString;
+ }
+
+ public String getOptionString() {
+ return optionString;
+ }
+
+ @Override
+ public String toString() {
+ return label;
}
}
@@ -638,12 +689,12 @@ public class TaintPlugin extends ProgramPlugin implements TaintService {
}
@Override
- public void setVarnodeMap(Map> vmap, boolean clear) {
+ public void setVarnodeMap(Map> vmap, boolean clear, TaskType delta) {
if (clear) {
taintProvider.clearTaint();
}
- state.setTaintVarnodeMap(vmap);
- taintProvider.setTaint();
+ state.setTaintVarnodeMap(vmap, delta);
+ taintProvider.setTaint(delta);
}
@Override
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintProvider.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintProvider.java
index ce63ee2033..34b605fdbe 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintProvider.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintProvider.java
@@ -34,6 +34,7 @@ import ghidra.app.nav.Navigatable;
import ghidra.app.plugin.core.decompile.DecompilerActionContext;
import ghidra.app.plugin.core.decompile.DecompilerProvider;
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin.Highlighter;
+import ghidra.app.plugin.core.decompiler.taint.TaintState.TaskType;
import ghidra.app.plugin.core.decompiler.taint.actions.*;
import ghidra.app.services.CodeViewerService;
import ghidra.framework.options.OptionsChangeListener;
@@ -64,8 +65,6 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
private DecompilerHighlighter highlighter;
- private Boolean allAccess;
-
private TaintCTokenHighlighterPalette highlightPalette;
private int paletteIndex;
@@ -250,12 +249,15 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
*
* TODO: We could limit our taint addresses to those in this function...? TODO:
* We should reset the palette cache to start coloring from the start.
+ *
+ * @param taskType subtract previous result
*/
- public void setTaint() {
+ public void setTaint(TaskType taskType) {
if (navigatable == null) {
navigatable = tool.getService(CodeViewerService.class).getNavigatable();
}
+ state.setTaskType(taskType);
AddressSet taintAddressSet = state.getTaintAddressSet();
Msg.info(this, "setTaint(): " + taintAddressSet.toString());
@@ -274,14 +276,16 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
// apply highlights to the decompiler window.
highlighter.applyHighlights();
+ state.setTaskType(TaskType.SET_TAINT);
+ }
+
+ public void setTaint() {
+ setTaint(TaskType.SET_TAINT);
}
public boolean matchOn(ClangToken token) {
- Map
> taintVarnodeMap = state.getTaintVarnodeMap();
-
- if (taintVarnodeMap == null || taintVarnodeMap.isEmpty() ||
- token instanceof ClangBreak ||
+ if (token instanceof ClangBreak ||
token instanceof ClangTypeToken ||
token instanceof ClangSyntaxToken ||
token instanceof ClangCommentToken) {
@@ -298,7 +302,8 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
Address tokenFuncEntryAddr = hf.getFunction().getEntryPoint();
// Just the tainted elements that are in this function.
- Set funcTaintSet = taintVarnodeMap.get(tokenFuncEntryAddr);
+ Set funcTaintSet = state.getQuerySet(tokenFuncEntryAddr);
+ //Set funcTaintSet = taintVarnodeMap.get(tokenFuncEntryAddr);
if (funcTaintSet == null || funcTaintSet.isEmpty()) {
return false;
}
@@ -458,14 +463,6 @@ public class TaintProvider extends ComponentProviderAdapter implements OptionsCh
plugin.changeHighlighter(hl);
}
- public boolean isAllAccess() {
- return allAccess;
- }
-
- public void setAllAccess(String taintAllAccess, Boolean allAccess) {
- this.allAccess = allAccess;
- }
-
public int getTokenCount() {
return matchCount;
}
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java
index 623bf9c620..1c5719bdc4 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintQueryResult.java
@@ -41,8 +41,8 @@ public record TaintQueryResult(String name,String fqname, Address iaddr, Address
public TaintQueryResult(Map result, Run run, LogicalLocation ll) {
this(
- SarifUtils.extractDisplayName(fqnFromLoc(run, ll)),
- fqnFromLoc(run, ll).getFullyQualifiedName(),
+ SarifUtils.extractDisplayName(ll),
+ ll.getFullyQualifiedName(),
(Address) result.get("Address"),
(Address) result.get("entry"),
new ArrayList(),
@@ -51,14 +51,6 @@ public record TaintQueryResult(String name,String fqname, Address iaddr, Address
addLabel(value);
}
- private static LogicalLocation fqnFromLoc(Run run, LogicalLocation ll) {
- String fqn = ll.getFullyQualifiedName();
- if (fqn == null) {
- ll = SarifUtils.getLogicalLocation(run, ll.getIndex());
- }
- return ll;
- }
-
public String getLabel() {
return this.labels.get(0);
}
@@ -111,8 +103,11 @@ public record TaintQueryResult(String name,String fqname, Address iaddr, Address
}
else {
// if neither are function-level, the addresses must match
+ // NB: parameter/local use matches on the representative
if (!iaddr.equals(vaddr)) {
- return null;
+ if (!(hv instanceof HighParam) || !iaddr.equals(hv.getRepresentative().getPCAddress())) {
+ return null;
+ }
}
}
if (hvName.startsWith(":")) { // fqname is FUN@FUN:name:vname
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintService.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintService.java
index ce1c0054c3..c7c88ce744 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintService.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintService.java
@@ -18,6 +18,7 @@ package ghidra.app.plugin.core.decompiler.taint;
import java.util.Map;
import java.util.Set;
+import ghidra.app.plugin.core.decompiler.taint.TaintState.TaskType;
import ghidra.framework.plugintool.ServiceInfo;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSet;
@@ -56,8 +57,9 @@ public interface TaintService {
*
* @param vmap tainted addresses
* @param clear before setting
+ * @param taskType operation to be performed
*/
- public void setVarnodeMap(Map> vmap, boolean clear);
+ public void setVarnodeMap(Map> vmap, boolean clear, TaskType taskType);
/**
* Clear existing taint
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintState.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintState.java
index 828ba22c17..3c1b256f76 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintState.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/TaintState.java
@@ -46,6 +46,10 @@ public interface TaintState {
SRCSINK, DEFAULT, CUSTOM
}
+ public enum TaskType {
+ SET_TAINT, SET_DELTA, APPLY_DELTA
+ }
+
public static TaintState newInstance(TaintPlugin plugin) {
return new TaintStateCTADL(plugin);
}
@@ -93,10 +97,12 @@ public interface TaintState {
public void setCancellation(boolean status);
- public void setTaintVarnodeMap(Map> vmap);
+ public void setTaintVarnodeMap(Map> vmap, TaskType delta);
public Map> getTaintVarnodeMap();
+ public Set getQuerySet(Address addr);
+
public void buildIndex(List param_list, String engine_path, String facts_path,
String index_directory);
@@ -153,4 +159,6 @@ public interface TaintState {
return false;
}
+ public void setTaskType(TaskType taskType);
+
}
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintAbstractQueryAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintAbstractQueryAction.java
index 64a2ea4eec..ef6d284040 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintAbstractQueryAction.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintAbstractQueryAction.java
@@ -39,12 +39,13 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
protected TaintPlugin plugin;
protected TaintState state;
protected String desc;
+ protected String title;
protected String executeTaintQueryIconString;
protected Icon executeTaintQueryIcon;
protected QueryType queryType;
- public TaintAbstractQueryAction(TaintPlugin plugin, TaintState state, String desc, String cmd) {
+ public TaintAbstractQueryAction(TaintPlugin plugin, TaintState state, String desc, String title, String cmd) {
super(cmd);
setHelpLocation(new HelpLocation(TaintPlugin.HELP_LOCATION, "Taint"+desc));
@@ -53,6 +54,7 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
this.plugin = plugin;
this.state = state;
this.desc = desc;
+ this.title = title;
}
/*
@@ -68,7 +70,7 @@ public abstract class TaintAbstractQueryAction extends TaintAbstractDecompilerAc
Program program = context.getProgram();
PluginTool tool = context.getTool();
- Task defaultQueryTask = new Task("Source-Sink Query Task", true, true, true, true) {
+ Task defaultQueryTask = new Task(title, true, true, true, true) {
@Override
public void run(TaskMonitor monitor) {
state.setCancellation(false);
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryAction.java
index ba5e46e45b..2ada4ef297 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryAction.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryAction.java
@@ -28,13 +28,13 @@ import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
public class TaintQueryAction extends TaintAbstractQueryAction {
public TaintQueryAction(TaintPlugin plugin, TaintState state) {
- super(plugin, state, "Query", "Run taint query");
+ super(plugin, state, "Query", "Source-Sink Taint Query", "Run taint query");
executeTaintQueryIconString = "icon.graph.default.display.program.graph";
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
queryType = QueryType.SRCSINK;
setToolBarData(new ToolBarData(executeTaintQueryIcon));
- setKeyBindingData(new KeyBindingData(KeyEvent.VK_Q, 0));
+ setKeyBindingData(new KeyBindingData(KeyEvent.VK_Y, 0));
}
@Override
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryCustomAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryCustomAction.java
index 27f1d8fe44..eac8d0b915 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryCustomAction.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryCustomAction.java
@@ -15,6 +15,10 @@
*/
package ghidra.app.plugin.core.decompiler.taint.actions;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import docking.action.KeyBindingData;
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
import ghidra.app.plugin.core.decompiler.taint.TaintState;
import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
@@ -22,8 +26,9 @@ import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
public class TaintQueryCustomAction extends TaintAbstractQueryAction {
public TaintQueryCustomAction(TaintPlugin plugin, TaintState state) {
- super(plugin, state, "CustomQuery", "Run custom taint query");
+ super(plugin, state, "CustomQuery", "Custom Taint Query", "Run custom taint query");
queryType = QueryType.CUSTOM;
+ setKeyBindingData(new KeyBindingData(KeyEvent.VK_Y, InputEvent.CTRL_DOWN_MASK));
}
}
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryDefaultAction.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryDefaultAction.java
index d5922f28a1..27fa19078c 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryDefaultAction.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/actions/TaintQueryDefaultAction.java
@@ -15,6 +15,10 @@
*/
package ghidra.app.plugin.core.decompiler.taint.actions;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+
+import docking.action.KeyBindingData;
import docking.action.ToolBarData;
import generic.theme.GIcon;
import ghidra.app.plugin.core.decompiler.taint.TaintPlugin;
@@ -24,12 +28,13 @@ import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
public class TaintQueryDefaultAction extends TaintAbstractQueryAction {
public TaintQueryDefaultAction(TaintPlugin plugin, TaintState state) {
- super(plugin, state, "DefaultQuery", "Run default taint query");
+ super(plugin, state, "DefaultQuery", "Default Taint Query", "Run default taint query");
executeTaintQueryIconString = "icon.version.tracking.markup.status.conflict";
executeTaintQueryIcon = new GIcon(executeTaintQueryIconString);
queryType = QueryType.DEFAULT;
setToolBarData(new ToolBarData(executeTaintQueryIcon));
+ setKeyBindingData(new KeyBindingData(KeyEvent.VK_Y, InputEvent.SHIFT_DOWN_MASK));
}
}
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/TaintStateCTADL.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/TaintStateCTADL.java
index 2da0418ad7..7781c41dc8 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/TaintStateCTADL.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/ctadl/TaintStateCTADL.java
@@ -23,6 +23,7 @@ import java.util.List;
import generic.jar.ResourceFile;
import ghidra.app.decompiler.*;
import ghidra.app.plugin.core.decompiler.taint.*;
+import ghidra.app.plugin.core.decompiler.taint.TaintPlugin.TaintDirection;
import ghidra.app.plugin.core.osgi.BundleHost;
import ghidra.app.script.*;
import ghidra.app.services.ConsoleService;
@@ -48,8 +49,23 @@ public class TaintStateCTADL extends AbstractTaintState {
paramList.add("--directory");
paramList.add(indexDirectory);
paramList.add("query");
+ Comparable direction = taintOptions.getTaintDirection();
+ if (!direction.equals(TaintDirection.DEFAULT)) {
+ paramList.add("--compute-slices");
+ switch (taintOptions.getTaintDirection()) {
+ case TaintDirection.BOTH ->
+ paramList.add("all");
+ case TaintDirection.FORWARD ->
+ paramList.add("fwd");
+ case TaintDirection.BACKWARD ->
+ paramList.add("bwd");
+ default -> {
+ // No action
+ }
+ }
+ }
paramList.add("-j8");
- paramList.add("--format=" + taintOptions.getTaintOutputForm());
+ paramList.add("--format=" + taintOptions.getTaintOutputForm().toString());
}
@Override
@@ -132,6 +148,10 @@ public class TaintStateCTADL extends AbstractTaintState {
if (!TaintState.isActualParam(token) && !(hv instanceof HighParam)) {
writer.println("\tVNODE_PC_ADDRESS(vn, " + addr.getOffset() + "),");
}
+ else { // NB: we still want a local match
+ writer.println("\t(PCODE_INPUT(i, _, vn) ; PCODE_OUTPUT(i, vn)),");
+ writer.println("\tPCODE_TARGET(i, " + addr.getOffset() + "),");
+ }
}
if (mark.bySymbol()) {
writer.println("\tSYMBOL_NAME(sym, \"" + token.getText() + "\"),");
diff --git a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintCodeFlowResultHandler.java b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintCodeFlowResultHandler.java
index 7f5c4a16b1..9ace7fc8d6 100644
--- a/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintCodeFlowResultHandler.java
+++ b/Ghidra/Features/DecompilerDependent/src/main/java/ghidra/app/plugin/core/decompiler/taint/sarif/SarifTaintCodeFlowResultHandler.java
@@ -41,12 +41,12 @@ public class SarifTaintCodeFlowResultHandler extends SarifResultHandler {
}
@Override
- public void handle(SarifDataFrame dframe, Run run, Result result, Map map) {
+ public void handle(SarifDataFrame dframe, Run r, Result res, Map map) {
this.df = dframe;
this.controller = df.getController();
- this.run = run;
- this.result = result;
+ this.run = r;
+ this.result = res;
List