• 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.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collection;
20 import java.util.List;
21 import java.util.Random;
22 
23 /**
24  * A convenience wrapper turning the raw fuzzer input bytes into Java primitive types.
25  *
26  * <p>The methods defined by this interface behave similarly to {@link Random#nextInt()}, with all
27  * returned values depending deterministically on the fuzzer input for the current run.
28  */
29 public interface FuzzedDataProvider {
30   /**
31    * Consumes a {@code boolean} from the fuzzer input.
32    *
33    * @return a {@code boolean}
34    */
consumeBoolean()35   boolean consumeBoolean();
36 
37   /**
38    * Consumes a {@code boolean} array from the fuzzer input.
39    * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
40    * is not sufficiently long.
41    *
42    * @param maxLength the maximum length of the array
43    * @return a {@code boolean} array of length at most {@code length}
44    */
consumeBooleans(int maxLength)45   boolean[] consumeBooleans(int maxLength);
46 
47   /**
48    * Consumes a {@code byte} from the fuzzer input.
49    *
50    * @return a {@code byte}
51    */
consumeByte()52   byte consumeByte();
53 
54   /**
55    * Consumes a {@code byte} between {@code min} and {@code max} from the fuzzer input.
56    *
57    * @param min the inclusive lower bound on the returned value
58    * @param max the inclusive upper bound on the returned value
59    * @return a {@code byte} in the range {@code [min, max]}
60    */
consumeByte(byte min, byte max)61   byte consumeByte(byte min, byte max);
62 
63   /**
64    * Consumes a {@code byte} array from the fuzzer input.
65    * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
66    * is not sufficiently long.
67    *
68    * @param maxLength the maximum length of the array
69    * @return a {@code byte} array of length at most {@code length}
70    */
consumeBytes(int maxLength)71   byte[] consumeBytes(int maxLength);
72 
73   /**
74    * Consumes the remaining fuzzer input as a {@code byte} array.
75    * <p><b>Note:</b> After calling this method, further calls to methods of this interface will
76    * return fixed values only.
77    *
78    * @return a {@code byte} array
79    */
consumeRemainingAsBytes()80   byte[] consumeRemainingAsBytes();
81 
82   /**
83    * Consumes a {@code short} from the fuzzer input.
84    *
85    * @return a {@code short}
86    */
consumeShort()87   short consumeShort();
88 
89   /**
90    * Consumes a {@code short} between {@code min} and {@code max} from the fuzzer input.
91    *
92    * @param min the inclusive lower bound on the returned value
93    * @param max the inclusive upper bound on the returned value
94    * @return a {@code short} in the range {@code [min, max]}
95    */
consumeShort(short min, short max)96   short consumeShort(short min, short max);
97 
98   /**
99    * Consumes a {@code short} array from the fuzzer input.
100    * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
101    * is not sufficiently long.
102    *
103    * @param maxLength the maximum length of the array
104    * @return a {@code short} array of length at most {@code length}
105    */
consumeShorts(int maxLength)106   short[] consumeShorts(int maxLength);
107 
108   /**
109    * Consumes an {@code int} from the fuzzer input.
110    *
111    * @return an {@code int}
112    */
consumeInt()113   int consumeInt();
114 
115   /**
116    * Consumes an {@code int} between {@code min} and {@code max} from the fuzzer input.
117    *
118    * @param min the inclusive lower bound on the returned value
119    * @param max the inclusive upper bound on the returned value
120    * @return an {@code int} in the range {@code [min, max]}
121    */
consumeInt(int min, int max)122   int consumeInt(int min, int max);
123 
124   /**
125    * Consumes an {@code int} array from the fuzzer input.
126    * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
127    * is not sufficiently long.
128    *
129    * @param maxLength the maximum length of the array
130    * @return an {@code int} array of length at most {@code length}
131    */
consumeInts(int maxLength)132   int[] consumeInts(int maxLength);
133 
134   /**
135    * Consumes a {@code long} from the fuzzer input.
136    *
137    * @return a {@code long}
138    */
consumeLong()139   long consumeLong();
140 
141   /**
142    * Consumes a {@code long} between {@code min} and {@code max} from the fuzzer input.
143    *
144    * @param min the inclusive lower bound on the returned value
145    * @param max the inclusive upper bound on the returned value
146    * @return a {@code long} in the range @{code [min, max]}
147    */
consumeLong(long min, long max)148   long consumeLong(long min, long max);
149 
150   /**
151    * Consumes a {@code long} array from the fuzzer input.
152    * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
153    * is not sufficiently long.
154    *
155    * @param maxLength the maximum length of the array
156    * @return a {@code long} array of length at most {@code length}
157    */
consumeLongs(int maxLength)158   long[] consumeLongs(int maxLength);
159 
160   /**
161    * Consumes a {@code float} from the fuzzer input.
162    *
163    * @return a {@code float} that may have a special value (e.g. a NaN or infinity)
164    */
consumeFloat()165   float consumeFloat();
166 
167   /**
168    * Consumes a regular {@code float} from the fuzzer input.
169    *
170    * @return a {@code float} that is not a special value (e.g. not a NaN or infinity)
171    */
consumeRegularFloat()172   float consumeRegularFloat();
173 
174   /**
175    * Consumes a regular {@code float} between {@code min} and {@code max} from the fuzzer input.
176    *
177    * @return a {@code float} in the range {@code [min, max]}
178    */
consumeRegularFloat(float min, float max)179   float consumeRegularFloat(float min, float max);
180 
181   /**
182    * Consumes a {@code float} between 0.0 and 1.0 (inclusive) from the fuzzer input.
183    *
184    * @return a {@code float} in the range {@code [0.0, 1.0]}
185    */
consumeProbabilityFloat()186   float consumeProbabilityFloat();
187 
188   /**
189    * Consumes a {@code double} from the fuzzer input.
190    *
191    * @return a {@code double} that may have a special value (e.g. a NaN or infinity)
192    */
consumeDouble()193   double consumeDouble();
194 
195   /**
196    * Consumes a regular {@code double} from the fuzzer input.
197    *
198    * @return a {@code double} that is not a special value (e.g. not a NaN or infinity)
199    */
consumeRegularDouble()200   double consumeRegularDouble();
201 
202   /**
203    * Consumes a regular {@code double} between {@code min} and {@code max} from the fuzzer input.
204    *
205    * @return a {@code double} in the range {@code [min, max]}
206    */
consumeRegularDouble(double min, double max)207   double consumeRegularDouble(double min, double max);
208 
209   /**
210    * Consumes a {@code double} between 0.0 and 1.0 (inclusive) from the fuzzer input.
211    *
212    * @return a {@code double} in the range {@code [0.0, 1.0]}
213    */
consumeProbabilityDouble()214   double consumeProbabilityDouble();
215 
216   /**
217    * Consumes a {@code char} from the fuzzer input.
218    */
consumeChar()219   char consumeChar();
220 
221   /**
222    * Consumes a {@code char} between {@code min} and {@code max} from the fuzzer input.
223    *
224    * @param min the inclusive lower bound on the returned value
225    * @param max the inclusive upper bound on the returned value
226    * @return a {@code char} in the range {@code [min, max]}
227    */
consumeChar(char min, char max)228   char consumeChar(char min, char max);
229 
230   /**
231    * Consumes a {@code char} from the fuzzer input that is never a UTF-16 surrogate character.
232    */
consumeCharNoSurrogates()233   char consumeCharNoSurrogates();
234 
235   /**
236    * Consumes a {@link String} from the fuzzer input.
237    * <p>The returned string may be of any length between 0 and {@code maxLength}, even if there is
238    * more fuzzer input available.
239    *
240    * @param maxLength the maximum length of the string
241    * @return a {@link String} of length between 0 and {@code maxLength} (inclusive)
242    */
consumeString(int maxLength)243   String consumeString(int maxLength);
244 
245   /**
246    * Consumes the remaining fuzzer input as a {@link String}.
247    * <p><b>Note:</b> After calling this method, further calls to methods of this interface will
248    * return fixed values only.
249    *
250    * @return a {@link String}
251    */
consumeRemainingAsString()252   String consumeRemainingAsString();
253 
254   /**
255    * Consumes an ASCII-only {@link String} from the fuzzer input.
256    * <p>The returned string may be of any length between 0 and {@code maxLength}, even if there is
257    * more fuzzer input available.
258    *
259    * @param maxLength the maximum length of the string
260    * @return a {@link String} of length between 0 and {@code maxLength} (inclusive) that contains
261    * only ASCII characters
262    */
consumeAsciiString(int maxLength)263   String consumeAsciiString(int maxLength);
264 
265   /**
266    * Consumes the remaining fuzzer input as an ASCII-only {@link String}.
267    * <p><b>Note:</b> After calling this method, further calls to methods of this interface will
268    * return fixed values only.
269    *
270    * @return a {@link String} that contains only ASCII characters
271    */
consumeRemainingAsAsciiString()272   String consumeRemainingAsAsciiString();
273 
274   /**
275    * Returns the number of unconsumed bytes in the fuzzer input.
276    *
277    * @return the number of unconsumed bytes in the fuzzer input
278    */
remainingBytes()279   int remainingBytes();
280 
281   /**
282    * Picks an element from {@code collection} based on the fuzzer input.
283    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
284    *
285    * @param collection the {@link Collection} to pick an element from.
286    * @param <T> the type of the collection element
287    * @return an element from {@code collection} chosen based on the fuzzer input
288    */
289   @SuppressWarnings("unchecked")
pickValue(Collection<T> collection)290   default<T> T pickValue(Collection<T> collection) {
291     int size = collection.size();
292     if (size == 0) {
293       throw new IllegalArgumentException("collection is empty");
294     }
295     if (collection instanceof List<?>) {
296       return ((List<T>) collection).get(consumeInt(0, size - 1));
297     } else {
298       return (T) pickValue(collection.toArray());
299     }
300   }
301 
302   /**
303    * Picks an element from {@code array} based on the fuzzer input.
304    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
305    *
306    * @param array the array to pick an element from.
307    * @param <T> the type of the array element
308    * @return an element from {@code array} chosen based on the fuzzer input
309    */
pickValue(T[] array)310   default<T> T pickValue(T[] array) {
311     return array[consumeInt(0, array.length - 1)];
312   }
313 
314   /**
315    * Picks an element from {@code array} based on the fuzzer input.
316    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
317    *
318    * @param array the array to pick an element from.
319    * @return an element from {@code array} chosen based on the fuzzer input
320    */
pickValue(boolean[] array)321   default boolean pickValue(boolean[] array) {
322     return array[consumeInt(0, array.length - 1)];
323   }
324 
325   /**
326    * Picks an element from {@code array} based on the fuzzer input.
327    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
328    *
329    * @param array the array to pick an element from.
330    * @return an element from {@code array} chosen based on the fuzzer input
331    */
pickValue(byte[] array)332   default byte pickValue(byte[] array) {
333     return array[consumeInt(0, array.length - 1)];
334   }
335 
336   /**
337    * Picks an element from {@code array} based on the fuzzer input.
338    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
339    *
340    * @param array the array to pick an element from.
341    * @return an element from {@code array} chosen based on the fuzzer input
342    */
pickValue(short[] array)343   default short pickValue(short[] array) {
344     return array[consumeInt(0, array.length - 1)];
345   }
346 
347   /**
348    * Picks an element from {@code array} based on the fuzzer input.
349    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
350    *
351    * @param array the array to pick an element from.
352    * @return an element from {@code array} chosen based on the fuzzer input
353    */
pickValue(int[] array)354   default int pickValue(int[] array) {
355     return array[consumeInt(0, array.length - 1)];
356   }
357 
358   /**
359    * Picks an element from {@code array} based on the fuzzer input.
360    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
361    *
362    * @param array the array to pick an element from.
363    * @return an element from {@code array} chosen based on the fuzzer input
364    */
pickValue(long[] array)365   default long pickValue(long[] array) {
366     return array[consumeInt(0, array.length - 1)];
367   }
368 
369   /**
370    * Picks an element from {@code array} based on the fuzzer input.
371    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
372    *
373    * @param array the array to pick an element from.
374    * @return an element from {@code array} chosen based on the fuzzer input
375    */
pickValue(double[] array)376   default double pickValue(double[] array) {
377     return array[consumeInt(0, array.length - 1)];
378   }
379 
380   /**
381    * Picks an element from {@code array} based on the fuzzer input.
382    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
383    *
384    * @param array the array to pick an element from.
385    * @return an element from {@code array} chosen based on the fuzzer input
386    */
pickValue(float[] array)387   default float pickValue(float[] array) {
388     return array[consumeInt(0, array.length - 1)];
389   }
390 
391   /**
392    * Picks an element from {@code array} based on the fuzzer input.
393    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
394    *
395    * @param array the array to pick an element from.
396    * @return an element from {@code array} chosen based on the fuzzer input
397    */
pickValue(char[] array)398   default char pickValue(char[] array) {
399     return array[consumeInt(0, array.length - 1)];
400   }
401 
402   /**
403    * Picks {@code numOfElements} elements from {@code collection} based on the fuzzer input.
404    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
405    *
406    * @param collection the {@link Collection} to pick an element from.
407    * @param numOfElements the number of elements to pick.
408    * @param <T> the type of the collection element
409    * @return an array of size {@code numOfElements} from {@code collection} chosen based on the
410    *     fuzzer input
411    */
pickValues(Collection<T> collection, int numOfElements)412   default<T> List<T> pickValues(Collection<T> collection, int numOfElements) {
413     int size = collection.size();
414     if (size == 0) {
415       throw new IllegalArgumentException("collection is empty");
416     }
417     if (numOfElements > collection.size()) {
418       throw new IllegalArgumentException("numOfElements exceeds collection.size()");
419     }
420 
421     List<T> remainingElements = new ArrayList<>(collection);
422     List<T> pickedElements = new ArrayList<>();
423     for (int i = 0; i < numOfElements; i++) {
424       T element = pickValue(remainingElements);
425       pickedElements.add(element);
426       remainingElements.remove(element);
427     }
428     return pickedElements;
429   }
430 
431   /**
432    * Picks {@code numOfElements} elements from {@code array} based on the fuzzer input.
433    * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
434    *
435    * @param array the array to pick an element from.
436    * @param numOfElements the number of elements to pick.
437    * @param <T> the type of the array element
438    * @return an array of size {@code numOfElements} from {@code array} chosen based on the fuzzer
439    *     input
440    */
pickValues(T[] array, int numOfElements)441   default<T> List<T> pickValues(T[] array, int numOfElements) {
442     return pickValues(Arrays.asList(array), numOfElements);
443   }
444 }
445