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