From 2900b4b902e93a4167b7ea230b49a009b80bee57 Mon Sep 17 00:00:00 2001 From: FerrumBrain Date: Wed, 5 Feb 2025 20:37:08 +0100 Subject: [PATCH 1/5] bipredicate instead of biconsumer --- .../jazzer/driver/FuzzTargetRunner.java | 18 +++++++++--------- .../jazzer/junit/FuzzTestExecutor.java | 7 ++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java b/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java index 0660928e4..9181f3c68 100644 --- a/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java +++ b/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java @@ -50,7 +50,7 @@ import java.util.Locale; import java.util.Objects; import java.util.Set; -import java.util.function.BiConsumer; +import java.util.function.BiPredicate; import java.util.stream.Stream; import sun.misc.Unsafe; @@ -119,7 +119,7 @@ public final class FuzzTargetRunner { private static final boolean useFuzzedDataProvider; private static final ArgumentsMutator mutator; private static final ReproducerTemplate reproducerTemplate; - private static BiConsumer fatalFindingHandlerForJUnit; + private static BiPredicate isFatalFindingForJUnit; static { FuzzTargetHolder.FuzzTarget fuzzTarget = FuzzTargetHolder.fuzzTarget; @@ -293,15 +293,15 @@ private static int runOne(long dataPtr, int dataLength) { emitDedupToken && (keepGoing == 0 || Long.compareUnsigned(ignoredTokens.size(), keepGoing) < 0); boolean isFuzzingFromCommandLine = - fatalFindingHandlerForJUnit == null || Opt.isJUnitAndCommandLine.get(); + isFatalFindingForJUnit == null || Opt.isJUnitAndCommandLine.get(); // In case of --keep_going, only the last finding is reported to JUnit as a Java object, all // previous ones are merely printed. When fuzzing from the command line, we always print all // findings. if (isFuzzingFromCommandLine || continueFuzzing) { Log.finding(finding); } - if (fatalFindingHandlerForJUnit != null && !continueFuzzing) { - fatalFindingHandlerForJUnit.accept(data, finding); + if (isFatalFindingForJUnit != null) { + continueFuzzing = continueFuzzing && !isFatalFindingForJUnit.test(data, finding); } if (emitDedupToken) { // Has to be printed to stdout as it is parsed by libFuzzer when minimizing a crash. It does @@ -322,7 +322,7 @@ private static int runOne(long dataPtr, int dataLength) { // that satisfies the same purpose. // It also doesn't support the mutator framework yet as that requires implementing Java code // generation for mutators. - if (fatalFindingHandlerForJUnit == null && !useMutatorFramework) { + if (isFatalFindingForJUnit == null && !useMutatorFramework) { dumpReproducer(data); } @@ -342,7 +342,7 @@ private static int runOne(long dataPtr, int dataLength) { Opt.autofuzzIgnore.get().stream(), Stream.of(finding.getClass().getName())) .collect(joining(",")))); } - if (fatalFindingHandlerForJUnit == null) { + if (isFatalFindingForJUnit == null) { // When running a legacy fuzzerTestOneInput test, exit now with the correct exit code. // This will trigger the shutdown hook that runs fuzzerTearDown. System.exit(JAZZER_FINDING_EXIT_CODE); @@ -443,8 +443,8 @@ public static int startLibFuzzer(List args) { } public static void registerFatalFindingHandlerForJUnit( - BiConsumer findingHandler) { - FuzzTargetRunner.fatalFindingHandlerForJUnit = Objects.requireNonNull(findingHandler); + BiPredicate findingHandler) { + FuzzTargetRunner.isFatalFindingForJUnit = Objects.requireNonNull(findingHandler); } private static void shutdown() { diff --git a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java index 422b31079..21bf43e49 100644 --- a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java +++ b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java @@ -43,7 +43,7 @@ import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.BiConsumer; +import java.util.function.BiPredicate; import java.util.function.Supplier; import java.util.stream.Stream; import org.junit.jupiter.api.Timeout; @@ -318,11 +318,12 @@ public Optional execute( AtomicReference atomicFinding = new AtomicReference<>(); try { // Non-fatal findings (with --keep_going) are logged by FuzzTargetRunner. - BiConsumer consumer = + BiPredicate predicate = (a, b) -> { atomicFinding.set(b); + return true; }; - FuzzTargetRunner.registerFatalFindingHandlerForJUnit(consumer); + FuzzTargetRunner.registerFatalFindingHandlerForJUnit(predicate); } catch (Throwable throwable) { // Exception during initialization of FuzzTargetRunner, e.g. unsupported // parameter type in fuzz target method. Rethrow as FuzzTestConfigurationError. From af6e99047bc7911c18820d2efb22fe3734ef044e Mon Sep 17 00:00:00 2001 From: FerrumBrain Date: Thu, 6 Feb 2025 11:30:14 +0100 Subject: [PATCH 2/5] fix tests --- .../code_intelligence/jazzer/junit/FuzzTestExecutor.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java index 21bf43e49..0758c4fc4 100644 --- a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java +++ b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java @@ -42,6 +42,7 @@ import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiPredicate; import java.util.function.Supplier; @@ -318,10 +319,12 @@ public Optional execute( AtomicReference atomicFinding = new AtomicReference<>(); try { // Non-fatal findings (with --keep_going) are logged by FuzzTargetRunner. + AtomicInteger counter = new AtomicInteger(); BiPredicate predicate = (a, b) -> { - atomicFinding.set(b); - return true; + if(counter.incrementAndGet() == Opt.keepGoing.get()) + atomicFinding.set(b); + return counter.get() == Opt.keepGoing.get(); }; FuzzTargetRunner.registerFatalFindingHandlerForJUnit(predicate); } catch (Throwable throwable) { From 8ce9eac22bc20e52499c2b542539d15ebe53cfa8 Mon Sep 17 00:00:00 2001 From: FerrumBrain Date: Thu, 6 Feb 2025 11:34:22 +0100 Subject: [PATCH 3/5] fix format --- .../com/code_intelligence/jazzer/junit/FuzzTestExecutor.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java index 0758c4fc4..1e19a9412 100644 --- a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java +++ b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java @@ -322,8 +322,7 @@ public Optional execute( AtomicInteger counter = new AtomicInteger(); BiPredicate predicate = (a, b) -> { - if(counter.incrementAndGet() == Opt.keepGoing.get()) - atomicFinding.set(b); + if (counter.incrementAndGet() == Opt.keepGoing.get()) atomicFinding.set(b); return counter.get() == Opt.keepGoing.get(); }; FuzzTargetRunner.registerFatalFindingHandlerForJUnit(predicate); From 30efea0e9bede0101dbd47cd77d42862282b3cac Mon Sep 17 00:00:00 2001 From: FerrumBrain Date: Thu, 6 Feb 2025 11:44:12 +0100 Subject: [PATCH 4/5] fix tests --- .../com/code_intelligence/jazzer/junit/FuzzTestExecutor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java index 1e19a9412..67dc977bb 100644 --- a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java +++ b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java @@ -319,11 +319,11 @@ public Optional execute( AtomicReference atomicFinding = new AtomicReference<>(); try { // Non-fatal findings (with --keep_going) are logged by FuzzTargetRunner. - AtomicInteger counter = new AtomicInteger(); + AtomicInteger counter = new AtomicInteger(0); BiPredicate predicate = (a, b) -> { if (counter.incrementAndGet() == Opt.keepGoing.get()) atomicFinding.set(b); - return counter.get() == Opt.keepGoing.get(); + return counter.get() >= Opt.keepGoing.get(); }; FuzzTargetRunner.registerFatalFindingHandlerForJUnit(predicate); } catch (Throwable throwable) { From 69816cca419af6bb58fae8fd502ca8781402a425 Mon Sep 17 00:00:00 2001 From: FerrumBrain Date: Thu, 6 Feb 2025 12:26:23 +0100 Subject: [PATCH 5/5] fix tests + renaming --- .../jazzer/driver/FuzzTargetRunner.java | 17 +++++++++-------- .../jazzer/junit/FuzzTestExecutor.java | 4 ++-- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java b/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java index 9181f3c68..db25a9956 100644 --- a/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java +++ b/src/main/java/com/code_intelligence/jazzer/driver/FuzzTargetRunner.java @@ -119,7 +119,7 @@ public final class FuzzTargetRunner { private static final boolean useFuzzedDataProvider; private static final ArgumentsMutator mutator; private static final ReproducerTemplate reproducerTemplate; - private static BiPredicate isFatalFindingForJUnit; + private static BiPredicate fatalFindingDeterminatorForJUnit; static { FuzzTargetHolder.FuzzTarget fuzzTarget = FuzzTargetHolder.fuzzTarget; @@ -293,15 +293,16 @@ private static int runOne(long dataPtr, int dataLength) { emitDedupToken && (keepGoing == 0 || Long.compareUnsigned(ignoredTokens.size(), keepGoing) < 0); boolean isFuzzingFromCommandLine = - isFatalFindingForJUnit == null || Opt.isJUnitAndCommandLine.get(); + fatalFindingDeterminatorForJUnit == null || Opt.isJUnitAndCommandLine.get(); // In case of --keep_going, only the last finding is reported to JUnit as a Java object, all // previous ones are merely printed. When fuzzing from the command line, we always print all // findings. if (isFuzzingFromCommandLine || continueFuzzing) { Log.finding(finding); } - if (isFatalFindingForJUnit != null) { - continueFuzzing = continueFuzzing && !isFatalFindingForJUnit.test(data, finding); + if (fatalFindingDeterminatorForJUnit != null) { + boolean isFatal = fatalFindingDeterminatorForJUnit.test(data, finding); + continueFuzzing = continueFuzzing && !isFatal; } if (emitDedupToken) { // Has to be printed to stdout as it is parsed by libFuzzer when minimizing a crash. It does @@ -322,7 +323,7 @@ private static int runOne(long dataPtr, int dataLength) { // that satisfies the same purpose. // It also doesn't support the mutator framework yet as that requires implementing Java code // generation for mutators. - if (isFatalFindingForJUnit == null && !useMutatorFramework) { + if (fatalFindingDeterminatorForJUnit == null && !useMutatorFramework) { dumpReproducer(data); } @@ -342,7 +343,7 @@ private static int runOne(long dataPtr, int dataLength) { Opt.autofuzzIgnore.get().stream(), Stream.of(finding.getClass().getName())) .collect(joining(",")))); } - if (isFatalFindingForJUnit == null) { + if (fatalFindingDeterminatorForJUnit == null) { // When running a legacy fuzzerTestOneInput test, exit now with the correct exit code. // This will trigger the shutdown hook that runs fuzzerTearDown. System.exit(JAZZER_FINDING_EXIT_CODE); @@ -442,9 +443,9 @@ public static int startLibFuzzer(List args) { args.stream().map(str -> str.getBytes(StandardCharsets.UTF_8)).toArray(byte[][]::new)); } - public static void registerFatalFindingHandlerForJUnit( + public static void registerFatalFindingDeterminatorForJUnit( BiPredicate findingHandler) { - FuzzTargetRunner.isFatalFindingForJUnit = Objects.requireNonNull(findingHandler); + FuzzTargetRunner.fatalFindingDeterminatorForJUnit = Objects.requireNonNull(findingHandler); } private static void shutdown() { diff --git a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java index 67dc977bb..1491f2907 100644 --- a/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java +++ b/src/main/java/com/code_intelligence/jazzer/junit/FuzzTestExecutor.java @@ -323,9 +323,9 @@ public Optional execute( BiPredicate predicate = (a, b) -> { if (counter.incrementAndGet() == Opt.keepGoing.get()) atomicFinding.set(b); - return counter.get() >= Opt.keepGoing.get(); + return Opt.keepGoing.get() != 0 && counter.get() >= Opt.keepGoing.get(); }; - FuzzTargetRunner.registerFatalFindingHandlerForJUnit(predicate); + FuzzTargetRunner.registerFatalFindingDeterminatorForJUnit(predicate); } catch (Throwable throwable) { // Exception during initialization of FuzzTargetRunner, e.g. unsupported // parameter type in fuzz target method. Rethrow as FuzzTestConfigurationError.