aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKhaled Yakdan <yakdan@code-intelligence.com>2021-10-14 15:25:34 +0200
committerFabian Meumertzheim <fabian@meumertzhe.im>2021-10-19 11:07:51 +0200
commitbc8cb4614b97cc1d905e5d1e083ea084ddfaa9af (patch)
tree905b961ce5765ed7591a753f553bdc1f858d421d
parent8311978af16a7e0a9661457b13423adc47540dc8 (diff)
downloadjazzer-api-bc8cb4614b97cc1d905e5d1e083ea084ddfaa9af.tar.gz
Create Objects from classes implementing an interface
-rw-r--r--agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java22
-rw-r--r--agent/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel14
-rw-r--r--agent/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java106
-rw-r--r--agent/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java2
-rw-r--r--driver/fuzz_target_runner.cpp2
5 files changed, 141 insertions, 5 deletions
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 1f8a21c6..8a640637 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
@@ -15,6 +15,9 @@
package com.code_intelligence.jazzer.autofuzz;
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfoList;
+import io.github.classgraph.ScanResult;
import java.io.ByteArrayInputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
@@ -23,10 +26,14 @@ import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
+import java.util.List;
+import java.util.WeakHashMap;
import net.jodah.typetools.TypeResolver;
import net.jodah.typetools.TypeResolver.Unknown;
public class Meta {
+ static WeakHashMap<Class<?>, List<Class<?>>> cache = new WeakHashMap<>();
+
public static Object consume(FuzzedDataProvider data, Class<?> type) {
if (type == byte.class || type == Byte.class) {
return data.consumeByte();
@@ -68,8 +75,19 @@ public class Meta {
return new ByteArrayInputStream(data.consumeBytes(data.remainingBytes() / 2));
} else if (type.isEnum()) {
return data.pickValue(type.getEnumConstants());
- } else if (Modifier.isAbstract(type.getModifiers())) {
- } else if (type.isInterface()) {
+ } else if (type.isInterface() || Modifier.isAbstract(type.getModifiers())) {
+ List<Class<?>> implementingClasses = cache.get(type);
+ if (implementingClasses == null) {
+ try (ScanResult result =
+ new ClassGraph().enableClassInfo().enableInterClassDependencies().scan()) {
+ ClassInfoList children =
+ type.isInterface() ? result.getClassesImplementing(type) : result.getSubclasses(type);
+ implementingClasses =
+ children.getStandardClasses().filter(cls -> !cls.isAbstract()).loadClasses();
+ cache.put(type, implementingClasses);
+ }
+ }
+ return consume(data, data.pickValue(implementingClasses));
} else if (type.getConstructors().length > 0) {
return autofuzz(data, data.pickValue(type.getConstructors()));
}
diff --git a/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel b/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel
index c25d7147..454e8e3f 100644
--- a/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel
+++ b/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/BUILD.bazel
@@ -14,3 +14,17 @@ java_test(
"@maven//:junit_junit",
],
)
+
+java_test(
+ name = "InterfaceCreationTest",
+ size = "small",
+ srcs = [
+ "InterfaceCreationTest.java",
+ ],
+ test_class = "com.code_intelligence.jazzer.autofuzz.InterfaceCreationTest",
+ deps = [
+ "//agent/src/main/java/com/code_intelligence/jazzer/api",
+ "//agent/src/main/java/com/code_intelligence/jazzer/autofuzz",
+ "@maven//:junit_junit",
+ ],
+)
diff --git a/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java b/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java
new file mode 100644
index 00000000..d15cfd89
--- /dev/null
+++ b/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/InterfaceCreationTest.java
@@ -0,0 +1,106 @@
+// 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.autofuzz;
+
+import static org.junit.Assert.assertEquals;
+
+import com.code_intelligence.jazzer.api.CannedFuzzedDataProvider;
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.Arrays;
+import java.util.Objects;
+import org.junit.Test;
+
+interface InterfaceA {
+ void foo();
+
+ void bar();
+}
+
+abstract class ClassA1 implements InterfaceA {
+ @Override
+ public void foo() {}
+}
+
+class ClassB1 extends ClassA1 {
+ int n;
+
+ public ClassB1(int _n) {
+ n = _n;
+ }
+
+ @Override
+ public void bar() {}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ClassB1 classB1 = (ClassB1) o;
+ return n == classB1.n;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(n);
+ }
+}
+
+class ClassB2 implements InterfaceA {
+ String s;
+
+ public ClassB2(String _s) {
+ s = _s;
+ }
+
+ @Override
+ public void foo() {}
+
+ @Override
+ public void bar() {}
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || getClass() != o.getClass())
+ return false;
+ ClassB2 classB2 = (ClassB2) o;
+ return Objects.equals(s, classB2.s);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(s);
+ }
+}
+
+public class InterfaceCreationTest {
+ FuzzedDataProvider data = CannedFuzzedDataProvider.create(Arrays.asList(0, // pick ClassB1
+ 0, // pick first constructor
+ 5, // arg for ClassB1 constructor
+ 1, // pick ClassB2
+ 0, // pick first constructor
+ 8, // remaining bytes
+ "test" // arg for ClassB2 constructor
+ ));
+
+ @Test
+ public void testConsumeInterface() {
+ assertEquals(Meta.consume(data, InterfaceA.class), new ClassB1(5));
+ assertEquals(Meta.consume(data, InterfaceA.class), new ClassB2("test"));
+ }
+}
diff --git a/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java b/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java
index c491ed66..52ec1eb0 100644
--- a/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java
+++ b/agent/src/test/java/com/code_intelligence/jazzer/autofuzz/MetaTest.java
@@ -20,10 +20,8 @@ import static org.junit.Assert.assertTrue;
import com.code_intelligence.jazzer.api.CannedFuzzedDataProvider;
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import com.google.json.JsonSanitizer;
-
import java.util.Arrays;
import java.util.Collections;
-
import org.junit.Test;
public class MetaTest {
diff --git a/driver/fuzz_target_runner.cpp b/driver/fuzz_target_runner.cpp
index 0bdaedf5..b71a937a 100644
--- a/driver/fuzz_target_runner.cpp
+++ b/driver/fuzz_target_runner.cpp
@@ -155,7 +155,7 @@ FuzzTargetRunner::FuzzTargetRunner(
jclass string_class = jvm.FindClass("java/lang/String");
jobjectArray arg_array = jvm.GetEnv().NewObjectArray(
fuzz_target_args_tokens.size(), string_class, nullptr);
- for (std::size_t i = 0; i < fuzz_target_args_tokens.size(); i++) {
+ for (jint i = 0; i < fuzz_target_args_tokens.size(); i++) {
jstring str = env.NewStringUTF(fuzz_target_args_tokens[i].c_str());
env.SetObjectArrayElement(arg_array, i, str);
}