xref: /aosp_15_r20/external/jazzer-api/src/main/java/com/code_intelligence/jazzer/api/MethodHook.java (revision 33edd6723662ea34453766bfdca85dbfdd5342b8)
1 // Copyright 2021 Code Intelligence GmbH
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 package com.code_intelligence.jazzer.api;
16 
17 import java.lang.annotation.Documented;
18 import java.lang.annotation.ElementType;
19 import java.lang.annotation.Repeatable;
20 import java.lang.annotation.Retention;
21 import java.lang.annotation.RetentionPolicy;
22 import java.lang.annotation.Target;
23 import java.lang.invoke.MethodType;
24 
25 /**
26  * Registers the annotated method as a hook that should run before, instead or
27  * after the method specified by the annotation parameters.
28  * <p>
29  * Depending on {@link #type()} this method will be called after, instead or
30  * before every call to the target method and has
31  * access to its parameters and return value. The target method is specified by
32  * {@link #targetClassName()} and {@link #targetMethod()}. In case of an
33  * overloaded method, {@link #targetMethodDescriptor()} can be used to restrict
34  * the application of the hook to a particular overload.
35  * <p>
36  * The signature of the annotated method must be as follows (this does not
37  * restrict the method name and parameter names, which are arbitrary),
38  * depending on the value of {@link #type()}:
39  *
40  * <dl>
41  * <dt><span class="strong">{@link HookType#BEFORE}</span>
42  * <dd>
43  * <pre>{@code
44  * public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId)
45  * }</pre>
46  * Arguments:
47  * <p><ul>
48  * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the
49  * original method. The original method can be invoked via
50  * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This
51  * requires passing {@code thisObject} as the first argument if the method is
52  * not static. This argument can be {@code null}.
53  * <li>{@code thisObject}: An {@link Object} containing the implicit
54  * {@code this} argument to the original method. If the original method is
55  * static, this argument will be {@code null}.
56  * <li>{@code arguments}: An array of {@link Object}s containing the arguments
57  * passed to the original method. Primitive types (e.g. {@code boolean}) will be
58  * wrapped into their corresponding wrapper type (e.g. {@link Boolean}).
59  * <li>{@code hookId}: A random {@code int} identifying the particular call
60  * site.This can be used to derive additional coverage information.
61  * </ul>
62  *
63  * <dt><span class="strong">{@link HookType#REPLACE}</span>
64  * <dd>
65  * <pre>{@code
66  * public static Object hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId)
67  * }</pre>
68  * The return type may alternatively be taken to be the exact return type of
69  * target method or a wrapper type thereof. The returned object will be casted
70  * and unwrapped automatically.
71  * <p>
72  * Arguments:
73  * <p><ul>
74  * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the
75  * original method. The original method can be invoked via
76  * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This
77  * requires passing {@code thisObject} as the first argument if the method is
78  * not static. This argument can be {@code null}.
79  * <li>{@code thisObject}: An {@link Object} containing the implicit
80  * {@code this} argument to the original method. If the original method is
81  * static, this argument will be {@code null}.
82  * <li>{@code arguments}: An array of {@link Object}s containing the arguments
83  * passed to the original method. Primitive types (e.g. {@code boolean}) will be
84  * wrapped into their corresponding wrapper type (e.g. {@link Boolean}).
85  * <li>{@code hookId}: A random {@code int} identifying the particular call
86  * site.This can be used to derive additional coverage information.
87  * </ul><p>
88  * <p>
89  * Return value: the value that should take the role of the value the target
90  * method would have returned
91  * <p>
92  * <dt><span class="strong">{@link HookType#AFTER}</span>
93  * <dd>
94  * <pre>{@code
95  * public static void hook(MethodHandle method, Object thisObject, Object[] arguments, int hookId,
96  * Object returnValue)
97  * }</pre>
98  * Arguments:
99  * <p><ul>
100  * <li>{@code method}: A {@link java.lang.invoke.MethodHandle} representing the
101  * original method. The original method can be invoked via
102  * {@link java.lang.invoke.MethodHandle#invokeWithArguments(Object...)}. This
103  * requires passing {@code thisObject} as the first argument if the method is
104  * not static. This argument can be {@code null}.
105  * <li>{@code thisObject}: An {@link Object} containing the implicit
106  * {@code this} argument to the original method. If the original method is
107  * static, this argument will be {@code null}.
108  * <li>{@code arguments}: An array of {@link Object}s containing the arguments
109  * passed to the original method. Primitive types (e.g. {@code boolean}) will be
110  * wrapped into their corresponding wrapper type (e.g. {@link Boolean}).
111  * <li>{@code hookId}: A random {@code int} identifying the particular call
112  * site.This can be used to derive additional coverage information.
113  * <li>{@code returnValue}: An {@link Object} containing the return value of the
114  * invocation of the original method. Primitive types (e.g. {@code boolean})
115  * will be wrapped into their corresponding wrapper type (e.g. {@link Boolean}).
116  * If the original method has return type {@code void}, this value will be
117  * {@code null}.
118  * <p>
119  * Multiple {@link HookType#BEFORE} and {@link HookType#AFTER} hooks are
120  * allowed to reference the same target method. Exclusively one
121  * {@link HookType#REPLACE} hook may reference a target method, no other types
122  * allowed. Attention must be paid to not guide the Fuzzer in different
123  * directions via {@link Jazzer}'s {@code guideTowardsXY} methods in the
124  * different hooks.
125  */
126 @Retention(RetentionPolicy.RUNTIME)
127 @Target(ElementType.METHOD)
128 @Repeatable(MethodHooks.class)
129 @Documented
130 public @interface MethodHook {
131   /**
132    * The time at which the annotated method should be called.
133    * <p>
134    * If this is {@link HookType#BEFORE}, the annotated method will be called
135    * before the target method and has access to its arguments.
136    * <p>
137    * If this is {@link HookType#REPLACE}, the annotated method will be called
138    * instead of the target method. It has access to its arguments and can
139    * return a value that will replace the target method's return value.
140    * <p>
141    * If this is {@link HookType#AFTER}, the annotated method will be called
142    * after the target method and has access to its arguments and return
143    * value.
144    *
145    * @return when the hook should be called
146    */
type()147   HookType type();
148 
149   /**
150    * The name of the class that contains the method that should be hooked,
151    * as returned by {@link Class#getName()}.
152    * <p>
153    * If an interface or abstract class is specified, also calls to all
154    * implementations and subclasses available on the classpath during startup
155    * are hooked, respectively. Interfaces and subclasses are not taken into
156    * account for concrete classes.
157    * <p>
158    * Examples:
159    * <p><ul>
160    * <li>{@link String}: {@code "java.lang.String"}
161    * <li>{@link java.nio.file.FileSystem}: {@code "java.nio.file.FileSystem"}
162    * </ul><p>
163    *
164    * @return the name of the class containing the method to be hooked
165    */
targetClassName()166   String targetClassName();
167 
168   /**
169    * The name of the method to be hooked. Use {@code "<init>"} for
170    * constructors.
171    * <p>
172    * Examples:
173    * <p><ul>
174    * <li>{@link String#equals(Object)}: {@code "equals"}
175    * <li>{@link String#String()}: {@code "<init>"}
176    * </ul><p>
177    *
178    * @return the name of the method to be hooked
179    */
targetMethod()180   String targetMethod();
181 
182   /**
183    * The descriptor of the method to be hooked. This is only needed if there
184    * are multiple methods with the same name and not all of them should be
185    * hooked.
186    * <p>
187    * The descriptor of a method is an internal representation of the method's
188    * signature, which includes the types of its parameters and its return
189    * value. For more information on descriptors, see the
190    * <a href=https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-4.html#jvms-4.3.3>JVM
191    * Specification, Section 4.3.3</a> and {@link MethodType#toMethodDescriptorString()}
192    *
193    * @return the descriptor of the method to be hooked
194    */
targetMethodDescriptor()195   String targetMethodDescriptor() default "";
196 
197   /**
198    * Array of additional classes to hook.
199    * <p>
200    * Hooks are applied on call sites. This means that classes calling the one
201    * defined in this annotation need to be instrumented to actually execute
202    * the hook. This property can be used to hook normally ignored classes.
203    *
204    * @return fully qualified class names to hook
205    */
additionalClassesToHook()206   String[] additionalClassesToHook() default {};
207 }
208