From 0545c9d4204aaf03e6f50781f9b709dae590fb50 Mon Sep 17 00:00:00 2001 From: karoliineh Date: Thu, 13 Jan 2022 16:47:53 +0200 Subject: [PATCH 1/7] GobPie now analyses files according to compilation database instead of individual opened or saved files --- src/main/java/GobPieConfiguration.java | 19 +++++++ src/main/java/GoblintAnalysis.java | 77 +++++++++++++------------- src/main/java/Main.java | 8 +-- 3 files changed, 62 insertions(+), 42 deletions(-) create mode 100644 src/main/java/GobPieConfiguration.java diff --git a/src/main/java/GobPieConfiguration.java b/src/main/java/GobPieConfiguration.java new file mode 100644 index 0000000..a5e0ab4 --- /dev/null +++ b/src/main/java/GobPieConfiguration.java @@ -0,0 +1,19 @@ +public class GobPieConfiguration { + + private String compilationDatabaseDirPath = ""; + private String goblintConfPath = ""; + private String[] compilationDBBuildCommands; + + public String getCompilationDatabaseDirPath() { + return this.compilationDatabaseDirPath; + } + + public String getGoblintConfPath() { + return this.goblintConfPath; + } + + public String[] getCompilationDBBuildCommands() { + return this.compilationDBBuildCommands; + } + +} diff --git a/src/main/java/GoblintAnalysis.java b/src/main/java/GoblintAnalysis.java index 3e2302c..6bbc453 100644 --- a/src/main/java/GoblintAnalysis.java +++ b/src/main/java/GoblintAnalysis.java @@ -3,12 +3,10 @@ import java.io.FileReader; import java.io.IOException; import java.net.MalformedURLException; -import java.net.URL; import java.util.*; import java.util.concurrent.TimeoutException; import com.ibm.wala.classLoader.Module; -import com.ibm.wala.classLoader.SourceFileModule; import magpiebridge.core.AnalysisConsumer; import magpiebridge.core.AnalysisResult; @@ -22,6 +20,7 @@ import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; import com.google.gson.JsonIOException; +import com.google.gson.JsonObject; import com.google.gson.JsonParser; import com.google.gson.JsonSyntaxException; @@ -34,8 +33,10 @@ public class GoblintAnalysis implements ServerAnalysis { final private MagpieServer magpieServer; - private URL sourcefileURL; private String pathToJsonResult = System.getProperty("user.dir") + "/" + "analysisResults.json"; + private String pathToGobPieConf = System.getProperty("user.dir") + "/" + "gobpie.json"; + private String pathToGoblintConf; + private String pathToCompilationDBDir; private String[] commands; private Logger log; @@ -64,7 +65,7 @@ public String[] getCommand() { /** * The files to be analyzed. * - * @param files the files that have been opened in the editor. + * @param files the files that have been opened in the editor (not using due to using the compilation database). * @param consumer the server which consumes the analysis results. * @param rerun tells if the analysis should be reran. */ @@ -72,33 +73,19 @@ public String[] getCommand() { public void analyze(Collection files, AnalysisConsumer consumer, boolean rerun) { if (rerun) { if (consumer instanceof MagpieServer) { + boolean gobpieconf = readGobPieConfiguration(); + if (!gobpieconf) return; log.info("New analysis started"); MagpieServer server = (MagpieServer) consumer; - Collection results = runAnalysisOnSelectedFiles(files); - server.consume(results, source()); - } - } - } - - /** - * Runs the command on CLI to generate the analysis results for opened files, - * reads in the output and converts it into a collection of AnalysisResults. - * - * @param files the files that have been opened in the editor. - */ - private Collection runAnalysisOnSelectedFiles(Collection files) { - - Collection analysisResults = new ArrayList<>(); - - for (Module file : files) { - if (file instanceof SourceFileModule) { - boolean successful = generateJson(file); + boolean successful = generateJson(); + Collection analysisResults = new ArrayList<>(); if (successful) analysisResults.addAll(readResultsFromJson()); + server.consume(analysisResults, source()); } } - return analysisResults; } + public ProcessResult runCommand(File dirPath) throws IOException, InvalidExitValueException, InterruptedException, TimeoutException { String[] command = this.getCommand(); log.debug("Waiting for Goblint to run..."); @@ -120,19 +107,10 @@ public ProcessResult runCommand(File dirPath) throws IOException, InvalidExitVal * @param file the file on which to run the analysis. * @return returns true if goblint finished the analysis and json was generated sucessfully, false otherwise */ - private boolean generateJson(Module file) { - SourceFileModule sourcefile = (SourceFileModule) file; - try { - // find sourcefile URL - this.sourcefileURL = new URL(magpieServer.getClientUri(sourcefile.getURL().toString())); - // file to be analyzed - String fileToAnalyze = sourcefileURL.getFile(); - // construct command to run - this.commands = new String[]{"goblint", "--conf", "goblint.json", "--set", "result", "json-messages", "-o", pathToJsonResult, fileToAnalyze}; - } catch (MalformedURLException e) { - log.error("An error occured while trying parse the url of the file to be analyzed. " + e.getMessage()); - return false; - } + private boolean generateJson() { + // construct command to run + this.commands = new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", pathToJsonResult, pathToCompilationDBDir}; + try { // run command log.info("Goblint run with command: " + String.join(" ", this.getCommand())); @@ -187,4 +165,29 @@ private Collection readResultsFromJson() { return results; } + private boolean readGobPieConfiguration() { + try { + log.debug("Reading GobPie configuration from json"); + Gson gson = new GsonBuilder().create(); + // Read json object + JsonObject jsonObject = JsonParser.parseReader(new FileReader(new File(pathToGobPieConf))).getAsJsonObject(); + // Convert json object to GobPieConfiguration object + GobPieConfiguration gobpieConfiguration = gson.fromJson(jsonObject, GobPieConfiguration.class); + pathToGoblintConf = System.getProperty("user.dir") + "/" + gobpieConfiguration.getGoblintConfPath(); + pathToCompilationDBDir = System.getProperty("user.dir") + "/" + gobpieConfiguration.getCompilationDatabaseDirPath(); + if (gobpieConfiguration.getGoblintConfPath().equals("") || gobpieConfiguration.getCompilationDatabaseDirPath().equals("")) { + log.debug("Configuration parameters missing from GobPie configuration file"); + magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Configuration parameters missing from GobPie configuration file.")); + return false; + } + log.debug("GobPie configuration read from json"); + } catch (JsonIOException | JsonSyntaxException e) { + throw new RuntimeException(e); + } catch (FileNotFoundException e) { + magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Could not locate GobPie configuration file." + e.getMessage())); + return false; + } + return true; + } + } diff --git a/src/main/java/Main.java b/src/main/java/Main.java index e4dc678..433de63 100644 --- a/src/main/java/Main.java +++ b/src/main/java/Main.java @@ -20,7 +20,7 @@ public static void main(String... args) { MagpieServer server = createServer(); log.info("Server created"); // launch the server only if there is a goblint conf file present - if (new File(System.getProperty("user.dir") + "/" + "goblint.json").exists()) { + if (new File(System.getProperty("user.dir") + "/" + "gobpie.json").exists()) { server.launchOnStdio(); log.info("Server launched"); } @@ -28,10 +28,8 @@ public static void main(String... args) { private static MagpieServer createServer() { // set up configuration for MagpieServer - ServerConfiguration defaultConfig = new ServerConfiguration(); - // trigger analysis when file is opened - defaultConfig.setDoAnalysisByOpen(true); - MagpieServer server = new MagpieServer(defaultConfig); + ServerConfiguration serverConfig = new ServerConfiguration(); + MagpieServer server = new MagpieServer(serverConfig); // define language String language = "c"; // add analysis to the MagpieServer From 116df04583922ce5f6607d2cc2aeb1b7ae8b3413 Mon Sep 17 00:00:00 2001 From: karoliineh Date: Thu, 13 Jan 2022 18:11:06 +0200 Subject: [PATCH 2/7] Compilation db build command is ran every time an analysis is stared (if provided) --- Readme.md | 20 +++++++++++++ src/main/java/GoblintAnalysis.java | 46 ++++++++++++++++-------------- 2 files changed, 44 insertions(+), 22 deletions(-) diff --git a/Readme.md b/Readme.md index 3674cef..7e89999 100644 --- a/Readme.md +++ b/Readme.md @@ -17,6 +17,26 @@ code . ``` The *switch name* (shown in the first column of `opam switch`) is the path to the goblint installation. +### Project prerequisites + +The project must have: +1. GobPie configuration file in project root with name "`gobpie.json`" +2. Goblint configuration file ([see examples](https://github.com/goblint/analyzer/tree/master/conf)) + +#### Gobpie configuration file + +Example configuration file `gobpie.json`: +``` +{ + "compilationDatabaseDirPath" : "build", + "goblintConfPath" : "goblint.json", + "compilationDBBuildCommands" : ["cmake", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "build"] +} +``` + +* `compilationDatabaseDirPath` - the relative path from project root to the folder containing the project's compilation database (required) +* `goblintConfPath` - the relative path from project root to the goblint configuration file (required) +* `compilationDBBuildCommands` - the command for building/updating the compilation database (optional) ## Developing diff --git a/src/main/java/GoblintAnalysis.java b/src/main/java/GoblintAnalysis.java index 6bbc453..d2b3c46 100644 --- a/src/main/java/GoblintAnalysis.java +++ b/src/main/java/GoblintAnalysis.java @@ -32,14 +32,15 @@ public class GoblintAnalysis implements ServerAnalysis { - final private MagpieServer magpieServer; - private String pathToJsonResult = System.getProperty("user.dir") + "/" + "analysisResults.json"; - private String pathToGobPieConf = System.getProperty("user.dir") + "/" + "gobpie.json"; + private final MagpieServer magpieServer; + private final String pathToJsonResult = System.getProperty("user.dir") + "/" + "analysisResults.json"; + private final String pathToGobPieConf = System.getProperty("user.dir") + "/" + "gobpie.json"; private String pathToGoblintConf; private String pathToCompilationDBDir; - private String[] commands; + private String[] compilationDBBuildCommand; + private String[] goblintRunCommand; - private Logger log; + private final Logger log; public GoblintAnalysis(MagpieServer server) { this.magpieServer = server; @@ -55,12 +56,6 @@ public String source() { return "GoblintAnalysis"; } - /** - * @return the CLI command including the arguments to be executed. - */ - public String[] getCommand() { - return this.commands; - } /** * The files to be analyzed. @@ -75,6 +70,13 @@ public void analyze(Collection files, AnalysisConsumer consume if (consumer instanceof MagpieServer) { boolean gobpieconf = readGobPieConfiguration(); if (!gobpieconf) return; + if (compilationDBBuildCommand != null && compilationDBBuildCommand.length > 0) { + try { + runCommand(new File(System.getProperty("user.dir")), compilationDBBuildCommand); + } catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) { + this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Warning, "Building compilation database failed. " + e.getMessage())); + } + } log.info("New analysis started"); MagpieServer server = (MagpieServer) consumer; boolean successful = generateJson(); @@ -86,8 +88,7 @@ public void analyze(Collection files, AnalysisConsumer consume } - public ProcessResult runCommand(File dirPath) throws IOException, InvalidExitValueException, InterruptedException, TimeoutException { - String[] command = this.getCommand(); + public ProcessResult runCommand(File dirPath, String[] command) throws IOException, InvalidExitValueException, InterruptedException, TimeoutException { log.debug("Waiting for Goblint to run..."); System.err.println("---------------------- Goblint's dump start ----------------------"); ProcessResult process = new ProcessExecutor() @@ -109,12 +110,12 @@ public ProcessResult runCommand(File dirPath) throws IOException, InvalidExitVal */ private boolean generateJson() { // construct command to run - this.commands = new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", pathToJsonResult, pathToCompilationDBDir}; + this.goblintRunCommand = new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", pathToJsonResult, pathToCompilationDBDir}; try { // run command - log.info("Goblint run with command: " + String.join(" ", this.getCommand())); - ProcessResult commandRunProcess = this.runCommand(new File(System.getProperty("user.dir"))); + log.info("Goblint run with command: " + String.join(" ", goblintRunCommand)); + ProcessResult commandRunProcess = runCommand(new File(System.getProperty("user.dir")), goblintRunCommand); if (commandRunProcess.getExitValue() != 0) { magpieServer.forwardMessageToClient( new MessageParams(MessageType.Error, @@ -125,7 +126,7 @@ private boolean generateJson() { log.info("Goblint finished analyzing."); return true; } catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) { - magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Running Goblint failed. " + e.getMessage())); + this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Running Goblint failed. " + e.getMessage())); return false; } } @@ -144,7 +145,7 @@ private Collection readResultsFromJson() { try { log.debug("Reading analysis results from json"); // Read json objects as an array - JsonArray resultArray = JsonParser.parseReader(new FileReader(new File(pathToJsonResult))).getAsJsonArray(); + JsonArray resultArray = JsonParser.parseReader(new FileReader(new File(this.pathToJsonResult))).getAsJsonArray(); GsonBuilder builder = new GsonBuilder(); // Add deserializer for tags builder.registerTypeAdapter(GoblintResult.tag.class, new TagInterfaceAdapter()); @@ -170,11 +171,12 @@ private boolean readGobPieConfiguration() { log.debug("Reading GobPie configuration from json"); Gson gson = new GsonBuilder().create(); // Read json object - JsonObject jsonObject = JsonParser.parseReader(new FileReader(new File(pathToGobPieConf))).getAsJsonObject(); + JsonObject jsonObject = JsonParser.parseReader(new FileReader(new File(this.pathToGobPieConf))).getAsJsonObject(); // Convert json object to GobPieConfiguration object GobPieConfiguration gobpieConfiguration = gson.fromJson(jsonObject, GobPieConfiguration.class); - pathToGoblintConf = System.getProperty("user.dir") + "/" + gobpieConfiguration.getGoblintConfPath(); - pathToCompilationDBDir = System.getProperty("user.dir") + "/" + gobpieConfiguration.getCompilationDatabaseDirPath(); + this.pathToGoblintConf = System.getProperty("user.dir") + "/" + gobpieConfiguration.getGoblintConfPath(); + this.pathToCompilationDBDir = System.getProperty("user.dir") + "/" + gobpieConfiguration.getCompilationDatabaseDirPath(); + this.compilationDBBuildCommand = gobpieConfiguration.getCompilationDBBuildCommands(); if (gobpieConfiguration.getGoblintConfPath().equals("") || gobpieConfiguration.getCompilationDatabaseDirPath().equals("")) { log.debug("Configuration parameters missing from GobPie configuration file"); magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Configuration parameters missing from GobPie configuration file.")); @@ -184,7 +186,7 @@ private boolean readGobPieConfiguration() { } catch (JsonIOException | JsonSyntaxException e) { throw new RuntimeException(e); } catch (FileNotFoundException e) { - magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Could not locate GobPie configuration file." + e.getMessage())); + this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Could not locate GobPie configuration file. " + e.getMessage())); return false; } return true; From 56d5fd4af941851a89c3fb768ac0673a68d454ba Mon Sep 17 00:00:00 2001 From: karoliineh Date: Thu, 13 Jan 2022 18:15:49 +0200 Subject: [PATCH 3/7] Update Log4J version --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 5a0dafa..f9f4e3d 100644 --- a/pom.xml +++ b/pom.xml @@ -28,12 +28,12 @@ org.apache.logging.log4j log4j-api - 2.14.1 + 2.15.0 org.apache.logging.log4j log4j-core - 2.14.1 + 2.15.0 From 0f3d7489a3fa6bd8db312f5587e4e18c54c55b43 Mon Sep 17 00:00:00 2001 From: karoliineh Date: Fri, 14 Jan 2022 18:06:41 +0200 Subject: [PATCH 4/7] Modified conf file and documentation --- Readme.md | 21 ++++++++++++----- src/main/java/GobPieConfiguration.java | 18 +++++++-------- src/main/java/GoblintAnalysis.java | 31 +++++++++++++++----------- src/main/java/GoblintResult.java | 6 ++--- 4 files changed, 45 insertions(+), 31 deletions(-) diff --git a/Readme.md b/Readme.md index 7e89999..d0dfab5 100644 --- a/Readme.md +++ b/Readme.md @@ -28,15 +28,24 @@ The project must have: Example configuration file `gobpie.json`: ``` { - "compilationDatabaseDirPath" : "build", - "goblintConfPath" : "goblint.json", - "compilationDBBuildCommands" : ["cmake", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "build"] + "goblintConf" : "goblint.json", + "files" : ["./build"], + "preAnalyzeCommand" : ["cmake", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "build"] } ``` -* `compilationDatabaseDirPath` - the relative path from project root to the folder containing the project's compilation database (required) -* `goblintConfPath` - the relative path from project root to the goblint configuration file (required) -* `compilationDBBuildCommands` - the command for building/updating the compilation database (optional) +* `goblintConf` - the relative path from project root to the goblint configuration file (required) +* `files` - the relative paths from project root to the files to be analysed (required) +* `preAnalyzeCommand` - the command to run before analysing (e.g. command for building/updating the compilation database for some automation) (optional) + +Example values for `files`: +* analyse files according to a compilation database: + * `["."]` (current directory should have the database) + * `["./build"]` (build directory should have the database) + * `["./build/compile_commands.json"]` (direct path to the database, not its directory) +* analyse specified file(s) from the project: + * `["./01-assert.c"]` (single file for analysis without database) + * `["./01-assert.c", "extra.c"]` (multiple files for analysis without database) ## Developing diff --git a/src/main/java/GobPieConfiguration.java b/src/main/java/GobPieConfiguration.java index a5e0ab4..2685c5d 100644 --- a/src/main/java/GobPieConfiguration.java +++ b/src/main/java/GobPieConfiguration.java @@ -1,19 +1,19 @@ public class GobPieConfiguration { - private String compilationDatabaseDirPath = ""; - private String goblintConfPath = ""; - private String[] compilationDBBuildCommands; + private String goblintConf = ""; + private String[] files; + private String[] preAnalyzeCommand; - public String getCompilationDatabaseDirPath() { - return this.compilationDatabaseDirPath; + public String getGoblintConf() { + return this.goblintConf; } - public String getGoblintConfPath() { - return this.goblintConfPath; + public String[] getFiles() { + return this.files; } - public String[] getCompilationDBBuildCommands() { - return this.compilationDBBuildCommands; + public String[] getPreAnalyzeCommand() { + return this.preAnalyzeCommand; } } diff --git a/src/main/java/GoblintAnalysis.java b/src/main/java/GoblintAnalysis.java index d2b3c46..b2ea025 100644 --- a/src/main/java/GoblintAnalysis.java +++ b/src/main/java/GoblintAnalysis.java @@ -2,9 +2,11 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; +import java.lang.reflect.Array; import java.net.MalformedURLException; import java.util.*; import java.util.concurrent.TimeoutException; +import java.util.stream.Stream; import com.ibm.wala.classLoader.Module; @@ -33,11 +35,11 @@ public class GoblintAnalysis implements ServerAnalysis { private final MagpieServer magpieServer; - private final String pathToJsonResult = System.getProperty("user.dir") + "/" + "analysisResults.json"; - private final String pathToGobPieConf = System.getProperty("user.dir") + "/" + "gobpie.json"; + private File jsonResult = new File("analysisResults.json"); + private File gobPieConf = new File("gobpie.json"); private String pathToGoblintConf; - private String pathToCompilationDBDir; - private String[] compilationDBBuildCommand; + private String[] filesToAnalyze; + private String[] preAnalyzeCommand; private String[] goblintRunCommand; private final Logger log; @@ -70,9 +72,9 @@ public void analyze(Collection files, AnalysisConsumer consume if (consumer instanceof MagpieServer) { boolean gobpieconf = readGobPieConfiguration(); if (!gobpieconf) return; - if (compilationDBBuildCommand != null && compilationDBBuildCommand.length > 0) { + if (preAnalyzeCommand != null && preAnalyzeCommand.length > 0) { try { - runCommand(new File(System.getProperty("user.dir")), compilationDBBuildCommand); + runCommand(new File(System.getProperty("user.dir")), preAnalyzeCommand); } catch (IOException | InvalidExitValueException | InterruptedException | TimeoutException e) { this.magpieServer.forwardMessageToClient(new MessageParams(MessageType.Warning, "Building compilation database failed. " + e.getMessage())); } @@ -110,7 +112,10 @@ public ProcessResult runCommand(File dirPath, String[] command) throws IOExcepti */ private boolean generateJson() { // construct command to run - this.goblintRunCommand = new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", pathToJsonResult, pathToCompilationDBDir}; + this.goblintRunCommand = Stream.concat( + Arrays.stream(new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", jsonResult.getAbsolutePath()}), + Arrays.stream(filesToAnalyze)) + .toArray(size -> (String[]) Array.newInstance(filesToAnalyze.getClass().getComponentType(), size)); try { // run command @@ -145,7 +150,7 @@ private Collection readResultsFromJson() { try { log.debug("Reading analysis results from json"); // Read json objects as an array - JsonArray resultArray = JsonParser.parseReader(new FileReader(new File(this.pathToJsonResult))).getAsJsonArray(); + JsonArray resultArray = JsonParser.parseReader(new FileReader(jsonResult)).getAsJsonArray(); GsonBuilder builder = new GsonBuilder(); // Add deserializer for tags builder.registerTypeAdapter(GoblintResult.tag.class, new TagInterfaceAdapter()); @@ -171,13 +176,13 @@ private boolean readGobPieConfiguration() { log.debug("Reading GobPie configuration from json"); Gson gson = new GsonBuilder().create(); // Read json object - JsonObject jsonObject = JsonParser.parseReader(new FileReader(new File(this.pathToGobPieConf))).getAsJsonObject(); + JsonObject jsonObject = JsonParser.parseReader(new FileReader(gobPieConf)).getAsJsonObject(); // Convert json object to GobPieConfiguration object GobPieConfiguration gobpieConfiguration = gson.fromJson(jsonObject, GobPieConfiguration.class); - this.pathToGoblintConf = System.getProperty("user.dir") + "/" + gobpieConfiguration.getGoblintConfPath(); - this.pathToCompilationDBDir = System.getProperty("user.dir") + "/" + gobpieConfiguration.getCompilationDatabaseDirPath(); - this.compilationDBBuildCommand = gobpieConfiguration.getCompilationDBBuildCommands(); - if (gobpieConfiguration.getGoblintConfPath().equals("") || gobpieConfiguration.getCompilationDatabaseDirPath().equals("")) { + this.pathToGoblintConf = new File(gobpieConfiguration.getGoblintConf()).getAbsolutePath().toString(); + this.filesToAnalyze = gobpieConfiguration.getFiles(); + this.preAnalyzeCommand = gobpieConfiguration.getPreAnalyzeCommand(); + if (gobpieConfiguration.getGoblintConf().equals("") || gobpieConfiguration.getFiles() == null || gobpieConfiguration.getFiles().length < 1) { log.debug("Configuration parameters missing from GobPie configuration file"); magpieServer.forwardMessageToClient(new MessageParams(MessageType.Error, "Configuration parameters missing from GobPie configuration file.")); return false; diff --git a/src/main/java/GoblintResult.java b/src/main/java/GoblintResult.java index 9d62619..6f1c4e2 100644 --- a/src/main/java/GoblintResult.java +++ b/src/main/java/GoblintResult.java @@ -1,8 +1,8 @@ import com.ibm.wala.cast.tree.CAstSourcePositionMap.Position; import com.ibm.wala.util.collections.Pair; +import java.io.File; import java.net.MalformedURLException; -import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; @@ -76,14 +76,14 @@ public List convert() throws MalformedURLException { if (multipiece.group_text == null) { String message = tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " " + multipiece.text; - GoblintPosition pos = new GoblintPosition(multipiece.loc.line, multipiece.loc.endLine, multipiece.loc.column - 1, multipiece.loc.endColumn - 1, new URL("file:" + multipiece.loc.file)); + GoblintPosition pos = new GoblintPosition(multipiece.loc.line, multipiece.loc.endLine, multipiece.loc.column - 1, multipiece.loc.endColumn - 1, new File(multipiece.loc.file).toURI().toURL()); GoblintAnalysisResult result = new GoblintAnalysisResult(pos, message, severity); results.add(result); } else { List intermresults = new ArrayList<>(); List pieces = multipiece.pieces; for (multipiece.pieces piece : pieces) { - GoblintPosition pos = new GoblintPosition(piece.loc.line, piece.loc.endLine, piece.loc.column - 1, piece.loc.endColumn - 1, new URL("file:" + piece.loc.file)); + GoblintPosition pos = new GoblintPosition(piece.loc.line, piece.loc.endLine, piece.loc.column - 1, piece.loc.endColumn - 1, new File(piece.loc.file).toURI().toURL()); GoblintAnalysisResult result = new GoblintAnalysisResult(pos, tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " Group: " + multipiece.group_text, piece.text, severity); From 5116aca4f27c8812deab80087fc99a98181dd2ff Mon Sep 17 00:00:00 2001 From: karoliineh Date: Wed, 19 Jan 2022 15:27:58 +0200 Subject: [PATCH 5/7] Update MagPieBridge version --- pom.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index f9f4e3d..2758bf8 100644 --- a/pom.xml +++ b/pom.xml @@ -6,10 +6,10 @@ goblintanalyzer 0.0.1-SNAPSHOT - - com.github.magpiebridge - magpiebridge - 0.1.2 + + com.github.magpiebridge + magpiebridge + 0.1.3 From df63a0c08f96dc589803305ef4475593d1ace33e Mon Sep 17 00:00:00 2001 From: karoliineh Date: Thu, 20 Jan 2022 14:54:30 +0200 Subject: [PATCH 6/7] adjusted to new goblint json output format --- src/main/java/GoblintAnalysis.java | 30 ++---- src/main/java/GoblintResult.java | 143 ++++++++++++++----------- src/main/java/TagInterfaceAdapter.java | 4 +- 3 files changed, 93 insertions(+), 84 deletions(-) diff --git a/src/main/java/GoblintAnalysis.java b/src/main/java/GoblintAnalysis.java index b2ea025..77ab663 100644 --- a/src/main/java/GoblintAnalysis.java +++ b/src/main/java/GoblintAnalysis.java @@ -11,7 +11,6 @@ import com.ibm.wala.classLoader.Module; import magpiebridge.core.AnalysisConsumer; -import magpiebridge.core.AnalysisResult; import magpiebridge.core.ServerAnalysis; import magpiebridge.core.MagpieServer; @@ -20,7 +19,6 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; import com.google.gson.JsonIOException; import com.google.gson.JsonObject; import com.google.gson.JsonParser; @@ -32,6 +30,7 @@ import org.zeroturnaround.exec.ProcessExecutor; import org.zeroturnaround.exec.ProcessResult; + public class GoblintAnalysis implements ServerAnalysis { private final MagpieServer magpieServer; @@ -41,6 +40,7 @@ public class GoblintAnalysis implements ServerAnalysis { private String[] filesToAnalyze; private String[] preAnalyzeCommand; private String[] goblintRunCommand; + // private List projectFiles; // for future use private final Logger log; @@ -81,10 +81,7 @@ public void analyze(Collection files, AnalysisConsumer consume } log.info("New analysis started"); MagpieServer server = (MagpieServer) consumer; - boolean successful = generateJson(); - Collection analysisResults = new ArrayList<>(); - if (successful) analysisResults.addAll(readResultsFromJson()); - server.consume(analysisResults, source()); + if (generateJson()) server.consume(new ArrayList<>(readResultsFromJson()), source()); } } } @@ -144,31 +141,22 @@ private boolean generateJson() { * @return A collection of GoblintAnalysisResult objects. */ private Collection readResultsFromJson() { - - Collection results = new ArrayList<>(); - try { log.debug("Reading analysis results from json"); // Read json objects as an array - JsonArray resultArray = JsonParser.parseReader(new FileReader(jsonResult)).getAsJsonArray(); + JsonObject json = JsonParser.parseReader(new FileReader(jsonResult)).getAsJsonObject(); GsonBuilder builder = new GsonBuilder(); // Add deserializer for tags - builder.registerTypeAdapter(GoblintResult.tag.class, new TagInterfaceAdapter()); + builder.registerTypeAdapter(GoblintResult.Message.tag.class, new TagInterfaceAdapter()); Gson gson = builder.create(); - // For each JsonObject - for (int i = 0; i < resultArray.size(); i++) { - // Deserailize them into GoblintResult objects - GoblintResult goblintResult = gson.fromJson(resultArray.get(i), GoblintResult.class); - // Convert GoblintResult object to a list of GoblintAnalysisResults - results.addAll(goblintResult.convert()); - } + GoblintResult goblintResult = gson.fromJson(json, GoblintResult.class); + Collection results = goblintResult.convert(); + // this.projectFiles = goblintResult.getFiles(); log.debug("Analysis results read from json"); - + return results; } catch (JsonIOException | JsonSyntaxException | FileNotFoundException | MalformedURLException e) { throw new RuntimeException(e); } - - return results; } private boolean readGobPieConfiguration() { diff --git a/src/main/java/GoblintResult.java b/src/main/java/GoblintResult.java index 6f1c4e2..4b05259 100644 --- a/src/main/java/GoblintResult.java +++ b/src/main/java/GoblintResult.java @@ -4,60 +4,55 @@ import java.io.File; import java.net.MalformedURLException; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.Map.Entry; import java.util.stream.Collectors; + public class GoblintResult { - private List tags = new ArrayList<>(); - private String severity; - private multipiece multipiece; + private Map> files; + private List messages = new ArrayList<>(); - public static interface tag { + static class Message { - public String toString(); + private List tags = new ArrayList<>(); + private String severity; + private multipiece multipiece; - static class Category implements tag { - private List Category = new ArrayList(); + static interface tag { - @Override - public String toString() { - return (Category.size() > 0) ? "[" + String.join(" > ", Category) + "]" : ""; - } + public String toString(); - } + static class Category implements tag { + private List Category = new ArrayList(); - static class CWE implements tag { - private Integer CWE; + @Override + public String toString() { + return (Category.size() > 0) ? "[" + String.join(" > ", Category) + "]" : ""; + } - @Override - public String toString() { - return (CWE != null) ? "[CWE-" + CWE + "]" : ""; } - } - } - - static class multipiece { - private loc loc; - private String text; - private String group_text; - private List pieces = new ArrayList(); - - static class loc { - - private String file; - private int line; - private int column; - private int endLine; - private int endColumn; + static class CWE implements tag { + private Integer CWE; + @Override + public String toString() { + return (CWE != null) ? "[CWE-" + CWE + "]" : ""; + } + } } - static class pieces { + static class multipiece { - private String text; private loc loc; + private String text; + private String group_text; + private List pieces = new ArrayList(); static class loc { @@ -66,45 +61,71 @@ static class loc { private int column; private int endLine; private int endColumn; + } - } + static class pieces { + + private String text; + private loc loc; + + static class loc { + + private String file; + private int line; + private int column; + private int endLine; + private int endColumn; + } + } + } } public List convert() throws MalformedURLException { List results = new ArrayList<>(); - if (multipiece.group_text == null) { - String message = tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " " + multipiece.text; - GoblintPosition pos = new GoblintPosition(multipiece.loc.line, multipiece.loc.endLine, multipiece.loc.column - 1, multipiece.loc.endColumn - 1, new File(multipiece.loc.file).toURI().toURL()); - GoblintAnalysisResult result = new GoblintAnalysisResult(pos, message, severity); - results.add(result); - } else { - List intermresults = new ArrayList<>(); - List pieces = multipiece.pieces; - for (multipiece.pieces piece : pieces) { - GoblintPosition pos = new GoblintPosition(piece.loc.line, piece.loc.endLine, piece.loc.column - 1, piece.loc.endColumn - 1, new File(piece.loc.file).toURI().toURL()); - GoblintAnalysisResult result = new GoblintAnalysisResult(pos, - tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " Group: " + multipiece.group_text, - piece.text, severity); - intermresults.add(result); - } - // Add related warnings to all the group elements - List addedRelated = new ArrayList<>(); - for (GoblintAnalysisResult res1 : intermresults) { - List> related = new ArrayList<>(); - for (GoblintAnalysisResult res2 : intermresults) { - if (res1 != res2) { - related.add(Pair.make(res2.position(), res2.text())); + for (Message message : messages) { + if (message.multipiece.group_text == null) { + String msg = message.tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " " + message.multipiece.text; + GoblintPosition pos = new GoblintPosition(message.multipiece.loc.line, message.multipiece.loc.endLine, message.multipiece.loc.column - 1, message.multipiece.loc.endColumn - 1, new File(message.multipiece.loc.file).toURI().toURL()); + GoblintAnalysisResult result = new GoblintAnalysisResult(pos, msg, message.severity); + results.add(result); + } else { + List intermresults = new ArrayList<>(); + List pieces = message.multipiece.pieces; + for (Message.multipiece.pieces piece : pieces) { + GoblintPosition pos = new GoblintPosition(piece.loc.line, piece.loc.endLine, piece.loc.column - 1, piece.loc.endColumn - 1, new File(piece.loc.file).toURI().toURL()); + GoblintAnalysisResult result = new GoblintAnalysisResult(pos, + message.tags.stream().map(tag -> tag.toString()).collect(Collectors.joining("")) + " Group: " + message.multipiece.group_text, + piece.text, message.severity); + intermresults.add(result); + } + // Add related warnings to all the group elements + List addedRelated = new ArrayList<>(); + for (GoblintAnalysisResult res1 : intermresults) { + List> related = new ArrayList<>(); + for (GoblintAnalysisResult res2 : intermresults) { + if (res1 != res2) { + related.add(Pair.make(res2.position(), res2.text())); + } } + addedRelated.add(new GoblintAnalysisResult(res1.position(), res1.group_text() + "\n" + res1.text(), + res1.severityStr(), related)); } - addedRelated.add(new GoblintAnalysisResult(res1.position(), res1.group_text() + "\n" + res1.text(), - res1.severityStr(), related)); + results.addAll(addedRelated); } - results.addAll(addedRelated); } return results; } + public List getFiles() { + Set allFiles = new HashSet<>(); + for (Entry> entry : files.entrySet()) { + allFiles.add(entry.getKey()); + allFiles.addAll(entry.getValue()); + } + return new ArrayList<>(allFiles); + } + } diff --git a/src/main/java/TagInterfaceAdapter.java b/src/main/java/TagInterfaceAdapter.java index f147bfa..c5a59d1 100644 --- a/src/main/java/TagInterfaceAdapter.java +++ b/src/main/java/TagInterfaceAdapter.java @@ -12,9 +12,9 @@ public class TagInterfaceAdapter implements JsonDeserializer { public Object deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { JsonObject jsonObject = jsonElement.getAsJsonObject(); if (jsonObject.has("Category")) - return jsonDeserializationContext.deserialize(jsonObject, GoblintResult.tag.Category.class); + return jsonDeserializationContext.deserialize(jsonObject, GoblintResult.Message.tag.Category.class); if (jsonObject.has("CWE")) - return jsonDeserializationContext.deserialize(jsonObject, GoblintResult.tag.CWE.class); + return jsonDeserializationContext.deserialize(jsonObject, GoblintResult.Message.tag.CWE.class); return null; } From a9fed532213a71383cdace8f9b189256c144f165 Mon Sep 17 00:00:00 2001 From: karoliineh Date: Thu, 20 Jan 2022 15:25:54 +0200 Subject: [PATCH 7/7] Refactoring --- src/main/java/GoblintAnalysis.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/GoblintAnalysis.java b/src/main/java/GoblintAnalysis.java index 77ab663..6b4d44f 100644 --- a/src/main/java/GoblintAnalysis.java +++ b/src/main/java/GoblintAnalysis.java @@ -2,7 +2,6 @@ import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; -import java.lang.reflect.Array; import java.net.MalformedURLException; import java.util.*; import java.util.concurrent.TimeoutException; @@ -112,7 +111,7 @@ private boolean generateJson() { this.goblintRunCommand = Stream.concat( Arrays.stream(new String[]{"goblint", "--conf", pathToGoblintConf, "--set", "result", "json-messages", "-o", jsonResult.getAbsolutePath()}), Arrays.stream(filesToAnalyze)) - .toArray(size -> (String[]) Array.newInstance(filesToAnalyze.getClass().getComponentType(), size)); + .toArray(String[]::new); try { // run command