com.code_intelligence.jazzer.api.MethodHook Maven / Gradle / Ivy
Show all versions of jazzer Show documentation
// 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.
*
* 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.
*
*
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()}:
*
*
* - {@link HookType#BEFORE}
*
-
*
{@code
* public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId)
* }
* Arguments:
*
*
* - {@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}.
*
- {@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}.
*
- {@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}).
*
- {@code hookId}: A random {@code int} identifying the particular call site.This can be
* used to derive additional coverage information.
*
* - {@link HookType#REPLACE}
*
-
*
{@code
* public static Object hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId)
* }
* 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.
* Arguments:
*
*
* - {@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}.
*
- {@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}.
*
- {@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}).
*
- {@code hookId}: A random {@code int} identifying the particular call site.This can be
* used to derive additional coverage information.
*
*
*
Return value: the value that should take the role of the value the target method would
* have returned
*
*
- {@link HookType#AFTER}
*
-
*
{@code
* public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId,
* Object returnValue)
* }
* Arguments:
*
*
* - {@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}.
*
- {@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}.
*
- {@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}).
*
- {@code hookId}: A random {@code int} identifying the particular call site.This can be
* used to derive additional coverage information.
*
- {@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}.
*
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.
*
*
If this is {@link HookType#BEFORE}, the annotated method will be called before the target
* method and has access to its arguments.
*
*
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.
*
*
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()}.
*
*
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.
*
*
Examples:
*
*
*
*
* - {@link String}: {@code "java.lang.String"}
*
- {@link java.nio.file.FileSystem}: {@code "java.nio.file.FileSystem"}
*
*
*
*
* @return the name of the class containing the method to be hooked
*/
String targetClassName();
/**
* The name of the method to be hooked. Use {@code ""} for constructors.
*
* Examples:
*
*
*
*
* - {@link String#equals(Object)}: {@code "equals"}
*
- {@link String#String()}: {@code "
"}
*
*
*
*
* @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.
*
*
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 JVM
* Specification, Section 4.3.3 and {@link MethodType#toMethodDescriptorString()}
*
* @return the descriptor of the method to be hooked
*/
String targetMethodDescriptor() default "";
/**
* Array of additional classes to hook.
*
*
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 {};
}