aboutsummaryrefslogtreecommitdiff
path: root/agent/src/main/java
diff options
context:
space:
mode:
authorFabian Meumertzheim <meumertzheim@code-intelligence.com>2021-10-18 15:54:42 +0200
committerFabian Meumertzheim <fabian@meumertzhe.im>2021-10-19 11:07:51 +0200
commiteff82062143cdcc13f3a20d1fec944dc4de9187e (patch)
treece1d003faff27468671c630ceb3b30c697cfd94e /agent/src/main/java
parent11ad0812c16539a4f19836cc7ad242240247c220 (diff)
downloadjazzer-api-eff82062143cdcc13f3a20d1fec944dc4de9187e.tar.gz
Add autofuzz debug mode
This mode prints detailed information in failure cases and can be enabled by setting the JAZZER_AUTOFUZZ_DEBUG env variable to a non-empty value.
Diffstat (limited to 'agent/src/main/java')
-rw-r--r--agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java3
-rw-r--r--agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzError.java4
-rw-r--r--agent/src/main/java/com/code_intelligence/jazzer/autofuzz/FuzzTarget.java9
-rw-r--r--agent/src/main/java/com/code_intelligence/jazzer/autofuzz/Meta.java66
4 files changed, 60 insertions, 22 deletions
diff --git a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java
index e1d775c4..7cb41d4b 100644
--- a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java
+++ b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzConstructionException.java
@@ -19,6 +19,9 @@ package com.code_intelligence.jazzer.autofuzz;
* not the actual invocation of an autofuzzed method.
*/
public class AutofuzzConstructionException extends RuntimeException {
+ public AutofuzzConstructionException() {
+ super();
+ }
public AutofuzzConstructionException(String message) {
super(message);
}
diff --git a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzError.java b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzError.java
index 65abc492..2773deea 100644
--- a/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzError.java
+++ b/agent/src/main/java/com/code_intelligence/jazzer/autofuzz/AutofuzzError.java
@@ -22,6 +22,10 @@ public class AutofuzzError extends Error {
super(message);
}
+ public AutofuzzError(String message, Throwable cause) {
+ super(message, cause);
+ }
+
public AutofuzzError(Throwable cause) {
super(cause);
}
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 9ad44420..9806bb3c 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
@@ -83,7 +83,7 @@ public class FuzzTarget {
.toArray(Method[] ::new);
if (targetMethods.length == 0) {
if (descriptor == null) {
- System.err.printf("%nFailed to find accessible methods named %s in class %s for autofuzz.%n"
+ System.err.printf("Failed to find accessible methods named %s in class %s for autofuzz.%n"
+ "Accessible methods:%n%s",
methodName, className,
Arrays.stream(targetClass.getMethods())
@@ -93,7 +93,7 @@ public class FuzzTarget {
.distinct()
.collect(Collectors.joining(System.lineSeparator())));
} else {
- System.err.printf("%nFailed to find accessible methods named %s in class %s for autofuzz.%n"
+ System.err.printf("Failed to find accessible methods named %s in class %s for autofuzz.%n"
+ "Accessible methods with that name:%n%s",
methodName, className,
Arrays.stream(targetClass.getMethods())
@@ -121,7 +121,10 @@ public class FuzzTarget {
try {
Meta.autofuzz(data, targetMethod);
executionsSinceLastInvocation = 0;
- } catch (AutofuzzConstructionException ignored) {
+ } catch (AutofuzzConstructionException e) {
+ if (Meta.isDebug()) {
+ e.printStackTrace();
+ }
// Ignore exceptions thrown while constructing the parameters for the target method. We can
// only guess how to generate valid parameters and any exceptions thrown while doing so
// are most likely on us. However, if this happens too often, Autofuzz got stuck and we should
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 94d1e921..dfa6c4a3 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,7 @@
package com.code_intelligence.jazzer.autofuzz;
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.code_intelligence.jazzer.utils.Utils;
import io.github.classgraph.ClassGraph;
import io.github.classgraph.ClassInfoList;
import io.github.classgraph.ScanResult;
@@ -50,7 +51,7 @@ public class Meta {
return method.invoke(thisObject, arguments);
} catch (IllegalAccessException | IllegalArgumentException | NullPointerException e) {
// We should ensure that the arguments fed into the method are always valid.
- throw new AutofuzzError(e);
+ throw new AutofuzzError(getDebugSummary(method, thisObject, arguments), e);
} catch (InvocationTargetException e) {
throw new AutofuzzInvocationException(e.getCause());
}
@@ -63,7 +64,7 @@ public class Meta {
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException e) {
// This should never be reached as the logic in consume should prevent us from e.g. calling
// constructors of abstract classes or private constructors.
- throw new AutofuzzError(e);
+ throw new AutofuzzError(getDebugSummary(constructor, null, arguments), e);
} catch (InvocationTargetException e) {
throw new AutofuzzInvocationException(e.getCause());
}
@@ -149,8 +150,12 @@ public class Meta {
}
}
if (implementingClasses.isEmpty()) {
- throw new AutofuzzConstructionException(String.format(
- "Could not find classes implementing %s on the classpath", type.getName()));
+ if (isDebug()) {
+ throw new AutofuzzConstructionException(String.format(
+ "Could not find classes implementing %s on the classpath", type.getName()));
+ } else {
+ throw new AutofuzzConstructionException();
+ }
}
return consume(data, data.pickValue(implementingClasses));
} else if (type.getConstructors().length > 0) {
@@ -168,10 +173,11 @@ public class Meta {
}
return obj;
}
- // We are out of more or less canonical ways to construct an instance of this class and have to resort to more
- // heuristic approaches.
+ // We are out of more or less canonical ways to construct an instance of this class and have to
+ // resort to more heuristic approaches.
- // First, try to find nested classes with names ending in Builder and call a subset of their chaining methods.
+ // First, try to find nested classes with names ending in Builder and call a subset of their
+ // chaining methods.
List<Class<?>> nestedBuilderClasses = getNestedBuilderClasses(type);
if (!nestedBuilderClasses.isEmpty()) {
Class<?> pickedBuilder = data.pickValue(nestedBuilderClasses);
@@ -197,24 +203,46 @@ public class Meta {
} catch (Exception e) {
throw new AutofuzzConstructionException(e);
}
+ }
+
+ // We ran out of ways to construct an instance of the requested type. If in debug mode, report
+ // more detailed information.
+ if (!isDebug()) {
+ throw new AutofuzzConstructionException();
} else {
- Constructor<?>[] c = type.getDeclaredConstructors();
- System.err.printf("ctor: %s\n", c[0].toGenericString());
- System.err.printf(" public %b\n", Modifier.isPublic(c[0].getModifiers()));
- System.err.printf(" private %b\n", Modifier.isPrivate(c[0].getModifiers()));
- System.err.printf(" protected %b\n", Modifier.isProtected(c[0].getModifiers()));
- // System.err.printf(" protected %b\n", Modifier.i(c[0].getModifiers()));
+ String summary = String.format(
+ "Failed to generate instance of %s:%nAccessible constructors: %s%nNested subclasses: %s%n",
+ type.getName(),
+ Arrays.stream(type.getConstructors())
+ .map(Utils::getReadableDescriptor)
+ .collect(Collectors.joining(", ")),
+ Arrays.stream(type.getClasses()).map(Class::getName).collect(Collectors.joining(", ")));
+ throw new AutofuzzConstructionException(summary);
}
- return null;
+ }
+
+ static boolean isDebug() {
+ String value = System.getenv("JAZZER_AUTOFUZZ_DEBUG");
+ return value != null && !value.isEmpty();
+ }
+
+ private static String getDebugSummary(
+ Executable executable, Object thisObject, Object[] arguments) {
+ return String.format("%nMethod: %s::%s%s%nthis: %s%nArguments: %s",
+ executable.getDeclaringClass().getName(), executable.getName(),
+ Utils.getReadableDescriptor(executable), thisObject,
+ Arrays.stream(arguments)
+ .map(arg -> arg == null ? "null" : arg.toString())
+ .collect(Collectors.joining(", ")));
}
private static List<Class<?>> getNestedBuilderClasses(Class<?> type) {
List<Class<?>> nestedBuilderClasses = nestedBuilderClassesCache.get(type);
if (nestedBuilderClasses == null) {
nestedBuilderClasses = Arrays.stream(type.getClasses())
- .filter(cls -> cls.getName().endsWith("Builder"))
- .filter(cls -> !getOriginalObjectCreationMethods(cls).isEmpty())
- .collect(Collectors.toList());
+ .filter(cls -> cls.getName().endsWith("Builder"))
+ .filter(cls -> !getOriginalObjectCreationMethods(cls).isEmpty())
+ .collect(Collectors.toList());
nestedBuilderClassesCache.put(type, nestedBuilderClasses);
}
return nestedBuilderClasses;
@@ -223,13 +251,13 @@ public class Meta {
private static List<Method> getOriginalObjectCreationMethods(Class<?> builder) {
List<Method> originalObjectCreationMethods = originalObjectCreationMethodsCache.get(builder);
if (originalObjectCreationMethods == null) {
- originalObjectCreationMethods = Arrays.stream(builder.getMethods())
+ originalObjectCreationMethods =
+ Arrays.stream(builder.getMethods())
.filter(m -> m.getReturnType() == builder.getEnclosingClass())
.collect(Collectors.toList());
originalObjectCreationMethodsCache.put(builder, originalObjectCreationMethods);
}
return originalObjectCreationMethods;
-
}
private static List<Method> getPotentialSetters(Class<?> type) {