• 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 
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