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.invoke.MethodHandle; 18 import java.lang.invoke.MethodHandles; 19 import java.lang.invoke.MethodType; 20 21 /** 22 * Static helper functions that allow Jazzer fuzz targets to use Autofuzz. 23 */ 24 final public class Autofuzz { 25 private static final MethodHandle CONSUME; 26 private static final MethodHandle AUTOFUZZ_FUNCTION_1; 27 private static final MethodHandle AUTOFUZZ_FUNCTION_2; 28 private static final MethodHandle AUTOFUZZ_FUNCTION_3; 29 private static final MethodHandle AUTOFUZZ_FUNCTION_4; 30 private static final MethodHandle AUTOFUZZ_FUNCTION_5; 31 private static final MethodHandle AUTOFUZZ_CONSUMER_1; 32 private static final MethodHandle AUTOFUZZ_CONSUMER_2; 33 private static final MethodHandle AUTOFUZZ_CONSUMER_3; 34 private static final MethodHandle AUTOFUZZ_CONSUMER_4; 35 private static final MethodHandle AUTOFUZZ_CONSUMER_5; 36 37 static { 38 MethodHandle consume = null; 39 MethodHandle autofuzzFunction1 = null; 40 MethodHandle autofuzzFunction2 = null; 41 MethodHandle autofuzzFunction3 = null; 42 MethodHandle autofuzzFunction4 = null; 43 MethodHandle autofuzzFunction5 = null; 44 MethodHandle autofuzzConsumer1 = null; 45 MethodHandle autofuzzConsumer2 = null; 46 MethodHandle autofuzzConsumer3 = null; 47 MethodHandle autofuzzConsumer4 = null; 48 MethodHandle autofuzzConsumer5 = null; 49 try { 50 Class<?> metaClass = Class.forName("com.code_intelligence.jazzer.autofuzz.Meta"); 51 MethodType consumeType = 52 MethodType.methodType(Object.class, FuzzedDataProvider.class, Class.class); 53 consume = MethodHandles.publicLookup().findStatic(metaClass, "consume", consumeType); 54 55 autofuzzFunction1 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 56 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function1.class)); 57 autofuzzFunction2 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 58 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function2.class)); 59 autofuzzFunction3 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 60 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function3.class)); 61 autofuzzFunction4 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 62 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function4.class)); 63 autofuzzFunction5 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 64 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function5.class)); 65 autofuzzConsumer1 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 66 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer1.class)); 67 autofuzzConsumer2 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 68 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer2.class)); 69 autofuzzConsumer3 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 70 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer3.class)); 71 autofuzzConsumer4 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 72 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer4.class)); 73 autofuzzConsumer5 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 74 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer5.class)); 75 } catch (ClassNotFoundException ignore) { 76 // Not running in the context of the agent. This is fine as long as no methods are called on 77 // this class. 78 } catch (NoSuchMethodException | IllegalAccessException e) { 79 // This should never happen as the Jazzer API is loaded from the agent and thus should always 80 // match the version of the runtime classes. 81 // Does not use the Log class as it is unlikely it can be loaded if the Autofuzz classes 82 // couldn't be loaded. 83 System.err.println("ERROR: Incompatible version of the Jazzer API detected, please update."); 84 e.printStackTrace(); 85 System.exit(1); 86 } 87 CONSUME = consume; 88 AUTOFUZZ_FUNCTION_1 = autofuzzFunction1; 89 AUTOFUZZ_FUNCTION_2 = autofuzzFunction2; 90 AUTOFUZZ_FUNCTION_3 = autofuzzFunction3; 91 AUTOFUZZ_FUNCTION_4 = autofuzzFunction4; 92 AUTOFUZZ_FUNCTION_5 = autofuzzFunction5; 93 AUTOFUZZ_CONSUMER_1 = autofuzzConsumer1; 94 AUTOFUZZ_CONSUMER_2 = autofuzzConsumer2; 95 AUTOFUZZ_CONSUMER_3 = autofuzzConsumer3; 96 AUTOFUZZ_CONSUMER_4 = autofuzzConsumer4; 97 AUTOFUZZ_CONSUMER_5 = autofuzzConsumer5; 98 } 99 Autofuzz()100 private Autofuzz() {} 101 102 /** 103 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 104 * using only public methods available on the classpath. 105 * <p> 106 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 107 * meaningful ways for a number of reasons. 108 * 109 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 110 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 111 * resolve ambiguities by explicitly casting to {@link Function1} with (partially) specified 112 * type variables, e.g. {@code (Function1<String, ?>) String::new}. 113 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 114 * the function. 115 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 116 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 117 * The {@link Throwable} is thrown unchecked. 118 */ 119 @SuppressWarnings("unchecked") autofuzz(FuzzedDataProvider data, Function1<T1, R> func)120 public static <T1, R> R autofuzz(FuzzedDataProvider data, Function1<T1, R> func) { 121 try { 122 return (R) AUTOFUZZ_FUNCTION_1.invoke(data, func); 123 } catch (AutofuzzInvocationException e) { 124 rethrowUnchecked(e.getCause()); 125 } catch (Throwable t) { 126 rethrowUnchecked(t); 127 } 128 // Not reached. 129 return null; 130 } 131 132 /** 133 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 134 * using only public methods available on the classpath. 135 * <p> 136 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 137 * meaningful ways for a number of reasons. 138 * 139 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 140 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 141 * resolve ambiguities by explicitly casting to {@link Function2} with (partially) specified 142 * type variables. 143 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 144 * the function. 145 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 146 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 147 * The {@link Throwable} is thrown unchecked. 148 */ 149 @SuppressWarnings("unchecked") autofuzz(FuzzedDataProvider data, Function2<T1, T2, R> func)150 public static <T1, T2, R> R autofuzz(FuzzedDataProvider data, Function2<T1, T2, R> func) { 151 try { 152 return (R) AUTOFUZZ_FUNCTION_2.invoke(data, func); 153 } catch (AutofuzzInvocationException e) { 154 rethrowUnchecked(e.getCause()); 155 } catch (Throwable t) { 156 rethrowUnchecked(t); 157 } 158 // Not reached. 159 return null; 160 } 161 162 /** 163 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 164 * using only public methods available on the classpath. 165 * <p> 166 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 167 * meaningful ways for a number of reasons. 168 * 169 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 170 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 171 * resolve ambiguities by explicitly casting to {@link Function3} with (partially) specified 172 * type variables. 173 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 174 * the function. 175 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 176 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 177 * The {@link Throwable} is thrown unchecked. 178 */ 179 @SuppressWarnings("unchecked") autofuzz(FuzzedDataProvider data, Function3<T1, T2, T3, R> func)180 public static <T1, T2, T3, R> R autofuzz(FuzzedDataProvider data, Function3<T1, T2, T3, R> func) { 181 try { 182 return (R) AUTOFUZZ_FUNCTION_3.invoke(data, func); 183 } catch (AutofuzzInvocationException e) { 184 rethrowUnchecked(e.getCause()); 185 } catch (Throwable t) { 186 rethrowUnchecked(t); 187 } 188 // Not reached. 189 return null; 190 } 191 192 /** 193 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 194 * using only public methods available on the classpath. 195 * <p> 196 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 197 * meaningful ways for a number of reasons. 198 * 199 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 200 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 201 * resolve ambiguities by explicitly casting to {@link Function4} with (partially) specified 202 * type variables. 203 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 204 * the function. 205 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 206 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 207 * The {@link Throwable} is thrown unchecked. 208 */ 209 @SuppressWarnings("unchecked") autofuzz( FuzzedDataProvider data, Function4<T1, T2, T3, T4, R> func)210 public static <T1, T2, T3, T4, R> R autofuzz( 211 FuzzedDataProvider data, Function4<T1, T2, T3, T4, R> func) { 212 try { 213 return (R) AUTOFUZZ_FUNCTION_4.invoke(data, func); 214 } catch (AutofuzzInvocationException e) { 215 rethrowUnchecked(e.getCause()); 216 } catch (Throwable t) { 217 rethrowUnchecked(t); 218 } 219 // Not reached. 220 return null; 221 } 222 223 /** 224 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 225 * using only public methods available on the classpath. 226 * <p> 227 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 228 * meaningful ways for a number of reasons. 229 * 230 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 231 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 232 * resolve ambiguities by explicitly casting to {@link Function5} with (partially) specified 233 * type variables. 234 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 235 * the function. 236 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 237 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 238 * The {@link Throwable} is thrown unchecked. 239 */ 240 @SuppressWarnings("unchecked") autofuzz( FuzzedDataProvider data, Function5<T1, T2, T3, T4, T5, R> func)241 public static <T1, T2, T3, T4, T5, R> R autofuzz( 242 FuzzedDataProvider data, Function5<T1, T2, T3, T4, T5, R> func) { 243 try { 244 return (R) AUTOFUZZ_FUNCTION_5.invoke(data, func); 245 } catch (AutofuzzInvocationException e) { 246 rethrowUnchecked(e.getCause()); 247 } catch (Throwable t) { 248 rethrowUnchecked(t); 249 } 250 // Not reached. 251 return null; 252 } 253 254 /** 255 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 256 * using only public methods available on the classpath. 257 * <p> 258 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 259 * meaningful ways for a number of reasons. 260 * 261 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 262 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 263 * resolve ambiguities by explicitly casting to {@link Consumer1} with explicitly specified 264 * type variable. 265 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 266 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 267 * The {@link Throwable} is thrown unchecked. 268 */ autofuzz(FuzzedDataProvider data, Consumer1<T1> func)269 public static <T1> void autofuzz(FuzzedDataProvider data, Consumer1<T1> func) { 270 try { 271 AUTOFUZZ_CONSUMER_1.invoke(data, func); 272 } catch (AutofuzzInvocationException e) { 273 rethrowUnchecked(e.getCause()); 274 } catch (Throwable t) { 275 rethrowUnchecked(t); 276 } 277 } 278 279 /** 280 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 281 * using only public methods available on the classpath. 282 * <p> 283 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 284 * meaningful ways for a number of reasons. 285 * 286 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 287 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 288 * resolve ambiguities by explicitly casting to {@link Consumer2} with (partially) specified 289 * type variables. 290 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 291 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 292 * The {@link Throwable} is thrown unchecked. 293 */ autofuzz(FuzzedDataProvider data, Consumer2<T1, T2> func)294 public static <T1, T2> void autofuzz(FuzzedDataProvider data, Consumer2<T1, T2> func) { 295 try { 296 AUTOFUZZ_CONSUMER_2.invoke(data, func); 297 } catch (AutofuzzInvocationException e) { 298 rethrowUnchecked(e.getCause()); 299 } catch (Throwable t) { 300 rethrowUnchecked(t); 301 } 302 } 303 304 /** 305 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 306 * using only public methods available on the classpath. 307 * <p> 308 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 309 * meaningful ways for a number of reasons. 310 * 311 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 312 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 313 * resolve ambiguities by explicitly casting to {@link Consumer3} with (partially) specified 314 * type variables. 315 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 316 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 317 * The {@link Throwable} is thrown unchecked. 318 */ autofuzz(FuzzedDataProvider data, Consumer3<T1, T2, T3> func)319 public static <T1, T2, T3> void autofuzz(FuzzedDataProvider data, Consumer3<T1, T2, T3> func) { 320 try { 321 AUTOFUZZ_CONSUMER_3.invoke(data, func); 322 } catch (AutofuzzInvocationException e) { 323 rethrowUnchecked(e.getCause()); 324 } catch (Throwable t) { 325 rethrowUnchecked(t); 326 } 327 } 328 329 /** 330 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 331 * using only public methods available on the classpath. 332 * <p> 333 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 334 * meaningful ways for a number of reasons. 335 * 336 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 337 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 338 * resolve ambiguities by explicitly casting to {@link Consumer4} with (partially) specified 339 * type variables. 340 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 341 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 342 * The {@link Throwable} is thrown unchecked. 343 */ autofuzz( FuzzedDataProvider data, Consumer4<T1, T2, T3, T4> func)344 public static <T1, T2, T3, T4> void autofuzz( 345 FuzzedDataProvider data, Consumer4<T1, T2, T3, T4> func) { 346 try { 347 AUTOFUZZ_CONSUMER_4.invoke(data, func); 348 } catch (AutofuzzInvocationException e) { 349 rethrowUnchecked(e.getCause()); 350 } catch (Throwable t) { 351 rethrowUnchecked(t); 352 } 353 } 354 355 /** 356 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 357 * using only public methods available on the classpath. 358 * <p> 359 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 360 * meaningful ways for a number of reasons. 361 * 362 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 363 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 364 * resolve ambiguities by explicitly casting to {@link Consumer5} with (partially) specified 365 * type variables. 366 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 367 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 368 * The {@link Throwable} is thrown unchecked. 369 */ autofuzz( FuzzedDataProvider data, Consumer5<T1, T2, T3, T4, T5> func)370 public static <T1, T2, T3, T4, T5> void autofuzz( 371 FuzzedDataProvider data, Consumer5<T1, T2, T3, T4, T5> func) { 372 try { 373 AUTOFUZZ_CONSUMER_5.invoke(data, func); 374 } catch (AutofuzzInvocationException e) { 375 rethrowUnchecked(e.getCause()); 376 } catch (Throwable t) { 377 rethrowUnchecked(t); 378 } 379 } 380 381 /** 382 * Attempts to construct an instance of {@code type} from the fuzzer input using only public 383 * methods available on the classpath. 384 * <p> 385 * <b>Note:</b> This function is inherently heuristic and may fail to return meaningful values for 386 * a variety of reasons. 387 * 388 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 389 * @param type the {@link Class} to construct an instance of. 390 * @return an instance of {@code type} constructed from the fuzzer input, or {@code null} if 391 * autofuzz failed to create an instance. 392 */ 393 @SuppressWarnings("unchecked") consume(FuzzedDataProvider data, Class<T> type)394 public static <T> T consume(FuzzedDataProvider data, Class<T> type) { 395 try { 396 return (T) CONSUME.invokeExact(data, type); 397 } catch (AutofuzzConstructionException ignored) { 398 return null; 399 } catch (Throwable t) { 400 rethrowUnchecked(t); 401 // Not reached. 402 return null; 403 } 404 } 405 406 // Rethrows a (possibly checked) exception while avoiding a throws declaration. 407 @SuppressWarnings("unchecked") rethrowUnchecked(Throwable t)408 private static <T extends Throwable> void rethrowUnchecked(Throwable t) throws T { 409 throw(T) t; 410 } 411 } 412