aboutsummaryrefslogtreecommitdiff
path: root/agent/src/main/java/com/code_intelligence/jazzer/api/FuzzedDataProvider.java
diff options
context:
space:
mode:
Diffstat (limited to 'agent/src/main/java/com/code_intelligence/jazzer/api/FuzzedDataProvider.java')
-rw-r--r--agent/src/main/java/com/code_intelligence/jazzer/api/FuzzedDataProvider.java444
1 files changed, 444 insertions, 0 deletions
diff --git a/agent/src/main/java/com/code_intelligence/jazzer/api/FuzzedDataProvider.java b/agent/src/main/java/com/code_intelligence/jazzer/api/FuzzedDataProvider.java
new file mode 100644
index 00000000..b1f38b50
--- /dev/null
+++ b/agent/src/main/java/com/code_intelligence/jazzer/api/FuzzedDataProvider.java
@@ -0,0 +1,444 @@
+// Copyright 2021 Code Intelligence GmbH
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.code_intelligence.jazzer.api;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.List;
+import java.util.Random;
+
+/**
+ * A convenience wrapper turning the raw fuzzer input bytes into Java primitive types.
+ *
+ * <p>The methods defined by this interface behave similarly to {@link Random#nextInt()}, with all
+ * returned values depending deterministically on the fuzzer input for the current run.
+ */
+public interface FuzzedDataProvider {
+ /**
+ * Consumes a {@code boolean} from the fuzzer input.
+ *
+ * @return a {@code boolean}
+ */
+ boolean consumeBoolean();
+
+ /**
+ * Consumes a {@code boolean} array from the fuzzer input.
+ * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
+ * is not sufficiently long.
+ *
+ * @param maxLength the maximum length of the array
+ * @return a {@code boolean} array of length at most {@code length}
+ */
+ boolean[] consumeBooleans(int maxLength);
+
+ /**
+ * Consumes a {@code byte} from the fuzzer input.
+ *
+ * @return a {@code byte}
+ */
+ byte consumeByte();
+
+ /**
+ * Consumes a {@code byte} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @param min the inclusive lower bound on the returned value
+ * @param max the inclusive upper bound on the returned value
+ * @return a {@code byte} in the range {@code [min, max]}
+ */
+ byte consumeByte(byte min, byte max);
+
+ /**
+ * Consumes a {@code byte} array from the fuzzer input.
+ * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
+ * is not sufficiently long.
+ *
+ * @param maxLength the maximum length of the array
+ * @return a {@code byte} array of length at most {@code length}
+ */
+ byte[] consumeBytes(int maxLength);
+
+ /**
+ * Consumes the remaining fuzzer input as a {@code byte} array.
+ * <p><b>Note:</b> After calling this method, further calls to methods of this interface will
+ * return fixed values only.
+ *
+ * @return a {@code byte} array
+ */
+ byte[] consumeRemainingAsBytes();
+
+ /**
+ * Consumes a {@code short} from the fuzzer input.
+ *
+ * @return a {@code short}
+ */
+ short consumeShort();
+
+ /**
+ * Consumes a {@code short} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @param min the inclusive lower bound on the returned value
+ * @param max the inclusive upper bound on the returned value
+ * @return a {@code short} in the range {@code [min, max]}
+ */
+ short consumeShort(short min, short max);
+
+ /**
+ * Consumes a {@code short} array from the fuzzer input.
+ * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
+ * is not sufficiently long.
+ *
+ * @param maxLength the maximum length of the array
+ * @return a {@code short} array of length at most {@code length}
+ */
+ short[] consumeShorts(int maxLength);
+
+ /**
+ * Consumes an {@code int} from the fuzzer input.
+ *
+ * @return an {@code int}
+ */
+ int consumeInt();
+
+ /**
+ * Consumes an {@code int} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @param min the inclusive lower bound on the returned value
+ * @param max the inclusive upper bound on the returned value
+ * @return an {@code int} in the range {@code [min, max]}
+ */
+ int consumeInt(int min, int max);
+
+ /**
+ * Consumes an {@code int} array from the fuzzer input.
+ * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
+ * is not sufficiently long.
+ *
+ * @param maxLength the maximum length of the array
+ * @return an {@code int} array of length at most {@code length}
+ */
+ int[] consumeInts(int maxLength);
+
+ /**
+ * Consumes a {@code long} from the fuzzer input.
+ *
+ * @return a {@code long}
+ */
+ long consumeLong();
+
+ /**
+ * Consumes a {@code long} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @param min the inclusive lower bound on the returned value
+ * @param max the inclusive upper bound on the returned value
+ * @return a {@code long} in the range @{code [min, max]}
+ */
+ long consumeLong(long min, long max);
+
+ /**
+ * Consumes a {@code long} array from the fuzzer input.
+ * <p>The array will usually have length {@code length}, but might be shorter if the fuzzer input
+ * is not sufficiently long.
+ *
+ * @param maxLength the maximum length of the array
+ * @return a {@code long} array of length at most {@code length}
+ */
+ long[] consumeLongs(int maxLength);
+
+ /**
+ * Consumes a {@code float} from the fuzzer input.
+ *
+ * @return a {@code float} that may have a special value (e.g. a NaN or infinity)
+ */
+ float consumeFloat();
+
+ /**
+ * Consumes a regular {@code float} from the fuzzer input.
+ *
+ * @return a {@code float} that is not a special value (e.g. not a NaN or infinity)
+ */
+ float consumeRegularFloat();
+
+ /**
+ * Consumes a regular {@code float} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @return a {@code float} in the range {@code [min, max]}
+ */
+ float consumeRegularFloat(float min, float max);
+
+ /**
+ * Consumes a {@code float} between 0.0 and 1.0 (inclusive) from the fuzzer input.
+ *
+ * @return a {@code float} in the range {@code [0.0, 1.0]}
+ */
+ float consumeProbabilityFloat();
+
+ /**
+ * Consumes a {@code double} from the fuzzer input.
+ *
+ * @return a {@code double} that may have a special value (e.g. a NaN or infinity)
+ */
+ double consumeDouble();
+
+ /**
+ * Consumes a regular {@code double} from the fuzzer input.
+ *
+ * @return a {@code double} that is not a special value (e.g. not a NaN or infinity)
+ */
+ double consumeRegularDouble();
+
+ /**
+ * Consumes a regular {@code double} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @return a {@code double} in the range {@code [min, max]}
+ */
+ double consumeRegularDouble(double min, double max);
+
+ /**
+ * Consumes a {@code double} between 0.0 and 1.0 (inclusive) from the fuzzer input.
+ *
+ * @return a {@code double} in the range {@code [0.0, 1.0]}
+ */
+ double consumeProbabilityDouble();
+
+ /**
+ * Consumes a {@code char} from the fuzzer input.
+ */
+ char consumeChar();
+
+ /**
+ * Consumes a {@code char} between {@code min} and {@code max} from the fuzzer input.
+ *
+ * @param min the inclusive lower bound on the returned value
+ * @param max the inclusive upper bound on the returned value
+ * @return a {@code char} in the range {@code [min, max]}
+ */
+ char consumeChar(char min, char max);
+
+ /**
+ * Consumes a {@code char} from the fuzzer input that is never a UTF-16 surrogate character.
+ */
+ char consumeCharNoSurrogates();
+
+ /**
+ * Consumes a {@link String} from the fuzzer input.
+ * <p>The returned string may be of any length between 0 and {@code maxLength}, even if there is
+ * more fuzzer input available.
+ *
+ * @param maxLength the maximum length of the string
+ * @return a {@link String} of length between 0 and {@code maxLength} (inclusive)
+ */
+ String consumeString(int maxLength);
+
+ /**
+ * Consumes the remaining fuzzer input as a {@link String}.
+ * <p><b>Note:</b> After calling this method, further calls to methods of this interface will
+ * return fixed values only.
+ *
+ * @return a {@link String}
+ */
+ String consumeRemainingAsString();
+
+ /**
+ * Consumes an ASCII-only {@link String} from the fuzzer input.
+ * <p>The returned string may be of any length between 0 and {@code maxLength}, even if there is
+ * more fuzzer input available.
+ *
+ * @param maxLength the maximum length of the string
+ * @return a {@link String} of length between 0 and {@code maxLength} (inclusive) that contains
+ * only ASCII characters
+ */
+ String consumeAsciiString(int maxLength);
+
+ /**
+ * Consumes the remaining fuzzer input as an ASCII-only {@link String}.
+ * <p><b>Note:</b> After calling this method, further calls to methods of this interface will
+ * return fixed values only.
+ *
+ * @return a {@link String} that contains only ASCII characters
+ */
+ String consumeRemainingAsAsciiString();
+
+ /**
+ * Returns the number of unconsumed bytes in the fuzzer input.
+ *
+ * @return the number of unconsumed bytes in the fuzzer input
+ */
+ int remainingBytes();
+
+ /**
+ * Picks an element from {@code collection} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param collection the {@link Collection} to pick an element from.
+ * @param <T> the type of the collection element
+ * @return an element from {@code collection} chosen based on the fuzzer input
+ */
+ @SuppressWarnings("unchecked")
+ default<T> T pickValue(Collection<T> collection) {
+ int size = collection.size();
+ if (size == 0) {
+ throw new IllegalArgumentException("collection is empty");
+ }
+ if (collection instanceof List<?>) {
+ return ((List<T>) collection).get(consumeInt(0, size - 1));
+ } else {
+ return (T) pickValue(collection.toArray());
+ }
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @param <T> the type of the array element
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default<T> T pickValue(T[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default boolean pickValue(boolean[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default byte pickValue(byte[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default short pickValue(short[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default int pickValue(int[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default long pickValue(long[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default double pickValue(double[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default float pickValue(float[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks an element from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @return an element from {@code array} chosen based on the fuzzer input
+ */
+ default char pickValue(char[] array) {
+ return array[consumeInt(0, array.length - 1)];
+ }
+
+ /**
+ * Picks {@code numOfElements} elements from {@code collection} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param collection the {@link Collection} to pick an element from.
+ * @param numOfElements the number of elements to pick.
+ * @param <T> the type of the collection element
+ * @return an array of size {@code numOfElements} from {@code collection} chosen based on the
+ * fuzzer input
+ */
+ default<T> List<T> pickValues(Collection<T> collection, int numOfElements) {
+ int size = collection.size();
+ if (size == 0) {
+ throw new IllegalArgumentException("collection is empty");
+ }
+ if (numOfElements > collection.size()) {
+ throw new IllegalArgumentException("numOfElements exceeds collection.size()");
+ }
+
+ List<T> remainingElements = new ArrayList<>(collection);
+ List<T> pickedElements = new ArrayList<>();
+ for (int i = 0; i < numOfElements; i++) {
+ T element = pickValue(remainingElements);
+ pickedElements.add(element);
+ remainingElements.remove(element);
+ }
+ return pickedElements;
+ }
+
+ /**
+ * Picks {@code numOfElements} elements from {@code array} based on the fuzzer input.
+ * <p><b>Note:</b> The distribution of picks is not perfectly uniform.
+ *
+ * @param array the array to pick an element from.
+ * @param numOfElements the number of elements to pick.
+ * @param <T> the type of the array element
+ * @return an array of size {@code numOfElements} from {@code array} chosen based on the fuzzer
+ * input
+ */
+ default<T> List<T> pickValues(T[] array, int numOfElements) {
+ return pickValues(Arrays.asList(array), numOfElements);
+ }
+}