Merge remote-tracking branch 'origin/GP-5141_d-millar_SARIF_CME--SQUASHED'

This commit is contained in:
Ryan Kurtz 2024-12-02 06:21:28 -05:00
commit 35a47cf69b
8 changed files with 136 additions and 148 deletions

View File

@ -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.
@ -17,28 +17,18 @@ package sarif;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.*;
import com.contrastsecurity.sarif.Location;
import com.contrastsecurity.sarif.Result;
import com.contrastsecurity.sarif.SarifSchema210;
import com.contrastsecurity.sarif.*;
import docking.widgets.table.ObjectSelectedListener;
import ghidra.app.plugin.core.colorizer.ColorizingService;
import ghidra.app.services.GraphDisplayBroker;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.BookmarkManager;
import ghidra.program.model.listing.CodeUnit;
import ghidra.program.model.listing.Program;
import ghidra.service.graph.AttributedGraph;
import ghidra.service.graph.EmptyGraphType;
import ghidra.service.graph.GraphDisplay;
import ghidra.service.graph.GraphDisplayOptions;
import ghidra.program.model.listing.*;
import ghidra.service.graph.*;
import ghidra.util.Msg;
import ghidra.util.classfinder.ClassSearcher;
import ghidra.util.exception.CancelledException;
@ -83,7 +73,7 @@ public class SarifController implements ObjectSelectedListener<Map<String, Objec
this.program = program;
this.plugin = plugin;
this.coloringService = plugin.getTool().getService(ColorizingService.class);
this.programManager = new ProgramSarifMgr(program);
this.programManager = new ProgramSarifMgr(program, new MessageLog());
}
public SarifController(ProgramSarifMgr manager) {

View File

@ -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.
@ -18,9 +18,7 @@ package sarif;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -30,23 +28,11 @@ import ghidra.app.util.Option;
import ghidra.app.util.OptionException;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.AbstractProgramLoader;
import ghidra.app.util.opinion.LoadException;
import ghidra.app.util.opinion.LoadSpec;
import ghidra.app.util.opinion.Loaded;
import ghidra.app.util.opinion.LoaderTier;
import ghidra.app.util.opinion.*;
import ghidra.framework.model.DomainObject;
import ghidra.framework.model.Project;
import ghidra.program.model.address.Address;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.CompilerSpecDescription;
import ghidra.program.model.lang.CompilerSpecNotFoundException;
import ghidra.program.model.lang.Endian;
import ghidra.program.model.lang.ExternalLanguageCompilerSpecQuery;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.LanguageCompilerSpecPair;
import ghidra.program.model.lang.LanguageDescription;
import ghidra.program.model.lang.LanguageNotFoundException;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Program;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
@ -88,7 +74,7 @@ public class SarifLoader extends AbstractProgramLoader {
//
getLanguageService();
ParseResult result = parse(provider);
ParseResult result = parse(provider, new MessageLog());
ProgramInfo info = result.lastInfo;
if (info == null) {
@ -199,7 +185,7 @@ public class SarifLoader extends AbstractProgramLoader {
CompilerSpec importerCompilerSpec =
importerLanguage.getCompilerSpecByID(pair.compilerSpecID);
ParseResult result = parse(provider);
ParseResult result = parse(provider, log);
Address imageBase = null;
if (result.lastInfo.imageBase != null) {
@ -230,7 +216,7 @@ public class SarifLoader extends AbstractProgramLoader {
List<Option> options, MessageLog log, Program prog, TaskMonitor monitor)
throws IOException, LoadException, CancelledException {
File file = provider.getFile();
doImport(new ProgramSarifMgr(prog, file), options, log, prog, monitor, true);
doImport(new ProgramSarifMgr(prog, file, log), options, log, prog, monitor, true);
}
private boolean doImportWork(final ProgramSarifMgr mgr, final List<Option> options,
@ -238,9 +224,7 @@ public class SarifLoader extends AbstractProgramLoader {
final boolean isAddToProgram) throws LoadException {
boolean success = true;
try {
SarifProgramOptions sarifOptions = mgr.getOptions();
sarifOptions.setOptions(options);
sarifOptions.setAddToProgram(isAddToProgram);
mgr.setOptions(options, isAddToProgram);
mgr.read(prog, monitor);
success = true;
}
@ -311,9 +295,9 @@ public class SarifLoader extends AbstractProgramLoader {
}
}
private ParseResult parse(ByteProvider provider) throws IOException {
private ParseResult parse(ByteProvider provider, MessageLog log) throws IOException {
try {
ProgramSarifMgr lastSarifMgr = new ProgramSarifMgr(provider);
ProgramSarifMgr lastSarifMgr = new ProgramSarifMgr(provider, log);
ProgramInfo lastInfo = lastSarifMgr.getProgramInfo();
return new ParseResult(lastSarifMgr, lastInfo);
}

View File

@ -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.
@ -19,11 +19,10 @@ import java.io.File;
import java.io.IOException;
import java.util.List;
import ghidra.app.util.DomainObjectService;
import ghidra.app.util.Option;
import ghidra.app.util.OptionException;
import ghidra.app.util.*;
import ghidra.app.util.exporter.Exporter;
import ghidra.app.util.exporter.ExporterException;
import ghidra.app.util.importer.MessageLog;
import ghidra.framework.model.DomainObject;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
@ -76,7 +75,7 @@ public class SarifExporter extends Exporter {
addrSet = program.getMemory();
}
ProgramSarifMgr mgr = new ProgramSarifMgr(program, file);
ProgramSarifMgr mgr = new ProgramSarifMgr(program, file, new MessageLog());
try {
log = mgr.write(program, addrSet, monitor, options);

View File

@ -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.
@ -15,41 +15,26 @@
*/
package sarif.managers;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.io.*;
import java.lang.Exception;
import java.util.*;
import com.contrastsecurity.sarif.Artifact;
import com.contrastsecurity.sarif.Run;
import com.contrastsecurity.sarif.SarifSchema210;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonArray;
import com.google.gson.JsonObject;
import org.xml.sax.SAXException;
import com.contrastsecurity.sarif.*;
import com.google.gson.*;
import com.google.gson.stream.JsonWriter;
import ghidra.app.util.Option;
import ghidra.app.util.OptionException;
import ghidra.app.util.bin.ByteProvider;
import ghidra.app.util.importer.MessageLog;
import ghidra.app.util.opinion.ElfLoader;
import ghidra.app.util.opinion.MzLoader;
import ghidra.app.util.opinion.NeLoader;
import ghidra.app.util.opinion.PeLoader;
import ghidra.app.util.opinion.*;
import ghidra.framework.Application;
import ghidra.program.database.module.TreeManager;
import ghidra.program.model.address.AddressFormatException;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.lang.CompilerSpec;
import ghidra.program.model.lang.CompilerSpecID;
import ghidra.program.model.lang.Language;
import ghidra.program.model.lang.LanguageID;
import ghidra.program.model.lang.*;
import ghidra.program.model.listing.Listing;
import ghidra.program.model.listing.Program;
import ghidra.program.util.GhidraProgramUtilities;
@ -84,6 +69,7 @@ public class ProgramSarifMgr {
private SarifMgr[] mgrs;
private Boolean[] opts;
private Program program;
private MessageLog log;
private SarifProgramOptions options;
private Map<String, Boolean> keys = new HashMap<>();
private Writer baseWriter;
@ -92,8 +78,9 @@ public class ProgramSarifMgr {
* Constructs a new program SARIF manager for applying results to an existing
* program - used by the SarifPlugin
*/
public ProgramSarifMgr(Program program) {
public ProgramSarifMgr(Program program, MessageLog log) {
this.program = program;
this.log = log;
options = new SarifProgramOptions();
addManagers();
}
@ -104,8 +91,8 @@ public class ProgramSarifMgr {
*
* @param file the SARIF file
*/
public ProgramSarifMgr(Program program, File file) {
this(program);
public ProgramSarifMgr(Program program, File file, MessageLog log) {
this(program, log);
this.file = file;
}
@ -115,10 +102,11 @@ public class ProgramSarifMgr {
*
* @param bp byte provider
*/
public ProgramSarifMgr(ByteProvider bp) {
public ProgramSarifMgr(ByteProvider bp, MessageLog log) {
options = new SarifProgramOptions();
this.file = (bp.getFSRL() != null && bp.getFSRL().getNestingDepth() == 1) ? new File(bp.getFSRL().getPath())
: bp.getFile();
this.log = log;
}
/**
@ -173,10 +161,8 @@ public class ProgramSarifMgr {
return file != null ? new FileWriter(file) : new StringWriter(1000);
}
public void addManagers() {
int mgrCount = 0;
MessageLog log = new MessageLog();
mgrs = new SarifMgr[N_MANAGERS+1];
opts = new Boolean[N_MANAGERS+1];
mgrs[mgrCount] = new DataTypesSarifMgr(program, log);
@ -221,6 +207,32 @@ public class ProgramSarifMgr {
}
}
public void setOptions(List<Option> optionList, boolean isAddToProgram) throws OptionException {
options.setOptions(optionList);
options.setAddToProgram(isAddToProgram);
int mgrCount = 0;
opts = new Boolean[N_MANAGERS + 1];
opts[mgrCount++] = options.isData();
opts[mgrCount++] = options.isMemoryBlocks();
opts[mgrCount++] = options.isRegisters();
opts[mgrCount++] = options.isInstructions();
opts[mgrCount++] = options.isData();
opts[mgrCount++] = options.isEquates();
opts[mgrCount++] = options.isComments();
opts[mgrCount++] = options.isProperties();
opts[mgrCount++] = options.isBookmarks();
opts[mgrCount++] = options.isTrees();
opts[mgrCount++] = options.isEntryPoints();
opts[mgrCount++] = options.isRelocationTable();
opts[mgrCount++] = options.isSymbols();
opts[mgrCount++] = options.isExternalLibraries();
opts[mgrCount++] = options.isFunctions();
opts[mgrCount++] = options.isSymbols();
opts[mgrCount++] = options.isReferences();
assert (mgrCount == N_MANAGERS + 1);
}
public Map<String, Boolean> getKeys() {
return keys;
}
@ -634,5 +646,4 @@ public class ProgramSarifMgr {
tempFile.deleteOnExit();
}
}

View File

@ -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.
@ -16,29 +16,16 @@
package sarif.managers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import com.google.gson.JsonArray;
import generic.stl.Pair;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFormatException;
import ghidra.program.model.address.AddressRange;
import ghidra.program.model.address.AddressRangeIterator;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.DuplicateGroupException;
import ghidra.program.model.listing.Group;
import ghidra.program.model.listing.Program;
import ghidra.program.model.listing.ProgramFragment;
import ghidra.program.model.listing.ProgramModule;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.*;
import ghidra.util.Msg;
import ghidra.util.exception.CancelledException;
import ghidra.util.exception.DuplicateNameException;
import ghidra.util.exception.NotEmptyException;
import ghidra.util.exception.NotFoundException;
import ghidra.util.exception.*;
import ghidra.util.task.TaskLauncher;
import ghidra.util.task.TaskMonitor;
import sarif.SarifProgramOptions;
@ -53,7 +40,6 @@ public class ProgramTreeSarifMgr extends SarifMgr {
public static String KEY = "PROGRAM_TREES";
public static String SUBKEY = "ProgramTree";
private List<String> fragmentNameList;
private String treeName;
private TaskMonitor monitor;
@ -83,7 +69,6 @@ public class ProgramTreeSarifMgr extends SarifMgr {
@SuppressWarnings("unchecked")
private void processTree(Map<String, Object> result) throws CancelledException {
treeName = (String) result.get("name");
fragmentNameList = new ArrayList<>();
ProgramModule root = listing.getRootModule(treeName);
try {
@ -115,16 +100,21 @@ public class ProgramTreeSarifMgr extends SarifMgr {
treeName = root.getTreeName();
}
Group[] orig = root.getChildren();
ProgramFragment depot = root.createFragment("depot");
for (Group g : orig) {
if (g instanceof ProgramFragment frag) {
AddressRangeIterator iter = frag.getAddressRanges(true);
while (iter.hasNext()) {
AddressRange next = iter.next();
depot.move(next.getMinAddress(), next.getMaxAddress());
}
Set<AddressRange> ranges = new HashSet<>();
List<Map<String, Object>> fragments =
(List<Map<String, Object>>) result.get("fragments");
for (Map<String, Object> f : fragments) {
try {
collectFragmentRanges(ranges, f);
}
catch (Exception e) {
log.appendMsg(e.getMessage());
}
}
ProgramFragment depot = root.createFragment("depot");
for (AddressRange r : ranges) {
depot.move(r.getMinAddress(), r.getMaxAddress());
}
removeEmptyFragments(root);
@ -133,13 +123,13 @@ public class ProgramTreeSarifMgr extends SarifMgr {
monitor.checkCancelled();
processModule(root, m);
}
List<Map<String, Object>> fragments = (List<Map<String, Object>>) result.get("fragments");
for (Map<String, Object> f : fragments) {
monitor.checkCancelled();
processFragment(root, f);
}
} catch (NotFoundException | DuplicateNameException e) {
root.removeChild("depot");
}
catch (NotFoundException | DuplicateNameException | NotEmptyException e) {
log.appendException(e);
}
}
@ -175,9 +165,6 @@ public class ProgramTreeSarifMgr extends SarifMgr {
private void processFragment(ProgramModule parent, Map<String, Object> fragment) {
String name = (String) fragment.get("name");
if (!fragmentNameList.contains(name)) {
fragmentNameList.add(name);
}
ProgramFragment frag = null;
try {
frag = parent.createFragment(name);
@ -223,15 +210,38 @@ public class ProgramTreeSarifMgr extends SarifMgr {
}
}
@SuppressWarnings("unchecked")
private void collectFragmentRanges(Set<AddressRange> set, Map<String, Object> fragment)
throws AddressFormatException {
List<Map<String, Object>> ranges = (List<Map<String, Object>>) fragment.get("ranges");
for (Map<String, Object> r : ranges) {
if (monitor.isCancelled()) {
break;
}
String startStr = (String) r.get("start");
String endStr = (String) r.get("end");
Address start = parseAddress(factory, startStr);
Address end = parseAddress(factory, endStr);
if (start == null || end == null) {
throw new AddressFormatException(
"Incompatible Fragment Address Range: [" + startStr + "," + endStr + "]");
}
set.add(new AddressRangeImpl(start, end));
}
}
/**
* Method removeEmptyFragments.
*/
private void removeEmptyFragments(ProgramModule module) {
Group[] groups = module.getChildren();
for (Group group : groups) {
if (group instanceof ProgramFragment) {
if (group instanceof ProgramFragment frag) {
String name = group.getName();
if (!fragmentNameList.contains(name)) {
if (frag.isEmpty()) {
try {
module.removeChild(name);
} catch (NotEmptyException e) {

View File

@ -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.
@ -169,7 +169,7 @@ public class PropertiesSarifMgr extends SarifMgr {
bmMgr.setBookmark(addr, BookmarkType.NOTE, name, val);
}
else {
log.appendMsg("Unsupported PROPERTY usage");
log.appendMsg("Unsupported PROPERTY usage: type = " + type);
}
}
@ -214,7 +214,7 @@ public class PropertiesSarifMgr extends SarifMgr {
}
Object val = result.get("value");
if (type == null || "void".equals(type)) {
log.appendMsg("Unsupported PROPERTY usage");
log.appendMsg("Unsupported PROPERTY usage: null type for " + name);
}
else if ("int".equals(type)) {
list.setInt(name, Integer.parseInt((String) val, 16));
@ -285,7 +285,7 @@ public class PropertiesSarifMgr extends SarifMgr {
list.setByteArray(name, bytes);
}
else {
log.appendMsg("Unsupported PROPERTY usage");
log.appendMsg("Unsupported PROPERTY usage: type = " + type);
}
}

View File

@ -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.
@ -16,9 +16,7 @@
package sarif.managers;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.*;
import com.google.gson.JsonArray;
@ -26,12 +24,7 @@ import ghidra.app.util.importer.MessageLog;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressSetView;
import ghidra.program.model.listing.Program;
import ghidra.program.model.symbol.Namespace;
import ghidra.program.model.symbol.SourceType;
import ghidra.program.model.symbol.Symbol;
import ghidra.program.model.symbol.SymbolIterator;
import ghidra.program.model.symbol.SymbolTable;
import ghidra.program.model.symbol.SymbolUtilities;
import ghidra.program.model.symbol.*;
import ghidra.util.exception.CancelledException;
import ghidra.util.task.TaskLauncher;
import ghidra.util.task.TaskMonitor;
@ -130,7 +123,7 @@ public class SymbolTableSarifMgr extends SarifMgr {
}
}
if (symbolTable.getSymbol(name, addr, scope) == null) {
if (addr.isMemoryAddress() && symbolTable.getSymbol(name, addr, scope) == null) {
Symbol s = SymbolUtilities.createPreferredLabelOrFunctionSymbol(program, addr, scope, name, sourceType);
if (s != null && isPrimary && overwritePrimary) {
s.setPrimary();

View File

@ -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.
@ -15,17 +15,16 @@
*/
package sarif;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.*;
import java.io.StringWriter;
import org.junit.After;
import org.junit.Before;
import ghidra.app.util.importer.MessageLog;
import ghidra.program.database.ProgramBuilder;
import ghidra.program.model.address.Address;
import ghidra.program.model.address.AddressFactory;
import ghidra.program.model.address.AddressSet;
import ghidra.program.model.address.*;
import ghidra.program.model.listing.Program;
import ghidra.program.model.mem.MemoryBlock;
import ghidra.program.util.ProgramDiff;
@ -43,6 +42,7 @@ public class AbstractSarifTest extends AbstractGhidraHeadedIntegrationTest {
protected Address entry;
protected MemoryBlock block;
protected DummyCancellableTaskMonitor monitor;
protected MessageLog log;
protected ProgramSarifMgr mgr;
protected AddressSet addrSet;
@ -97,7 +97,8 @@ public class AbstractSarifTest extends AbstractGhidraHeadedIntegrationTest {
addrSet = new AddressSet(program.getMemory());
monitor = new DummyCancellableTaskMonitor();
mgr = new ProgramSarifMgr(program);
log = new MessageLog();
mgr = new ProgramSarifMgr(program, log);
mgr.useTempFileForBytes(getTestDirectoryPath());
}