diff options
Diffstat (limited to 'src/main/java/com/code_intelligence/jazzer/api/MethodHook.java')
-rw-r--r-- | src/main/java/com/code_intelligence/jazzer/api/MethodHook.java | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/src/main/java/com/code_intelligence/jazzer/api/MethodHook.java b/src/main/java/com/code_intelligence/jazzer/api/MethodHook.java new file mode 100644 index 00000000..3a1c5f39 --- /dev/null +++ b/src/main/java/com/code_intelligence/jazzer/api/MethodHook.java @@ -0,0 +1,207 @@ +// 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 java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Repeatable; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.invoke.MethodType; + +/** + * Registers the annotated method as a hook that should run before, instead or + * after the method specified by the annotation parameters. + * <p> + * Depending on {@link #type()} this method will be called after, instead or + * before every call to the target method and has + * access to its parameters and return value. The target method is specified by + * {@link #targetClassName()} and {@link #targetMethod()}. In case of an + * overloaded method, {@link #targetMethodDescriptor()} can be used to restrict + * the application of the hook to a particular overload. + * <p> + * The signature of the annotated method must be as follows (this does not + * restrict the method name and parameter names, which are arbitrary), + * depending on the value of {@link #type()}: + * + * <dl> + * <dt><span class="strong">{@link HookType#BEFORE}</span> + * <dd> + * <pre>{@code + * public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId) + * }</pre> + * Arguments: + * <p><ul> + * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the + * original method. The original method can be invoked via + * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This + * requires passing {@code thisObject} as the first argument if the method is + * not static. This argument can be {@code null}. + * <li>{@code thisObject}: An {@link Object} containing the implicit + * {@code this} argument to the original method. If the original method is + * static, this argument will be {@code null}. + * <li>{@code arguments}: An array of {@link Object}s containing the arguments + * passed to the original method. Primitive types (e.g. {@code boolean}) will be + * wrapped into their corresponding wrapper type (e.g. {@link Boolean}). + * <li>{@code hookId}: A random {@code int} identifying the particular call + * site.This can be used to derive additional coverage information. + * </ul> + * + * <dt><span class="strong">{@link HookType#REPLACE}</span> + * <dd> + * <pre>{@code + * public static Object hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId) + * }</pre> + * The return type may alternatively be taken to be the exact return type of + * target method or a wrapper type thereof. The returned object will be casted + * and unwrapped automatically. + * <p> + * Arguments: + * <p><ul> + * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the + * original method. The original method can be invoked via + * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This + * requires passing {@code thisObject} as the first argument if the method is + * not static. This argument can be {@code null}. + * <li>{@code thisObject}: An {@link Object} containing the implicit + * {@code this} argument to the original method. If the original method is + * static, this argument will be {@code null}. + * <li>{@code arguments}: An array of {@link Object}s containing the arguments + * passed to the original method. Primitive types (e.g. {@code boolean}) will be + * wrapped into their corresponding wrapper type (e.g. {@link Boolean}). + * <li>{@code hookId}: A random {@code int} identifying the particular call + * site.This can be used to derive additional coverage information. + * </ul><p> + * <p> + * Return value: the value that should take the role of the value the target + * method would have returned + * <p> + * <dt><span class="strong">{@link HookType#AFTER}</span> + * <dd> + * <pre>{@code + * public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId, + * Object returnValue) + * }</pre> + * Arguments: + * <p><ul> + * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the + * original method. The original method can be invoked via + * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This + * requires passing {@code thisObject} as the first argument if the method is + * not static. This argument can be {@code null}. + * <li>{@code thisObject}: An {@link Object} containing the implicit + * {@code this} argument to the original method. If the original method is + * static, this argument will be {@code null}. + * <li>{@code arguments}: An array of {@link Object}s containing the arguments + * passed to the original method. Primitive types (e.g. {@code boolean}) will be + * wrapped into their corresponding wrapper type (e.g. {@link Boolean}). + * <li>{@code hookId}: A random {@code int} identifying the particular call + * site.This can be used to derive additional coverage information. + * <li>{@code returnValue}: An {@link Object} containing the return value of the + * invocation of the original method. Primitive types (e.g. {@code boolean}) + * will be wrapped into their corresponding wrapper type (e.g. {@link Boolean}). + * If the original method has return type {@code void}, this value will be + * {@code null}. + * <p> + * Multiple {@link HookType#BEFORE} and {@link HookType#AFTER} hooks are + * allowed to reference the same target method. Exclusively one + * {@link HookType#REPLACE} hook may reference a target method, no other types + * allowed. Attention must be paid to not guide the Fuzzer in different + * directions via {@link Jazzer}'s {@code guideTowardsXY} methods in the + * different hooks. + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +@Repeatable(MethodHooks.class) +@Documented +public @interface MethodHook { + /** + * The time at which the annotated method should be called. + * <p> + * If this is {@link HookType#BEFORE}, the annotated method will be called + * before the target method and has access to its arguments. + * <p> + * If this is {@link HookType#REPLACE}, the annotated method will be called + * instead of the target method. It has access to its arguments and can + * return a value that will replace the target method's return value. + * <p> + * If this is {@link HookType#AFTER}, the annotated method will be called + * after the target method and has access to its arguments and return + * value. + * + * @return when the hook should be called + */ + HookType type(); + + /** + * The name of the class that contains the method that should be hooked, + * as returned by {@link Class#getName()}. + * <p> + * If an interface or abstract class is specified, also calls to all + * implementations and subclasses available on the classpath during startup + * are hooked, respectively. Interfaces and subclasses are not taken into + * account for concrete classes. + * <p> + * Examples: + * <p><ul> + * <li>{@link String}: {@code "java.lang.String"} + * <li>{@link java.nio.file.FileSystem}: {@code "java.nio.file.FileSystem"} + * </ul><p> + * + * @return the name of the class containing the method to be hooked + */ + String targetClassName(); + + /** + * The name of the method to be hooked. Use {@code "<init>"} for + * constructors. + * <p> + * Examples: + * <p><ul> + * <li>{@link String#equals(Object)}: {@code "equals"} + * <li>{@link String#String()}: {@code "<init>"} + * </ul><p> + * + * @return the name of the method to be hooked + */ + String targetMethod(); + + /** + * The descriptor of the method to be hooked. This is only needed if there + * are multiple methods with the same name and not all of them should be + * hooked. + * <p> + * The descriptor of a method is an internal representation of the method's + * signature, which includes the types of its parameters and its return + * value. For more information on descriptors, see the + * <a href=https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-4.html#jvms-4.3.3>JVM + * Specification, Section 4.3.3</a> and {@link MethodType#toMethodDescriptorString()} + * + * @return the descriptor of the method to be hooked + */ + String targetMethodDescriptor() default ""; + + /** + * Array of additional classes to hook. + * <p> + * Hooks are applied on call sites. This means that classes calling the one + * defined in this annotation need to be instrumented to actually execute + * the hook. This property can be used to hook normally ignored classes. + * + * @return fully qualified class names to hook + */ + String[] additionalClassesToHook() default {}; +} |