mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2026-01-09 14:08:03 -05:00
Merge remote-tracking branch 'origin/GP-5238_d-millar_ctadl_mods--SQUASHED'
This commit is contained in:
@@ -124,6 +124,17 @@
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="sect2">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="ForceDirection"></a>Force Direction</h3></div></div></div>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="sect2">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="TaintTokenColor"></a>Highlight Color</h3></div></div></div>
|
||||
@@ -144,15 +155,17 @@
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="TaintOutputFormat"></a>Output Format</h3></div></div></div>
|
||||
<p>
|
||||
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).
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="sect2">
|
||||
<div class="titlepage"><div><div><h3 class="title">
|
||||
<a name="TaintAllAccess"></a>Use all access paths</h3></div></div></div>
|
||||
<a name="TaintAllAccess"></a>Match on Fields</h3></div></div></div>
|
||||
<p>
|
||||
Use all access paths for sink/source variables.
|
||||
Use all access paths, including field references, for sink/source variables.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -51,7 +51,9 @@ public abstract class AbstractTaintState implements TaintState {
|
||||
private AddressSet taintAddressSet = new AddressSet();
|
||||
private Map<Address, Set<TaintQueryResult>> taintVarnodeMap = new HashMap<>();
|
||||
|
||||
/// private QueryDataFrame currentQueryData;
|
||||
private AddressSet deltaAddressSet = new AddressSet();
|
||||
private Map<Address, Set<TaintQueryResult>> 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<Address, Set<TaintQueryResult>> vmap) {
|
||||
taintVarnodeMap = vmap;
|
||||
public void setTaintVarnodeMap(Map<Address, Set<TaintQueryResult>> 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<TaintQueryResult> getQuerySet(Address key) {
|
||||
Set<TaintQueryResult> set = new HashSet<>();
|
||||
switch (taskType) {
|
||||
case SET_TAINT -> set = taintVarnodeMap.get(key);
|
||||
case SET_DELTA -> set = deltaVarnodeMap.get(key);
|
||||
case APPLY_DELTA -> {
|
||||
Set<TaintQueryResult> A = taintVarnodeMap.get(key);
|
||||
if (A != null) {
|
||||
set.addAll(A);
|
||||
}
|
||||
Set<TaintQueryResult> 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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Address, Set<TaintQueryResult>> vmap, boolean clear) {
|
||||
public void setVarnodeMap(Map<Address, Set<TaintQueryResult>> vmap, boolean clear, TaskType delta) {
|
||||
if (clear) {
|
||||
taintProvider.clearTaint();
|
||||
}
|
||||
state.setTaintVarnodeMap(vmap);
|
||||
taintProvider.setTaint();
|
||||
state.setTaintVarnodeMap(vmap, delta);
|
||||
taintProvider.setTaint(delta);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -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
|
||||
* <p>
|
||||
* 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<Address, Set<TaintQueryResult>> 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<TaintQueryResult> funcTaintSet = taintVarnodeMap.get(tokenFuncEntryAddr);
|
||||
Set<TaintQueryResult> funcTaintSet = state.getQuerySet(tokenFuncEntryAddr);
|
||||
//Set<TaintQueryResult> 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;
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ public record TaintQueryResult(String name,String fqname, Address iaddr, Address
|
||||
|
||||
public TaintQueryResult(Map<String, Object> 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<String>(),
|
||||
@@ -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
|
||||
|
||||
@@ -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<Address, Set<TaintQueryResult>> vmap, boolean clear);
|
||||
public void setVarnodeMap(Map<Address, Set<TaintQueryResult>> vmap, boolean clear, TaskType taskType);
|
||||
|
||||
/**
|
||||
* Clear existing taint
|
||||
|
||||
@@ -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<Address, Set<TaintQueryResult>> vmap);
|
||||
public void setTaintVarnodeMap(Map<Address, Set<TaintQueryResult>> vmap, TaskType delta);
|
||||
|
||||
public Map<Address, Set<TaintQueryResult>> getTaintVarnodeMap();
|
||||
|
||||
public Set<TaintQueryResult> getQuerySet(Address addr);
|
||||
|
||||
public void buildIndex(List<String> 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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<TaintDirection> 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() + "\"),");
|
||||
|
||||
@@ -41,12 +41,12 @@ public class SarifTaintCodeFlowResultHandler extends SarifResultHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(SarifDataFrame dframe, Run run, Result result, Map<String, Object> map) {
|
||||
public void handle(SarifDataFrame dframe, Run r, Result res, Map<String, Object> map) {
|
||||
this.df = dframe;
|
||||
this.controller = df.getController();
|
||||
|
||||
this.run = run;
|
||||
this.result = result;
|
||||
this.run = r;
|
||||
this.result = res;
|
||||
|
||||
List<Map<String, Object>> tableResults = df.getTableResults();
|
||||
String ruleId = result.getRuleId();
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.contrastsecurity.sarif.*;
|
||||
import docking.ActionContext;
|
||||
import docking.action.*;
|
||||
import ghidra.app.plugin.core.decompiler.taint.*;
|
||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.TaskType;
|
||||
import ghidra.framework.plugintool.PluginTool;
|
||||
import ghidra.program.model.address.Address;
|
||||
import ghidra.program.model.address.AddressRange;
|
||||
@@ -49,12 +50,12 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handle(SarifDataFrame dframe, Run run, Result result, Map<String, Object> map) {
|
||||
public void handle(SarifDataFrame dframe, Run r, Result res, Map<String, Object> map) {
|
||||
this.df = dframe;
|
||||
this.controller = df.getController();
|
||||
|
||||
this.run = run;
|
||||
this.result = result;
|
||||
this.run = r;
|
||||
this.result = res;
|
||||
|
||||
String ruleId = result.getRuleId();
|
||||
if (ruleId == null || ruleId.equals("C0001")) {
|
||||
@@ -199,6 +200,7 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||
private class ApplyTaintViaVarnodesTask extends ProgramTask {
|
||||
|
||||
private SarifResultsTableProvider tableProvider;
|
||||
protected TaskType taskType = TaskType.SET_TAINT;
|
||||
|
||||
protected ApplyTaintViaVarnodesTask(SarifResultsTableProvider provider) {
|
||||
super(provider.getController().getProgram(), "ApplyTaintViaVarnodesTask", true, true,
|
||||
@@ -224,7 +226,7 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||
PluginTool tool = tableProvider.getController().getPlugin().getTool();
|
||||
TaintService service = tool.getService(TaintService.class);
|
||||
if (service != null) {
|
||||
service.setVarnodeMap(map, true);
|
||||
service.setVarnodeMap(map, true, taskType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +320,7 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||
}
|
||||
}
|
||||
|
||||
service.setVarnodeMap(map, false);
|
||||
service.setVarnodeMap(map, false, TaskType.SET_TAINT);
|
||||
service.setAddressSet(set, false);
|
||||
}
|
||||
|
||||
@@ -363,4 +365,68 @@ public class SarifTaintResultHandler extends SarifResultHandler {
|
||||
return vset;
|
||||
}
|
||||
|
||||
// Saving these for later - on the fence re use case
|
||||
/*
|
||||
DockingAction applyDelta = new DockingAction("Apply delta", getKey()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
provider.filterTable.getTable().selectAll();
|
||||
TaskLauncher.launch(new ApplyDeltaViaVarnodesTask(provider));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddToPopup(ActionContext context) {
|
||||
return isEnabled;
|
||||
}
|
||||
};
|
||||
applyDelta.setDescription("Apply delta");
|
||||
applyDelta.setToolBarData(new ToolBarData(Icons.COLLAPSE_ALL_ICON));
|
||||
provider.addLocalAction(applyDelta);
|
||||
|
||||
DockingAction initDelta = new DockingAction("Set base for delta", getKey()) {
|
||||
@Override
|
||||
public void actionPerformed(ActionContext context) {
|
||||
TaskLauncher.launch(new SetDeltaBaseTask(provider));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabledForContext(ActionContext context) {
|
||||
return isEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAddToPopup(ActionContext context) {
|
||||
return isEnabled;
|
||||
}
|
||||
};
|
||||
initDelta.setDescription("Initialize delta");
|
||||
initDelta.setToolBarData(new ToolBarData(Icons.INFO_ICON));
|
||||
provider.addLocalAction(initDelta);
|
||||
*/
|
||||
|
||||
/*
|
||||
private class ApplyDeltaViaVarnodesTask extends ApplyTaintViaVarnodesTask {
|
||||
|
||||
protected ApplyDeltaViaVarnodesTask(SarifResultsTableProvider provider) {
|
||||
super(provider);
|
||||
this.delta = TaskType.APPLY_DELTA;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SetDeltaBaseTask extends ApplyTaintViaVarnodesTask {
|
||||
|
||||
protected SetDeltaBaseTask(SarifResultsTableProvider provider) {
|
||||
super(provider);
|
||||
this.delta = TaskType.SET_DELTA;
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
@@ -32,8 +32,7 @@ import ghidra.app.decompiler.*;
|
||||
import ghidra.app.plugin.core.codebrowser.CodeBrowserPlugin;
|
||||
import ghidra.app.plugin.core.decompile.DecompilePlugin;
|
||||
import ghidra.app.plugin.core.decompile.DecompilerProvider;
|
||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.MarkType;
|
||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.QueryType;
|
||||
import ghidra.app.plugin.core.decompiler.taint.TaintState.*;
|
||||
import ghidra.app.plugin.core.decompiler.taint.sarif.SarifTaintGraphRunHandler;
|
||||
import ghidra.app.services.CodeViewerService;
|
||||
import ghidra.framework.Application;
|
||||
@@ -186,7 +185,7 @@ public class DecompilerTaintTest extends AbstractGhidraHeadedIntegrationTest {
|
||||
for (Map<String, Object> result : df.getTableResults()) {
|
||||
processResult(map, result);
|
||||
}
|
||||
taintService.setVarnodeMap(map, true);
|
||||
taintService.setVarnodeMap(map, true, TaskType.SET_TAINT);
|
||||
validateResult(token, map);
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,7 @@ public class SarifPlugin extends ProgramPlugin implements SarifService, OptionsC
|
||||
return io.readSarif(sarif);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SarifController getController() {
|
||||
currentProgram = getCurrentProgram();
|
||||
if (currentProgram != null) {
|
||||
@@ -156,9 +157,10 @@ public class SarifPlugin extends ProgramPlugin implements SarifService, OptionsC
|
||||
* Ultimately both selections end up calling this to actually show something on
|
||||
* the Ghidra gui
|
||||
*
|
||||
* @param logName
|
||||
* @param sarif
|
||||
* @param logName display name
|
||||
* @param sarif the raw sarif
|
||||
*/
|
||||
@Override
|
||||
public void showSarif(String logName, SarifSchema210 sarif) {
|
||||
SarifController currentController = getController();
|
||||
if (currentController != null) {
|
||||
|
||||
@@ -68,13 +68,17 @@ public class SarifUtils {
|
||||
// artifactLocation/uri <= the overlayED space name (typically OTHER)
|
||||
|
||||
private static Run currentRun = null;
|
||||
// llocs has indexed per run and is not valid across runs
|
||||
// Attempts to access llocs outside the population phase will throw an error
|
||||
private static LogicalLocation[] llocs;
|
||||
// All of the following have keys that are valid across queries
|
||||
private static List<com.contrastsecurity.sarif.Address> addresses;
|
||||
private static Map<String, Long> nameToOffset = new HashMap<>();
|
||||
private static Map<String, LogicalLocation[]> nodeLocs = new HashMap<>();
|
||||
private static Map<String, String> edgeSrcs = new HashMap<>();
|
||||
private static Map<String, String> edgeDsts = new HashMap<>();
|
||||
private static Map<String, String> edgeDescs = new HashMap<>();
|
||||
private static boolean populating = false;
|
||||
|
||||
public static JsonArray setLocations(Address min, Address max) {
|
||||
AddressSet set = new AddressSet(min, max);
|
||||
@@ -141,6 +145,9 @@ public class SarifUtils {
|
||||
}
|
||||
|
||||
public static Address locationToAddress(Location location, Program program, boolean useOverlays) {
|
||||
if (!populating) {
|
||||
throw new RuntimeException("Locations valid only during population phase");
|
||||
}
|
||||
Long addr = -1L;
|
||||
PhysicalLocation physicalLocation = location.getPhysicalLocation();
|
||||
if (location.getPhysicalLocation() != null) {
|
||||
@@ -244,7 +251,9 @@ public class SarifUtils {
|
||||
|
||||
public static Address extractFunctionEntryAddr(Program program, String fqname) {
|
||||
String addr = null;
|
||||
if (fqname.contains("!")) {
|
||||
// NB: ! can be used both as a delimiter and part of an operator
|
||||
// TODO: This may eventually require a more complicated check
|
||||
if (fqname.contains("!") && !fqname.contains("!=")) {
|
||||
fqname = fqname.substring(0, fqname.indexOf("!"));
|
||||
}
|
||||
String[] parts = fqname.split("@");
|
||||
@@ -263,10 +272,6 @@ public class SarifUtils {
|
||||
return program.getAddressFactory().getAddress(addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fqname
|
||||
* @return
|
||||
*/
|
||||
public static List<Address> extractFQNameAddrPair(Program program, String fqname) {
|
||||
List<Address> addr_pair = new ArrayList<Address>();
|
||||
String[] parts = fqname.split("@");
|
||||
@@ -350,6 +355,9 @@ public class SarifUtils {
|
||||
}
|
||||
|
||||
public static LogicalLocation getLogicalLocation(Run run, Location loc) {
|
||||
if (!populating) {
|
||||
throw new RuntimeException("Locations valid only during population phase");
|
||||
}
|
||||
Set<LogicalLocation> llocset = loc.getLogicalLocations();
|
||||
if (llocset == null) {
|
||||
return null;
|
||||
@@ -366,10 +374,6 @@ public class SarifUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LogicalLocation getLogicalLocation(Run run, Long index) {
|
||||
return llocs[index.intValue()];
|
||||
}
|
||||
|
||||
public static void validateRun(Run run) {
|
||||
if (!run.equals(currentRun) || llocs == null) {
|
||||
initRun(run);
|
||||
@@ -407,9 +411,18 @@ public class SarifUtils {
|
||||
Location loc = n.getLocation();
|
||||
if (loc != null) {
|
||||
Set<LogicalLocation> logicalLocations = loc.getLogicalLocations();
|
||||
LogicalLocation[] llocs = new LogicalLocation[logicalLocations.size()];
|
||||
logicalLocations.toArray(llocs);
|
||||
nodeLocs.put(id, llocs);
|
||||
LogicalLocation[] nodells = new LogicalLocation[logicalLocations.size()];
|
||||
int i = 0;
|
||||
for (LogicalLocation ll : logicalLocations) {
|
||||
// NB: These have to be derefenced immediately as they will be invalid for subsequent queries
|
||||
if (ll.getFullyQualifiedName() != null) {
|
||||
nodells[i++] = ll;
|
||||
}
|
||||
else {
|
||||
nodells[i++] = llocs[ll.getIndex().intValue()];
|
||||
}
|
||||
}
|
||||
nodeLocs.put(id, nodells);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -439,4 +452,8 @@ public class SarifUtils {
|
||||
return nodeLocs.get(id);
|
||||
}
|
||||
|
||||
public static void setPopulating(boolean b) {
|
||||
populating = b;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -82,28 +82,34 @@ public class SarifDataFrame {
|
||||
columns.add(new SarifColumnKey(entry.getKey(), entry.getValue()));
|
||||
}
|
||||
SarifUtils.validateRun(run);
|
||||
for (Result result : run.getResults()) {
|
||||
compileTaxaMap(run, result);
|
||||
|
||||
Map<String, Object> curTableResult = new HashMap<>();
|
||||
for (SarifResultHandler handler : resultHandlers) {
|
||||
SarifUtils.setPopulating(true);
|
||||
try {
|
||||
for (Result result : run.getResults()) {
|
||||
compileTaxaMap(run, result);
|
||||
|
||||
Map<String, Object> curTableResult = new HashMap<>();
|
||||
for (SarifResultHandler handler : resultHandlers) {
|
||||
if (handler.isEnabled(this)) {
|
||||
handler.handle(this, run, result, curTableResult);
|
||||
}
|
||||
}
|
||||
tableResults.add(curTableResult);
|
||||
String ruleid = (String) curTableResult.get("RuleId");
|
||||
List<Map<String, Object>> list = tableResultsAsMap.get(ruleid);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
tableResultsAsMap.put(ruleid, list);
|
||||
}
|
||||
list.add(curTableResult);
|
||||
}
|
||||
for (SarifRunHandler handler : controller.getSarifRunHandlers()) {
|
||||
if (handler.isEnabled(this)) {
|
||||
handler.handle(this, run, result, curTableResult);
|
||||
handler.handle(this, run);
|
||||
}
|
||||
}
|
||||
tableResults.add(curTableResult);
|
||||
String ruleid = (String) curTableResult.get("RuleId");
|
||||
List<Map<String, Object>> list = tableResultsAsMap.get(ruleid);
|
||||
if (list == null) {
|
||||
list = new ArrayList<>();
|
||||
tableResultsAsMap.put(ruleid, list);
|
||||
}
|
||||
list.add(curTableResult);
|
||||
}
|
||||
for (SarifRunHandler handler : controller.getSarifRunHandlers()) {
|
||||
if (handler.isEnabled(this)) {
|
||||
handler.handle(this, run);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
SarifUtils.setPopulating(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,7 +153,7 @@ public class SarifDataFrame {
|
||||
Set<ReportingDescriptorReference> taxa = result.getTaxa();
|
||||
if (taxa != null) {
|
||||
for (ReportingDescriptorReference ref : taxa) {
|
||||
long idx = (long) ref.getToolComponent().getIndex();
|
||||
long idx = ref.getToolComponent().getIndex();
|
||||
if (idx >= 0 && idx < view.size()) {
|
||||
ToolComponent tc = view.get((int) idx);
|
||||
taxaMap.put(tc.getName(), ref);
|
||||
|
||||
Reference in New Issue
Block a user