• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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