aboutsummaryrefslogtreecommitdiff
path: root/agent/src/main/java/com/code_intelligence/jazzer/api/MethodHook.java
blob: 3a1c5f396394c3aa50cef06390d5cdd6366d0502 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
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 {};
}