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 import java.lang.reflect.InvocationTargetException; 21 import java.security.SecureRandom; 22 23 /** 24 * Helper class with static methods that interact with Jazzer at runtime. 25 */ 26 final public class Jazzer { 27 /** 28 * A 32-bit random number that hooks can use to make pseudo-random choices 29 * between multiple possible mutations they could guide the fuzzer towards. 30 * Hooks <b>must not</b> base the decision whether or not to report a finding 31 * on this number as this will make findings non-reproducible. 32 * <p> 33 * This is the same number that libFuzzer uses as a seed internally, which 34 * makes it possible to deterministically reproduce a previous fuzzing run by 35 * supplying the seed value printed by libFuzzer as the value of the 36 * {@code -seed}. 37 */ 38 public static final int SEED = getLibFuzzerSeed(); 39 40 private static final Class<?> JAZZER_INTERNAL; 41 42 private static final MethodHandle ON_FUZZ_TARGET_READY; 43 44 private static final MethodHandle TRACE_STRCMP; 45 private static final MethodHandle TRACE_STRSTR; 46 private static final MethodHandle TRACE_MEMCMP; 47 private static final MethodHandle TRACE_PC_INDIR; 48 49 private static final MethodHandle CONSUME; 50 private static final MethodHandle AUTOFUZZ_FUNCTION_1; 51 private static final MethodHandle AUTOFUZZ_FUNCTION_2; 52 private static final MethodHandle AUTOFUZZ_FUNCTION_3; 53 private static final MethodHandle AUTOFUZZ_FUNCTION_4; 54 private static final MethodHandle AUTOFUZZ_FUNCTION_5; 55 private static final MethodHandle AUTOFUZZ_CONSUMER_1; 56 private static final MethodHandle AUTOFUZZ_CONSUMER_2; 57 private static final MethodHandle AUTOFUZZ_CONSUMER_3; 58 private static final MethodHandle AUTOFUZZ_CONSUMER_4; 59 private static final MethodHandle AUTOFUZZ_CONSUMER_5; 60 61 static { 62 Class<?> jazzerInternal = null; 63 MethodHandle onFuzzTargetReady = null; 64 MethodHandle traceStrcmp = null; 65 MethodHandle traceStrstr = null; 66 MethodHandle traceMemcmp = null; 67 MethodHandle tracePcIndir = null; 68 MethodHandle consume = null; 69 MethodHandle autofuzzFunction1 = null; 70 MethodHandle autofuzzFunction2 = null; 71 MethodHandle autofuzzFunction3 = null; 72 MethodHandle autofuzzFunction4 = null; 73 MethodHandle autofuzzFunction5 = null; 74 MethodHandle autofuzzConsumer1 = null; 75 MethodHandle autofuzzConsumer2 = null; 76 MethodHandle autofuzzConsumer3 = null; 77 MethodHandle autofuzzConsumer4 = null; 78 MethodHandle autofuzzConsumer5 = null; 79 try { 80 jazzerInternal = Class.forName("com.code_intelligence.jazzer.runtime.JazzerInternal"); 81 MethodType onFuzzTargetReadyType = MethodType.methodType(void.class, Runnable.class); 82 onFuzzTargetReady = MethodHandles.publicLookup().findStatic( 83 jazzerInternal, "registerOnFuzzTargetReadyCallback", onFuzzTargetReadyType); 84 Class<?> traceDataFlowNativeCallbacks = 85 Class.forName("com.code_intelligence.jazzer.runtime.TraceDataFlowNativeCallbacks"); 86 87 // Use method handles for hints as the calls are potentially performance critical. 88 MethodType traceStrcmpType = 89 MethodType.methodType(void.class, String.class, String.class, int.class, int.class); 90 traceStrcmp = MethodHandles.publicLookup().findStatic( 91 traceDataFlowNativeCallbacks, "traceStrcmp", traceStrcmpType); 92 MethodType traceStrstrType = 93 MethodType.methodType(void.class, String.class, String.class, int.class); 94 traceStrstr = MethodHandles.publicLookup().findStatic( 95 traceDataFlowNativeCallbacks, "traceStrstr", traceStrstrType); 96 MethodType traceMemcmpType = 97 MethodType.methodType(void.class, byte[].class, byte[].class, int.class, int.class); 98 traceMemcmp = MethodHandles.publicLookup().findStatic( 99 traceDataFlowNativeCallbacks, "traceMemcmp", traceMemcmpType); 100 MethodType tracePcIndirType = MethodType.methodType(void.class, int.class, int.class); 101 tracePcIndir = MethodHandles.publicLookup().findStatic( 102 traceDataFlowNativeCallbacks, "tracePcIndir", tracePcIndirType); 103 104 Class<?> metaClass = Class.forName("com.code_intelligence.jazzer.autofuzz.Meta"); 105 MethodType consumeType = 106 MethodType.methodType(Object.class, FuzzedDataProvider.class, Class.class); 107 consume = MethodHandles.publicLookup().findStatic(metaClass, "consume", consumeType); 108 109 autofuzzFunction1 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 110 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function1.class)); 111 autofuzzFunction2 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 112 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function2.class)); 113 autofuzzFunction3 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 114 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function3.class)); 115 autofuzzFunction4 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 116 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function4.class)); 117 autofuzzFunction5 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 118 MethodType.methodType(Object.class, FuzzedDataProvider.class, Function5.class)); 119 autofuzzConsumer1 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 120 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer1.class)); 121 autofuzzConsumer2 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 122 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer2.class)); 123 autofuzzConsumer3 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 124 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer3.class)); 125 autofuzzConsumer4 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 126 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer4.class)); 127 autofuzzConsumer5 = MethodHandles.publicLookup().findStatic(metaClass, "autofuzz", 128 MethodType.methodType(void.class, FuzzedDataProvider.class, Consumer5.class)); 129 } catch (ClassNotFoundException ignore) { 130 // Not running in the context of the agent. This is fine as long as no methods are called on 131 // this class. 132 } catch (NoSuchMethodException | IllegalAccessException e) { 133 // This should never happen as the Jazzer API is loaded from the agent and thus should always 134 // match the version of the runtime classes. 135 System.err.println("ERROR: Incompatible version of the Jazzer API detected, please update."); 136 e.printStackTrace(); 137 System.exit(1); 138 } 139 JAZZER_INTERNAL = jazzerInternal; 140 ON_FUZZ_TARGET_READY = onFuzzTargetReady; 141 TRACE_STRCMP = traceStrcmp; 142 TRACE_STRSTR = traceStrstr; 143 TRACE_MEMCMP = traceMemcmp; 144 TRACE_PC_INDIR = tracePcIndir; 145 CONSUME = consume; 146 AUTOFUZZ_FUNCTION_1 = autofuzzFunction1; 147 AUTOFUZZ_FUNCTION_2 = autofuzzFunction2; 148 AUTOFUZZ_FUNCTION_3 = autofuzzFunction3; 149 AUTOFUZZ_FUNCTION_4 = autofuzzFunction4; 150 AUTOFUZZ_FUNCTION_5 = autofuzzFunction5; 151 AUTOFUZZ_CONSUMER_1 = autofuzzConsumer1; 152 AUTOFUZZ_CONSUMER_2 = autofuzzConsumer2; 153 AUTOFUZZ_CONSUMER_3 = autofuzzConsumer3; 154 AUTOFUZZ_CONSUMER_4 = autofuzzConsumer4; 155 AUTOFUZZ_CONSUMER_5 = autofuzzConsumer5; 156 } 157 Jazzer()158 private Jazzer() {} 159 160 /** 161 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 162 * using only public methods available on the classpath. 163 * <p> 164 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 165 * meaningful ways for a number of reasons. 166 * 167 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 168 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 169 * resolve ambiguities by explicitly casting to {@link Function1} with (partially) specified 170 * type variables, e.g. {@code (Function1<String, ?>) String::new}. 171 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 172 * the function. 173 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 174 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 175 * The {@link Throwable} is thrown unchecked. 176 */ 177 @SuppressWarnings("unchecked") autofuzz(FuzzedDataProvider data, Function1<T1, R> func)178 public static <T1, R> R autofuzz(FuzzedDataProvider data, Function1<T1, R> func) { 179 try { 180 return (R) AUTOFUZZ_FUNCTION_1.invoke(data, func); 181 } catch (AutofuzzInvocationException e) { 182 rethrowUnchecked(e.getCause()); 183 } catch (Throwable t) { 184 rethrowUnchecked(t); 185 } 186 // Not reached. 187 return null; 188 } 189 190 /** 191 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 192 * using only public methods available on the classpath. 193 * <p> 194 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 195 * meaningful ways for a number of reasons. 196 * 197 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 198 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 199 * resolve ambiguities by explicitly casting to {@link Function2} with (partially) specified 200 * type variables. 201 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 202 * the function. 203 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 204 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 205 * The {@link Throwable} is thrown unchecked. 206 */ 207 @SuppressWarnings("unchecked") autofuzz(FuzzedDataProvider data, Function2<T1, T2, R> func)208 public static <T1, T2, R> R autofuzz(FuzzedDataProvider data, Function2<T1, T2, R> func) { 209 try { 210 return (R) AUTOFUZZ_FUNCTION_2.invoke(data, func); 211 } catch (AutofuzzInvocationException e) { 212 rethrowUnchecked(e.getCause()); 213 } catch (Throwable t) { 214 rethrowUnchecked(t); 215 } 216 // Not reached. 217 return null; 218 } 219 220 /** 221 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 222 * using only public methods available on the classpath. 223 * <p> 224 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 225 * meaningful ways for a number of reasons. 226 * 227 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 228 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 229 * resolve ambiguities by explicitly casting to {@link Function3} with (partially) specified 230 * type variables. 231 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 232 * the function. 233 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 234 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 235 * The {@link Throwable} is thrown unchecked. 236 */ 237 @SuppressWarnings("unchecked") autofuzz(FuzzedDataProvider data, Function3<T1, T2, T3, R> func)238 public static <T1, T2, T3, R> R autofuzz(FuzzedDataProvider data, Function3<T1, T2, T3, R> func) { 239 try { 240 return (R) AUTOFUZZ_FUNCTION_3.invoke(data, func); 241 } catch (AutofuzzInvocationException e) { 242 rethrowUnchecked(e.getCause()); 243 } catch (Throwable t) { 244 rethrowUnchecked(t); 245 } 246 // Not reached. 247 return null; 248 } 249 250 /** 251 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 252 * using only public methods available on the classpath. 253 * <p> 254 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 255 * meaningful ways for a number of reasons. 256 * 257 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 258 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 259 * resolve ambiguities by explicitly casting to {@link Function4} with (partially) specified 260 * type variables. 261 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 262 * the function. 263 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 264 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 265 * The {@link Throwable} is thrown unchecked. 266 */ 267 @SuppressWarnings("unchecked") autofuzz( FuzzedDataProvider data, Function4<T1, T2, T3, T4, R> func)268 public static <T1, T2, T3, T4, R> R autofuzz( 269 FuzzedDataProvider data, Function4<T1, T2, T3, T4, R> func) { 270 try { 271 return (R) AUTOFUZZ_FUNCTION_4.invoke(data, func); 272 } catch (AutofuzzInvocationException e) { 273 rethrowUnchecked(e.getCause()); 274 } catch (Throwable t) { 275 rethrowUnchecked(t); 276 } 277 // Not reached. 278 return null; 279 } 280 281 /** 282 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 283 * using only public methods available on the classpath. 284 * <p> 285 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 286 * meaningful ways for a number of reasons. 287 * 288 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 289 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 290 * resolve ambiguities by explicitly casting to {@link Function5} with (partially) specified 291 * type variables. 292 * @return the return value of {@code func}, or {@code null} if {@code autofuzz} failed to invoke 293 * the function. 294 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 295 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 296 * The {@link Throwable} is thrown unchecked. 297 */ 298 @SuppressWarnings("unchecked") autofuzz( FuzzedDataProvider data, Function5<T1, T2, T3, T4, T5, R> func)299 public static <T1, T2, T3, T4, T5, R> R autofuzz( 300 FuzzedDataProvider data, Function5<T1, T2, T3, T4, T5, R> func) { 301 try { 302 return (R) AUTOFUZZ_FUNCTION_5.invoke(data, func); 303 } catch (AutofuzzInvocationException e) { 304 rethrowUnchecked(e.getCause()); 305 } catch (Throwable t) { 306 rethrowUnchecked(t); 307 } 308 // Not reached. 309 return null; 310 } 311 312 /** 313 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 314 * using only public methods available on the classpath. 315 * <p> 316 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 317 * meaningful ways for a number of reasons. 318 * 319 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 320 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 321 * resolve ambiguities by explicitly casting to {@link Consumer1} with explicitly specified 322 * type variable. 323 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 324 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 325 * The {@link Throwable} is thrown unchecked. 326 */ autofuzz(FuzzedDataProvider data, Consumer1<T1> func)327 public static <T1> void autofuzz(FuzzedDataProvider data, Consumer1<T1> func) { 328 try { 329 AUTOFUZZ_CONSUMER_1.invoke(data, func); 330 } catch (AutofuzzInvocationException e) { 331 rethrowUnchecked(e.getCause()); 332 } catch (Throwable t) { 333 rethrowUnchecked(t); 334 } 335 } 336 337 /** 338 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 339 * using only public methods available on the classpath. 340 * <p> 341 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 342 * meaningful ways for a number of reasons. 343 * 344 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 345 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 346 * resolve ambiguities by explicitly casting to {@link Consumer2} with (partially) specified 347 * type variables. 348 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 349 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 350 * The {@link Throwable} is thrown unchecked. 351 */ autofuzz(FuzzedDataProvider data, Consumer2<T1, T2> func)352 public static <T1, T2> void autofuzz(FuzzedDataProvider data, Consumer2<T1, T2> func) { 353 try { 354 AUTOFUZZ_CONSUMER_2.invoke(data, func); 355 } catch (AutofuzzInvocationException e) { 356 rethrowUnchecked(e.getCause()); 357 } catch (Throwable t) { 358 rethrowUnchecked(t); 359 } 360 } 361 362 /** 363 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 364 * using only public methods available on the classpath. 365 * <p> 366 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 367 * meaningful ways for a number of reasons. 368 * 369 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 370 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 371 * resolve ambiguities by explicitly casting to {@link Consumer3} with (partially) specified 372 * type variables. 373 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 374 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 375 * The {@link Throwable} is thrown unchecked. 376 */ autofuzz(FuzzedDataProvider data, Consumer3<T1, T2, T3> func)377 public static <T1, T2, T3> void autofuzz(FuzzedDataProvider data, Consumer3<T1, T2, T3> func) { 378 try { 379 AUTOFUZZ_CONSUMER_3.invoke(data, func); 380 } catch (AutofuzzInvocationException e) { 381 rethrowUnchecked(e.getCause()); 382 } catch (Throwable t) { 383 rethrowUnchecked(t); 384 } 385 } 386 387 /** 388 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 389 * using only public methods available on the classpath. 390 * <p> 391 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 392 * meaningful ways for a number of reasons. 393 * 394 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 395 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 396 * resolve ambiguities by explicitly casting to {@link Consumer4} with (partially) specified 397 * type variables. 398 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 399 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 400 * The {@link Throwable} is thrown unchecked. 401 */ autofuzz( FuzzedDataProvider data, Consumer4<T1, T2, T3, T4> func)402 public static <T1, T2, T3, T4> void autofuzz( 403 FuzzedDataProvider data, Consumer4<T1, T2, T3, T4> func) { 404 try { 405 AUTOFUZZ_CONSUMER_4.invoke(data, func); 406 } catch (AutofuzzInvocationException e) { 407 rethrowUnchecked(e.getCause()); 408 } catch (Throwable t) { 409 rethrowUnchecked(t); 410 } 411 } 412 413 /** 414 * Attempts to invoke {@code func} with arguments created automatically from the fuzzer input 415 * using only public methods available on the classpath. 416 * <p> 417 * <b>Note:</b> This function is inherently heuristic and may fail to execute {@code func} in 418 * meaningful ways for a number of reasons. 419 * 420 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 421 * @param func a method reference for the function to autofuzz. If there are multiple overloads, 422 * resolve ambiguities by explicitly casting to {@link Consumer5} with (partially) specified 423 * type variables. 424 * @throws Throwable any {@link Throwable} thrown by {@code func}, or an {@link 425 * AutofuzzConstructionException} if autofuzz failed to construct the arguments for the call. 426 * The {@link Throwable} is thrown unchecked. 427 */ autofuzz( FuzzedDataProvider data, Consumer5<T1, T2, T3, T4, T5> func)428 public static <T1, T2, T3, T4, T5> void autofuzz( 429 FuzzedDataProvider data, Consumer5<T1, T2, T3, T4, T5> func) { 430 try { 431 AUTOFUZZ_CONSUMER_5.invoke(data, func); 432 } catch (AutofuzzInvocationException e) { 433 rethrowUnchecked(e.getCause()); 434 } catch (Throwable t) { 435 rethrowUnchecked(t); 436 } 437 } 438 439 /** 440 * Attempts to construct an instance of {@code type} from the fuzzer input using only public 441 * methods available on the classpath. 442 * <p> 443 * <b>Note:</b> This function is inherently heuristic and may fail to return meaningful values for 444 * a variety of reasons. 445 * 446 * @param data the {@link FuzzedDataProvider} instance provided to {@code fuzzerTestOneInput}. 447 * @param type the {@link Class} to construct an instance of. 448 * @return an instance of {@code type} constructed from the fuzzer input, or {@code null} if 449 * autofuzz failed to create an instance. 450 */ 451 @SuppressWarnings("unchecked") consume(FuzzedDataProvider data, Class<T> type)452 public static <T> T consume(FuzzedDataProvider data, Class<T> type) { 453 try { 454 return (T) CONSUME.invokeExact(data, type); 455 } catch (AutofuzzConstructionException ignored) { 456 return null; 457 } catch (Throwable t) { 458 rethrowUnchecked(t); 459 // Not reached. 460 return null; 461 } 462 } 463 464 /** 465 * Instructs the fuzzer to guide its mutations towards making {@code current} equal to {@code 466 * target}. 467 * <p> 468 * If the relation between the raw fuzzer input and the value of {@code current} is relatively 469 * complex, running the fuzzer with the argument {@code -use_value_profile=1} may be necessary to 470 * achieve equality. 471 * 472 * @param current a non-constant string observed during fuzz target execution 473 * @param target a string that {@code current} should become equal to, but currently isn't 474 * @param id a (probabilistically) unique identifier for this particular compare hint 475 */ guideTowardsEquality(String current, String target, int id)476 public static void guideTowardsEquality(String current, String target, int id) { 477 if (TRACE_STRCMP == null) { 478 return; 479 } 480 try { 481 TRACE_STRCMP.invokeExact(current, target, 1, id); 482 } catch (Throwable e) { 483 e.printStackTrace(); 484 } 485 } 486 487 /** 488 * Instructs the fuzzer to guide its mutations towards making {@code current} equal to {@code 489 * target}. 490 * <p> 491 * If the relation between the raw fuzzer input and the value of {@code current} is relatively 492 * complex, running the fuzzer with the argument {@code -use_value_profile=1} may be necessary to 493 * achieve equality. 494 * 495 * @param current a non-constant byte array observed during fuzz target execution 496 * @param target a byte array that {@code current} should become equal to, but currently isn't 497 * @param id a (probabilistically) unique identifier for this particular compare hint 498 */ guideTowardsEquality(byte[] current, byte[] target, int id)499 public static void guideTowardsEquality(byte[] current, byte[] target, int id) { 500 if (TRACE_MEMCMP == null) { 501 return; 502 } 503 try { 504 TRACE_MEMCMP.invokeExact(current, target, 1, id); 505 } catch (Throwable e) { 506 e.printStackTrace(); 507 } 508 } 509 510 /** 511 * Instructs the fuzzer to guide its mutations towards making {@code haystack} contain {@code 512 * needle} as a substring. 513 * <p> 514 * If the relation between the raw fuzzer input and the value of {@code haystack} is relatively 515 * complex, running the fuzzer with the argument {@code -use_value_profile=1} may be necessary to 516 * satisfy the substring check. 517 * 518 * @param haystack a non-constant string observed during fuzz target execution 519 * @param needle a string that should be contained in {@code haystack} as a substring, but 520 * currently isn't 521 * @param id a (probabilistically) unique identifier for this particular compare hint 522 */ guideTowardsContainment(String haystack, String needle, int id)523 public static void guideTowardsContainment(String haystack, String needle, int id) { 524 if (TRACE_STRSTR == null) { 525 return; 526 } 527 try { 528 TRACE_STRSTR.invokeExact(haystack, needle, id); 529 } catch (Throwable e) { 530 e.printStackTrace(); 531 } 532 } 533 534 /** 535 * Instructs the fuzzer to attain as many possible values for the absolute value of {@code state} 536 * as possible. 537 * <p> 538 * Call this function from a fuzz target or a hook to help the fuzzer track partial progress 539 * (e.g. by passing the length of a common prefix of two lists that should become equal) or 540 * explore different values of state that is not directly related to code coverage (see the 541 * MazeFuzzer example). 542 * <p> 543 * <b>Note:</b> This hint only takes effect if the fuzzer is run with the argument 544 * {@code -use_value_profile=1}. 545 * 546 * @param state a numeric encoding of a state that should be varied by the fuzzer 547 * @param id a (probabilistically) unique identifier for this particular state hint 548 */ exploreState(byte state, int id)549 public static void exploreState(byte state, int id) { 550 if (TRACE_PC_INDIR == null) { 551 return; 552 } 553 // We only use the lower 7 bits of state, which allows for 128 different state values tracked 554 // per id. The particular amount of 7 bits of state is also used in libFuzzer's 555 // TracePC::HandleCmp: 556 // https://github.com/llvm/llvm-project/blob/c12d49c4e286fa108d4d69f1c6d2b8d691993ffd/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp#L390 557 // This value should be large enough for most use cases (e.g. tracking the length of a prefix in 558 // a comparison) while being small enough that the bitmap isn't filled up too quickly 559 // (65536 bits/ 128 bits per id = 512 ids). 560 561 // We use tracePcIndir as a way to set a bit in libFuzzer's value profile bitmap. In 562 // TracePC::HandleCallerCallee, which is what this function ultimately calls through to, the 563 // lower 12 bits of each argument are combined into a 24-bit index into the bitmap, which is 564 // then reduced modulo a 16-bit prime. To keep the modulo bias small, we should fill as many 565 // of the relevant bits as possible. However, there are the following restrictions: 566 // 1. Since we use the return address trampoline to set the caller address indirectly, its 567 // upper 3 bits are fixed, which leaves a total of 21 variable bits on x86_64. 568 // 2. On arm64 macOS, where every instruction is aligned to 4 bytes, the lower 2 bits of the 569 // caller address will always be zero, further reducing the number of variable bits in the 570 // caller parameter to 7. 571 // https://github.com/llvm/llvm-project/blob/c12d49c4e286fa108d4d69f1c6d2b8d691993ffd/compiler-rt/lib/fuzzer/FuzzerTracePC.cpp#L121 572 // Even taking these restrictions into consideration, we pass state in the lowest bits of the 573 // caller address, which is used to form the lowest bits of the bitmap index. This should result 574 // in the best caching behavior as state is expected to change quickly in consecutive runs and 575 // in this way all its bitmap entries would be located close to each other in memory. 576 int lowerBits = (state & 0x7f) | (id << 7); 577 int upperBits = id >>> 5; 578 try { 579 TRACE_PC_INDIR.invokeExact(upperBits, lowerBits); 580 } catch (Throwable e) { 581 e.printStackTrace(); 582 } 583 } 584 585 /** 586 * Make Jazzer report the provided {@link Throwable} as a finding. 587 * <p> 588 * <b>Note:</b> This method must only be called from a method hook. In a 589 * fuzz target, simply throw an exception to trigger a finding. 590 * @param finding the finding that Jazzer should report 591 */ reportFindingFromHook(Throwable finding)592 public static void reportFindingFromHook(Throwable finding) { 593 try { 594 JAZZER_INTERNAL.getMethod("reportFindingFromHook", Throwable.class).invoke(null, finding); 595 } catch (NullPointerException | IllegalAccessException | NoSuchMethodException e) { 596 // We can only reach this point if the runtime is not on the classpath, e.g. in case of a 597 // reproducer. Just throw the finding. 598 rethrowUnchecked(finding); 599 } catch (InvocationTargetException e) { 600 // reportFindingFromHook throws a HardToCatchThrowable, which will bubble up wrapped in an 601 // InvocationTargetException that should not be stopped here. 602 if (e.getCause().getClass().getName().endsWith(".HardToCatchError")) { 603 throw(Error) e.getCause(); 604 } else { 605 e.printStackTrace(); 606 } 607 } 608 } 609 610 /** 611 * Register a callback to be executed right before the fuzz target is executed for the first time. 612 * <p> 613 * This can be used to disable hooks until after Jazzer has been fully initializing, e.g. to 614 * prevent Jazzer internals from triggering hooks on Java standard library classes. 615 * 616 * @param callback the callback to execute 617 */ onFuzzTargetReady(Runnable callback)618 public static void onFuzzTargetReady(Runnable callback) { 619 try { 620 ON_FUZZ_TARGET_READY.invokeExact(callback); 621 } catch (Throwable e) { 622 e.printStackTrace(); 623 } 624 } 625 getLibFuzzerSeed()626 private static int getLibFuzzerSeed() { 627 // The Jazzer driver sets this property based on the value of libFuzzer's -seed command-line 628 // option, which allows for fully reproducible fuzzing runs if set. If not running in the 629 // context of the driver, fall back to a random number instead. 630 String rawSeed = System.getProperty("jazzer.seed"); 631 if (rawSeed == null) { 632 return new SecureRandom().nextInt(); 633 } 634 // If jazzer.seed is set, we expect it to be a valid integer. 635 return Integer.parseUnsignedInt(rawSeed); 636 } 637 638 // Rethrows a (possibly checked) exception while avoiding a throws declaration. 639 @SuppressWarnings("unchecked") rethrowUnchecked(Throwable t)640 private static <T extends Throwable> void rethrowUnchecked(Throwable t) throws T { 641 throw(T) t; 642 } 643 } 644