Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OutOfMemory Handling Improvement #84

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
target
.idea
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,16 @@ old-hits/log4j-core-2.0-beta2.jar contains Log4J-2.x <= 2.0-beta8 _POTENTIALLY
```
java -jar log4j-detector-2021.12.29.jar

Usage: java -jar log4j-detector-2021.12.29.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]
Usage: java -jar log4j-detector-2021.12.29.jar [--verbose] [--json] [--stdin] [--exclude=X] [--oomThreshold=Y] [paths to scan...]

--json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)
--stdin - Read STDIN for paths to explore (one path per line)
--exclude=X - Where X is a JSON list containing full paths to exclude. Must be valid JSON.
--json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)
--stdin - Read STDIN for paths to explore (one path per line)
--exclude=X - Where X is a JSON list containing full paths to exclude. Must be valid JSON.

Example: --exclude='["/dev", "/media", "Z:\TEMP"]'
Example: --exclude='["/dev", "/media", "Z:\TEMP"]'

--oomThreshold - Specifies how many OutOfMemoryErrors should be catched during analyzing ZIP files before aborting the run as an int.
If 0 or negative, no OutOfMemoryError will be catched. If omitted, defaults to 10.
Exit codes: 0 = No vulnerable Log4J versions found.
1 = At least one legacy Log4J 1.x version found.
2 = At least one vulnerable Log4J version found.
Expand Down
56 changes: 49 additions & 7 deletions src/main/java/com/mergebase/log4j/Log4JDetector.java
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,13 @@ public class Log4JDetector {
// This occurs in "DataSourceConnectionSource.class" in 2.17.1 and friends.
private static final byte[] IS_CVE_2021_44832_SAFE = Bytes.fromString("JNDI must be enabled by setting log4j2.enableJndiJdbc=true");

private static final String SWITCH_OOM_THRESHOLD = "--oomThreshold=";

private static boolean verbose = false;
private static boolean debug = false;
private static boolean json = false;
private static int oomThreshold = 10;
private static int oomCounter = 0;
private static Set<String> excludes = new TreeSet<String>();
private static boolean foundHits = false;
private static boolean foundLog4j1 = false;
Expand Down Expand Up @@ -132,6 +136,19 @@ public static void main(String[] args) throws IOException {
byte[] b = Bytes.streamToBytes(System.in);
String s = new String(b, Bytes.UTF_8);
stdinLines = Strings.intoLines(s);
} else if (argOrig.startsWith(SWITCH_OOM_THRESHOLD)) {
String thresholdString = argOrig.substring(SWITCH_OOM_THRESHOLD.length());
it.remove();
try {
oomThreshold = Integer.parseInt(thresholdString);
// don't need to check against negative numbers here - the simply the first OOM will lead to
// abort as we begin counting by 0;
} catch(NumberFormatException e) {
System.err.println("Illegal value for " + SWITCH_OOM_THRESHOLD + "<" + thresholdString + ">, you need to specify an int. " +
"Aborting ... Stack Trace Follows:");
e.printStackTrace();
System.exit(103);
}
} else {
File f;
if (argOrig.length() == 2 && ':' == argOrig.charAt(1) && Character.isLetter(argOrig.charAt(0))) {
Expand All @@ -149,26 +166,31 @@ public static void main(String[] args) throws IOException {

if (argsList.isEmpty()) {
System.out.println();
System.out.println("Usage: java -jar log4j-detector-2021.12.29.jar [--verbose] [--json] [--stdin] [--exclude=X] [paths to scan...]");
System.out.println("Usage: java -jar log4j-detector-<upstreamversion>.jar [--verbose] [--json] " +
"[--stdin] [--exclude=X] [--oomThreshold=Y] [paths to scan...]");
System.out.println();
System.out.println(" --json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)");
System.out.println(" --stdin - Parse STDIN for paths to explore.");
System.out.println(" --exclude=X - Where X is a JSON list containing full paths to exclude. Must be valid JSON.");
System.out.println(" --json - Output STDOUT results in JSON. (Errors/warning still emitted to STDERR)");
System.out.println(" --stdin - Parse STDIN for paths to explore.");
System.out.println(" --exclude=X - Where X is a JSON list containing full paths to exclude. Must be valid JSON.");
System.out.println();
System.out.println(" Example: --exclude='[\"/dev\", \"/media\", \"Z:\\TEMP\"]' ");
System.out.println(" Example: --exclude='[\"/dev\", \"/media\", \"Z:\\TEMP\"]' ");
System.out.println();
System.out.println(" --oomThreshold - Specifies how many OutOfMemoryErrors should be catched during analyzing ZIP files before " +
"aborting the run as an int. If 0 or negative, no OutOfMemoryError will be catched. If omitted, defaults to 10.");
System.out.println();
System.out.println("Exit codes: 0 = No vulnerable Log4J versions found.");
System.out.println(" 1 = At least one legacy Log4J 1.x version found.");
System.out.println(" 2 = At least one vulnerable Log4J 2.x version found.");
System.out.println();
System.out.println("About - MergeBase log4j detector (version 2021.12.29)");
System.out.println("About - MergeBase log4j detector (version <upstreamversion>)");
System.out.println("Docs - https://github.com/mergebase/log4j-detector ");
System.out.println("(C) Copyright 2021 Mergebase Software Inc. Licensed to you via GPLv3.");
System.out.println();
System.exit(100);
}

System.err.println("-- github.com/mergebase/log4j-detector v2021.12.29 (by mergebase.com) analyzing paths (could take a while).");
System.err.println("-- github.com/mergebase/log4j-detector (by mergebase.com) <upstreamversion> analyzing " +
"paths (could take a while).");
System.err.println("-- Note: specify the '--verbose' flag to have every file examined printed to STDERR.");
if (json) {
System.out.println("{\"hits\":[");
Expand Down Expand Up @@ -666,6 +688,26 @@ public void close() {
} catch (Exception e) {
System.err.println("-- Problem: " + zipFile.getPath() + " FAILED: " + e);
e.printStackTrace(System.err);
} catch (OutOfMemoryError oom) {
// Safety Guard for multiple OutOfMemories on low free Heap
// Threshold oomThreshold is checked to limit this
// in some cases a new OutOfMemory might rise from within the catch block - not attempting to handle that
// though ...
if(oomCounter < oomThreshold) {
oomCounter++;
System.err.println("-- Problem: OutOfMemoryError for path: <" + zipFile.getPath() + ">");
System.err.println("oomCounter now: <" + oomCounter + ">, Stack Trace follows:");
oom.printStackTrace(System.err);
} else {
oomCounter++;
System.err.println("-- Problem: OutOfMemoryError for path: <" + zipFile.getPath() + ">");
System.err.println("oom Threshold reached by oomCounter now: <" + oomCounter + ">, ABORTING, Stack " +
"Trace follows:");
oom.printStackTrace(System.err);
System.err.flush();
System.exit(104);
}

} finally {
myZipper.close();
}
Expand Down