diff options
author | Fabian Meumertzheim <meumertzheim@code-intelligence.com> | 2021-10-21 12:06:58 +0200 |
---|---|---|
committer | Fabian Meumertzheim <fabian@meumertzhe.im> | 2021-10-21 14:09:41 +0200 |
commit | d4a1ce3f2e227bc30bcd2d97b623c193197e293e (patch) | |
tree | 7bb451018e0b080c8306921598430063d1dcf014 /agent/src | |
parent | 4d925f2464b4ccf759bd4d957d5db9aa749e85b3 (diff) | |
download | jazzer-api-d4a1ce3f2e227bc30bcd2d97b623c193197e293e.tar.gz |
Add Jazzer.consume to the Jazzer API
This requires moving AutofuzzConstructionException to api package.
Diffstat (limited to 'agent/src')
-rw-r--r-- | agent/src/main/java/com/code_intelligence/jazzer/api/AutofuzzConstructionException.java (renamed from agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java) | 7 | ||||
-rw-r--r-- | agent/src/main/java/com/code_intelligence/jazzer/api/Jazzer.java | 38 | ||||
-rw-r--r-- | agent/src/main/java/com/code_intelligence/jazzer/autofuzz/FuzzTarget.java | 1 | ||||
-rw-r--r-- | agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java | 1 | ||||
-rw-r--r-- | agent/src/test/java/com/code_intelligence/jazzer/api/AutofuzzTest.java | 45 | ||||
-rw-r--r-- | agent/src/test/java/com/code_intelligence/jazzer/api/BUILD.bazel | 21 |
6 files changed, 110 insertions, 3 deletions
diff --git a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java b/agent/src/main/java/com/code_intelligence/jazzer/api/AutofuzzConstructionException.java index 7cb41d4b..93340ee8 100644 --- a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java +++ b/agent/src/main/java/com/code_intelligence/jazzer/api/AutofuzzConstructionException.java @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package com.code_intelligence.jazzer.autofuzz; +package com.code_intelligence.jazzer.api; +// An exception wrapping a Throwable thrown during the construction of parameters for, but not the +// actual invocation of an autofuzzed method. /** - * An exception wrapping a {@link Throwable} thrown during the construction of parameters for, but - * not the actual invocation of an autofuzzed method. + * Only used internally. */ public class AutofuzzConstructionException extends RuntimeException { public AutofuzzConstructionException() { diff --git a/agent/src/main/java/com/code_intelligence/jazzer/api/Jazzer.java b/agent/src/main/java/com/code_intelligence/jazzer/api/Jazzer.java index a4f6f740..930d8f0f 100644 --- a/agent/src/main/java/com/code_intelligence/jazzer/api/Jazzer.java +++ b/agent/src/main/java/com/code_intelligence/jazzer/api/Jazzer.java @@ -29,6 +29,8 @@ final public class Jazzer { private static MethodHandle traceStrstr = null; private static MethodHandle traceMemcmp = null; + private static MethodHandle consume = null; + static { try { jazzerInternal = Class.forName("com.code_intelligence.jazzer.runtime.JazzerInternal"); @@ -48,6 +50,11 @@ final public class Jazzer { MethodType.methodType(void.class, byte[].class, byte[].class, int.class, int.class); traceMemcmp = MethodHandles.publicLookup().findStatic( traceDataFlowNativeCallbacks, "traceMemcmp", traceMemcmpType); + + Class<?> metaClass = Class.forName("com.code_intelligence.jazzer.autofuzz.Meta"); + MethodType consumeType = + MethodType.methodType(Object.class, FuzzedDataProvider.class, Class.class); + consume = MethodHandles.publicLookup().findStatic(metaClass, "consume", consumeType); } catch (ClassNotFoundException ignore) { // Not running in the context of the agent. This is fine as long as no methods are called on // this class. @@ -63,6 +70,31 @@ final public class Jazzer { private Jazzer() {} /** + * Attempts to construct an instance of {@code type} from the fuzzer input using only public + * methods available on the classpath. + * + * <b>Note:</b> This function is inherently heuristic and may fail to return meaningful values for + * a variety of reasons. + * + * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. + * @param type the {@link Class} to construct an instance of. + * @return an instance of {@code type} constructed from the fuzzer input, or {@code null} if + * autofuzz failed to create an instance. + */ + @SuppressWarnings("unchecked") + public static <T> T consume(FuzzedDataProvider data, Class<T> type) { + try { + return (T) consume.invokeExact(data, type); + } catch (AutofuzzConstructionException ignored) { + return null; + } catch (Throwable t) { + rethrowUnchecked(t); + // Not reached. + return null; + } + } + + /** * Instructs the fuzzer to guide its mutations towards making {@code current} equal to {@code * target}. * @@ -148,4 +180,10 @@ final public class Jazzer { } } } + + // Rethrows a (possibly checked) exception while avoiding a throws declaration. + @SuppressWarnings("unchecked") + private static <T extends Throwable> void rethrowUnchecked(Throwable t) throws T { + throw(T) t; + } } diff --git a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/FuzzTarget.java b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/FuzzTarget.java index ea1b9a96..ce7df069 100644 --- a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/FuzzTarget.java +++ b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/FuzzTarget.java @@ -14,6 +14,7 @@ package com.code_intelligence.jazzer.autofuzz; +import com.code_intelligence.jazzer.api.AutofuzzConstructionException; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.utils.SimpleGlobMatcher; import com.code_intelligence.jazzer.utils.Utils; diff --git a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java index ad439730..4a679b8f 100644 --- a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java +++ b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java @@ -14,6 +14,7 @@ package com.code_intelligence.jazzer.autofuzz; +import com.code_intelligence.jazzer.api.AutofuzzConstructionException; import com.code_intelligence.jazzer.api.FuzzedDataProvider; import com.code_intelligence.jazzer.utils.Utils; import io.github.classgraph.ClassGraph; diff --git a/agent/src/test/java/com/code_intelligence/jazzer/api/AutofuzzTest.java b/agent/src/test/java/com/code_intelligence/jazzer/api/AutofuzzTest.java new file mode 100644 index 00000000..b4696ce8 --- /dev/null +++ b/agent/src/test/java/com/code_intelligence/jazzer/api/AutofuzzTest.java @@ -0,0 +1,45 @@ +// Copyright 2021 Code Intelligence GmbH +// +// 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. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.code_intelligence.jazzer.api; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.Arrays; +import java.util.Collections; +import org.junit.Test; + +public class AutofuzzTest { + public interface UnimplementedInterface {} + + public interface ImplementedInterface {} + public static class ImplementingClass implements ImplementedInterface {} + + @Test + public void testConsume() { + FuzzedDataProvider data = CannedFuzzedDataProvider.create( + Arrays.asList((byte) 1 /* do not return null */, 0 /* first class on the classpath */, + (byte) 1 /* do not return null */, 0 /* first constructor */)); + ImplementedInterface result = Jazzer.consume(data, ImplementedInterface.class); + assertNotNull(result); + } + + @Test + public void testConsumeFailsWithoutException() { + FuzzedDataProvider data = CannedFuzzedDataProvider.create(Collections.singletonList( + (byte) 1 /* do not return null without searching for implementing classes */)); + assertNull(Jazzer.consume(data, UnimplementedInterface.class)); + } +} diff --git a/agent/src/test/java/com/code_intelligence/jazzer/api/BUILD.bazel b/agent/src/test/java/com/code_intelligence/jazzer/api/BUILD.bazel new file mode 100644 index 00000000..9192ff77 --- /dev/null +++ b/agent/src/test/java/com/code_intelligence/jazzer/api/BUILD.bazel @@ -0,0 +1,21 @@ +java_test( + name = "AutofuzzTest", + size = "small", + srcs = [ + "AutofuzzTest.java", + ], + env = { + # Also consider implementing classes from com.code_intelligence.jazzer.*. + "JAZZER_AUTOFUZZ_TESTING": "1", + }, + test_class = "com.code_intelligence.jazzer.api.AutofuzzTest", + runtime_deps = [ + "//agent/src/main/java/com/code_intelligence/jazzer/autofuzz", + # Needed for JazzerInternal. + "//agent/src/main/java/com/code_intelligence/jazzer/runtime", + ], + deps = [ + "//agent/src/main/java/com/code_intelligence/jazzer/api", + "@maven//:junit_junit", + ], +) |