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