aboutsummaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorFabian Meumertzheim <meumertzheim@code-intelligence.com>2021-01-29 16:20:19 +0100
committerFabian Meumertzheim <meumertzheim@code-intelligence.com>2021-02-09 17:20:51 +0100
commit5246e52be3bf4427791000355cbef86626b43eca (patch)
treee0683ad15664f2c3deecf3a6ce8c56f2a9597d85 /examples
downloadjazzer-api-5246e52be3bf4427791000355cbef86626b43eca.tar.gz
Initial commit
Diffstat (limited to 'examples')
-rw-r--r--examples/BUILD.bazel149
-rw-r--r--examples/src/main/java/com/example/ExampleFuzzer.java40
-rw-r--r--examples/src/main/java/com/example/ExampleFuzzerHooks.java30
-rw-r--r--examples/src/main/java/com/example/ExampleFuzzerWithNative.java35
-rw-r--r--examples/src/main/java/com/example/ExampleValueProfileFuzzer.java53
-rw-r--r--examples/src/main/java/com/example/FastJsonFuzzer.java32
-rw-r--r--examples/src/main/java/com/example/GifImageParserFuzzer.java34
-rw-r--r--examples/src/main/java/com/example/JacksonCborFuzzer.java36
-rw-r--r--examples/src/main/java/com/example/JpegImageParserFuzzer.java33
-rw-r--r--examples/src/main/java/com/example/JsonSanitizerFuzzer.java42
-rw-r--r--examples/src/main/java/com/example/TiffImageParserFuzzer.java33
-rw-r--r--examples/src/main/java/com/example/TurboJpegFuzzer.java61
-rw-r--r--examples/src/main/native/BUILD.bazel20
-rw-r--r--examples/src/main/native/com_example_ExampleFuzzerWithNative.cpp36
-rw-r--r--examples/src/main/native/com_example_ExampleFuzzerWithNative.h37
15 files changed, 671 insertions, 0 deletions
diff --git a/examples/BUILD.bazel b/examples/BUILD.bazel
new file mode 100644
index 00000000..d417e352
--- /dev/null
+++ b/examples/BUILD.bazel
@@ -0,0 +1,149 @@
+load("//bazel:fuzz_target.bzl", "java_fuzz_target_test")
+
+java_fuzz_target_test(
+ name = "ExampleFuzzer",
+ srcs = [
+ "src/main/java/com/example/ExampleFuzzer.java",
+ "src/main/java/com/example/ExampleFuzzerHooks.java",
+ ],
+ # Comment out the next line to keep the fuzzer running indefinitely.
+ hook_classes = ["com.example.ExampleFuzzerHooks"],
+ target_class = "com.example.ExampleFuzzer",
+ deps = [
+ "//agent/src/main/java/com/code_intelligence/jazzer/api",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "ExampleFuzzerWithNative",
+ srcs = [
+ "src/main/java/com/example/ExampleFuzzerWithNative.java",
+ ],
+ native_libs = ["//examples/src/main/native"],
+ target_class = "com.example.ExampleFuzzerWithNative",
+ use_asan = True,
+ deps = [
+ "//agent:jazzer_api_deploy.jar",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "ExampleValueProfileFuzzer",
+ srcs = [
+ "src/main/java/com/example/ExampleValueProfileFuzzer.java",
+ ],
+ # Comment out the next line to keep the fuzzer running indefinitely.
+ fuzzer_args = ["-use_value_profile=1"],
+ target_class = "com.example.ExampleValueProfileFuzzer",
+ deps = [
+ "//agent/src/main/java/com/code_intelligence/jazzer/api",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "JpegImageParserFuzzer",
+ srcs = [
+ "src/main/java/com/example/JpegImageParserFuzzer.java",
+ ],
+ target_class = "com.example.JpegImageParserFuzzer",
+ deps = [
+ "@maven//:org_apache_commons_commons_imaging",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "GifImageParserFuzzer",
+ srcs = [
+ "src/main/java/com/example/GifImageParserFuzzer.java",
+ ],
+ target_class = "com.example.GifImageParserFuzzer",
+ deps = [
+ "@maven//:org_apache_commons_commons_imaging",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "TiffImageParserFuzzer",
+ srcs = [
+ "src/main/java/com/example/TiffImageParserFuzzer.java",
+ ],
+ tags = ["manual"],
+ target_class = "com.example.TiffImageParserFuzzer",
+ deps = [
+ "@maven//:org_apache_commons_commons_imaging",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "JsonSanitizerFuzzer",
+ srcs = [
+ "src/main/java/com/example/JsonSanitizerFuzzer.java",
+ ],
+ target_class = "com.example.JsonSanitizerFuzzer",
+ deps = [
+ "//agent/src/main/java/com/code_intelligence/jazzer/api",
+ "@maven//:com_google_code_gson_gson",
+ "@maven//:com_mikesamuel_json_sanitizer",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "JacksonCborFuzzer",
+ srcs = [
+ "src/main/java/com/example/JacksonCborFuzzer.java",
+ ],
+ target_class = "com.example.JacksonCborFuzzer",
+ deps = [
+ "@maven//:com_fasterxml_jackson_core_jackson_core",
+ "@maven//:com_fasterxml_jackson_core_jackson_databind",
+ "@maven//:com_fasterxml_jackson_dataformat_jackson_dataformat_cbor",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "FastJsonFuzzer",
+ srcs = [
+ "src/main/java/com/example/FastJsonFuzzer.java",
+ ],
+ target_class = "com.example.FastJsonFuzzer",
+ deps = [
+ "//agent/src/main/java/com/code_intelligence/jazzer/api",
+ "@maven//:com_alibaba_fastjson",
+ ],
+)
+
+java_fuzz_target_test(
+ name = "TurboJpegFuzzer",
+ srcs = [
+ "src/main/java/com/example/TurboJpegFuzzer.java",
+ ],
+ fuzzer_args = [
+ "-rss_limit_mb=8196",
+ ],
+ native_libs = [
+ "@libjpeg_turbo//:turbojpeg_native",
+ ],
+ tags = ["manual"],
+ target_class = "com.example.TurboJpegFuzzer",
+ use_asan = True,
+ deps = [
+ "//agent/src/main/java/com/code_intelligence/jazzer/api",
+ "@libjpeg_turbo//:turbojpeg_java",
+ ],
+)
+
+java_binary(
+ name = "examples",
+ create_executable = False,
+ resource_jars = [
+ ":ExampleFuzzer_target_deploy.jar",
+ ":ExampleValueProfileFuzzer_target_deploy.jar",
+ ":FastJsonFuzzer_target_deploy.jar",
+ ":GifImageParserFuzzer_target_deploy.jar",
+ ":JacksonCborFuzzer_target_deploy.jar",
+ ":JpegImageParserFuzzer_target_deploy.jar",
+ ":JsonSanitizerFuzzer_target_deploy.jar",
+ ":TiffImageParserFuzzer_target_deploy.jar",
+ ],
+ visibility = ["//visibility:public"],
+)
diff --git a/examples/src/main/java/com/example/ExampleFuzzer.java b/examples/src/main/java/com/example/ExampleFuzzer.java
new file mode 100644
index 00000000..40dcb697
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleFuzzer.java
@@ -0,0 +1,40 @@
+// 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.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.security.SecureRandom;
+
+public class ExampleFuzzer {
+ public static void fuzzerInitialize() {
+ // Optional initialization to be run before the first call to fuzzerTestOneInput.
+ }
+
+ public static boolean fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ // Without the hook in ExampleFuzzerHooks.java, the value of random would change on every
+ // invocation, making it almost impossible to guess for the fuzzer.
+ long random = new SecureRandom().nextLong();
+ if (input.startsWith("magicstring" + random) && input.length() > 30
+ && input.charAt(25) == 'C') {
+ mustNeverBeCalled();
+ }
+ return false;
+ }
+
+ private static void mustNeverBeCalled() {
+ throw new IllegalStateException("mustNeverBeCalled has been called");
+ }
+}
diff --git a/examples/src/main/java/com/example/ExampleFuzzerHooks.java b/examples/src/main/java/com/example/ExampleFuzzerHooks.java
new file mode 100644
index 00000000..41f16635
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleFuzzerHooks.java
@@ -0,0 +1,30 @@
+// 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.example;
+
+import com.code_intelligence.jazzer.api.HookType;
+import com.code_intelligence.jazzer.api.MethodHook;
+import java.lang.invoke.MethodHandle;
+
+public class ExampleFuzzerHooks {
+ @MethodHook(type = HookType.REPLACE, targetClassName = "java.security.SecureRandom",
+ targetMethod = "nextLong", targetMethodDescriptor = "()J")
+ public static long
+ getRandomNumber(MethodHandle handle, Object thisObject, Object[] args, int hookId) {
+ return 4; // chosen by fair dice roll.
+ // guaranteed to be random.
+ // https://xkcd.com/221/
+ }
+}
diff --git a/examples/src/main/java/com/example/ExampleFuzzerWithNative.java b/examples/src/main/java/com/example/ExampleFuzzerWithNative.java
new file mode 100644
index 00000000..801e84ea
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleFuzzerWithNative.java
@@ -0,0 +1,35 @@
+// 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.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+public class ExampleFuzzerWithNative {
+ static {
+ System.loadLibrary("native");
+ }
+
+ public static boolean fuzzerTestOneInput(FuzzedDataProvider data) {
+ int val = data.consumeInt();
+ String stringData = data.consumeRemainingAsString();
+ if (val == 17759716 && stringData.length() > 10 && stringData.contains("jazzer")) {
+ // call native function which contains a crash
+ new ExampleFuzzerWithNative().parse(stringData);
+ }
+ return false;
+ }
+
+ private native boolean parse(String bytes);
+} \ No newline at end of file
diff --git a/examples/src/main/java/com/example/ExampleValueProfileFuzzer.java b/examples/src/main/java/com/example/ExampleValueProfileFuzzer.java
new file mode 100644
index 00000000..1eb55df0
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleValueProfileFuzzer.java
@@ -0,0 +1,53 @@
+// 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.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import java.util.Base64;
+
+public class ExampleValueProfileFuzzer {
+ private static String base64(byte[] input) {
+ return Base64.getEncoder().encodeToString(input);
+ }
+
+ private static long insecureEncrypt(long input) {
+ long key = 0xefe4eb93215cb6b0L;
+ return input ^ key;
+ }
+
+ public static boolean fuzzerTestOneInput(FuzzedDataProvider data) {
+ // Without -use_value_profile=1, the fuzzer gets stuck here as there is no direct correspondence
+ // between the input bytes and the compared string. With value profile, the fuzzer can guess the
+ // expected input byte by byte, which takes linear rather than exponential time.
+ if (base64(data.consumeBytes(6)).equals("SmF6emVy")) {
+ long[] plaintextBlocks = data.consumeLongs(2);
+ if (plaintextBlocks.length != 2)
+ return false;
+ if (insecureEncrypt(plaintextBlocks[0]) == 0x9fc48ee64d3dc090L) {
+ // Without --fake_pcs (enabled by default with -use_value_profile=1), the fuzzer would get
+ // stuck here as the value profile information for long comparisons would not be able to
+ // distinguish between this comparison and the one above.
+ if (insecureEncrypt(plaintextBlocks[1]) == 0x888a82ff483ad9c2L) {
+ mustNeverBeCalled();
+ }
+ }
+ }
+ return false;
+ }
+
+ private static void mustNeverBeCalled() {
+ throw new IllegalStateException("mustNeverBeCalled has been called");
+ }
+}
diff --git a/examples/src/main/java/com/example/FastJsonFuzzer.java b/examples/src/main/java/com/example/FastJsonFuzzer.java
new file mode 100644
index 00000000..5c203ffb
--- /dev/null
+++ b/examples/src/main/java/com/example/FastJsonFuzzer.java
@@ -0,0 +1,32 @@
+// 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.example;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONException;
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+
+// Found the issues described in
+// https://github.com/alibaba/fastjson/issues/3631
+public class FastJsonFuzzer {
+ public static boolean fuzzerTestOneInput(FuzzedDataProvider data) {
+ try {
+ JSON.parse(data.consumeRemainingAsString());
+ } catch (JSONException e) {
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/java/com/example/GifImageParserFuzzer.java b/examples/src/main/java/com/example/GifImageParserFuzzer.java
new file mode 100644
index 00000000..276bdb84
--- /dev/null
+++ b/examples/src/main/java/com/example/GifImageParserFuzzer.java
@@ -0,0 +1,34 @@
+// 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.example;
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.gif.GifImageParser;
+
+// Found https://issues.apache.org/jira/browse/IMAGING-277 and
+// https://issues.apache.org/jira/browse/IMAGING-278.
+public class GifImageParserFuzzer {
+ public static boolean fuzzerTestOneInput(byte[] input) {
+ try {
+ new GifImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException e) {
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/java/com/example/JacksonCborFuzzer.java b/examples/src/main/java/com/example/JacksonCborFuzzer.java
new file mode 100644
index 00000000..3d847751
--- /dev/null
+++ b/examples/src/main/java/com/example/JacksonCborFuzzer.java
@@ -0,0 +1,36 @@
+// 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.example;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
+import java.io.IOException;
+
+// Reproduces https://github.com/FasterXML/jackson-dataformats-binary/issues/236 and
+// https://github.com/FasterXML/jackson-databind/pull/3032 if executed with
+// `--keep_going=3 -seed=2735196724`.
+public class JacksonCborFuzzer {
+ public static boolean fuzzerTestOneInput(byte[] input) {
+ CBORFactory factory = new CBORFactory();
+ ObjectMapper mapper = new ObjectMapper(factory);
+ mapper.enableDefaultTyping();
+ try {
+ mapper.readTree(input);
+ } catch (IOException e) {
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/java/com/example/JpegImageParserFuzzer.java b/examples/src/main/java/com/example/JpegImageParserFuzzer.java
new file mode 100644
index 00000000..4040daee
--- /dev/null
+++ b/examples/src/main/java/com/example/JpegImageParserFuzzer.java
@@ -0,0 +1,33 @@
+// 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.example;
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.jpeg.JpegImageParser;
+
+// Found https://issues.apache.org/jira/browse/IMAGING-275.
+public class JpegImageParserFuzzer {
+ public static boolean fuzzerTestOneInput(byte[] input) {
+ try {
+ new JpegImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException e) {
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/java/com/example/JsonSanitizerFuzzer.java b/examples/src/main/java/com/example/JsonSanitizerFuzzer.java
new file mode 100644
index 00000000..ef13f369
--- /dev/null
+++ b/examples/src/main/java/com/example/JsonSanitizerFuzzer.java
@@ -0,0 +1,42 @@
+// 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.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.json.JsonSanitizer;
+
+public class JsonSanitizerFuzzer {
+ public static boolean fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ String validJson;
+ try {
+ validJson = JsonSanitizer.sanitize(input, 60);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // ArrayIndexOutOfBoundsException is expected if nesting depth is
+ // exceeded.
+ return false;
+ }
+ Gson gson = new Gson();
+ gson.fromJson(validJson, JsonElement.class);
+ if (validJson.contains("</script>") || validJson.contains("<script")
+ || validJson.contains("<!--") || validJson.contains("]]>")) {
+ System.out.println(validJson);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/java/com/example/TiffImageParserFuzzer.java b/examples/src/main/java/com/example/TiffImageParserFuzzer.java
new file mode 100644
index 00000000..6dd127c2
--- /dev/null
+++ b/examples/src/main/java/com/example/TiffImageParserFuzzer.java
@@ -0,0 +1,33 @@
+// 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.example;
+
+import java.io.IOException;
+import java.util.HashMap;
+import org.apache.commons.imaging.ImageReadException;
+import org.apache.commons.imaging.common.bytesource.ByteSourceArray;
+import org.apache.commons.imaging.formats.tiff.TiffImageParser;
+
+// Found https://issues.apache.org/jira/browse/IMAGING-276.
+public class TiffImageParserFuzzer {
+ public static boolean fuzzerTestOneInput(byte[] input) {
+ try {
+ new TiffImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException e) {
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/java/com/example/TurboJpegFuzzer.java b/examples/src/main/java/com/example/TurboJpegFuzzer.java
new file mode 100644
index 00000000..0a0059e4
--- /dev/null
+++ b/examples/src/main/java/com/example/TurboJpegFuzzer.java
@@ -0,0 +1,61 @@
+// 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.example;
+
+import com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import org.libjpegturbo.turbojpeg.TJ;
+import org.libjpegturbo.turbojpeg.TJDecompressor;
+import org.libjpegturbo.turbojpeg.TJException;
+import org.libjpegturbo.turbojpeg.TJTransform;
+import org.libjpegturbo.turbojpeg.TJTransformer;
+
+public class TurboJpegFuzzer {
+ static byte[] buffer = new byte[128 * 128 * 4];
+
+ public static void fuzzerInitialize() throws TJException {
+ // Trigger an early load of the native library to show the coverage counters stats in libFuzzer.
+ new TJDecompressor();
+ }
+
+ public static boolean fuzzerTestOneInput(FuzzedDataProvider data) {
+ try {
+ int flagsDecompress = data.consumeInt();
+ int flagsTransform = data.consumeInt();
+ int pixelFormat = data.consumeInt(TJ.PF_RGB, TJ.PF_CMYK);
+ // Specify explicit small target width/height so that we can reuse a
+ // fixed-size buffer.
+ int desiredWidth = data.consumeInt(1, 128);
+ int desiredHeight = data.consumeInt(1, 128);
+ int transformOp = data.consumeInt(TJTransform.OP_NONE, TJTransform.OP_ROT270);
+ int transformOptions = data.consumeInt();
+ int transformWidth = data.consumeBoolean() ? 128 : 64;
+ int transformHeight = data.consumeBoolean() ? 128 : 64;
+ TJDecompressor tjd;
+ if (data.consumeBoolean()) {
+ TJTransformer tjt = new TJTransformer(data.consumeRemainingAsBytes());
+ TJTransform tjf = new TJTransform(
+ 0, 0, transformWidth, transformHeight, transformOp, transformOptions, null);
+ tjd = tjt.transform(new TJTransform[] {tjf}, flagsTransform)[0];
+ } else {
+ tjd = new TJDecompressor(data.consumeRemainingAsBytes());
+ }
+ tjd.decompress(buffer, 0, 0, desiredWidth, 0, desiredHeight, pixelFormat, flagsDecompress);
+ } catch (Exception e) {
+ // We are not looking for Java exceptions, but segfaults and ASan reports.
+ return false;
+ }
+ return false;
+ }
+}
diff --git a/examples/src/main/native/BUILD.bazel b/examples/src/main/native/BUILD.bazel
new file mode 100644
index 00000000..11a6a740
--- /dev/null
+++ b/examples/src/main/native/BUILD.bazel
@@ -0,0 +1,20 @@
+load("@rules_cc//cc:defs.bzl", "cc_binary")
+
+cc_binary(
+ name = "native",
+ srcs = [
+ "com_example_ExampleFuzzerWithNative.cpp",
+ "com_example_ExampleFuzzerWithNative.h",
+ ],
+ copts = [
+ "-fsanitize=fuzzer-no-link,address",
+ ],
+ linkopts = [
+ "-fsanitize=fuzzer-no-link,address",
+ ],
+ linkshared = True,
+ visibility = ["//examples:__pkg__"],
+ deps = [
+ "//third_party/jni:jni_headers_only",
+ ],
+)
diff --git a/examples/src/main/native/com_example_ExampleFuzzerWithNative.cpp b/examples/src/main/native/com_example_ExampleFuzzerWithNative.cpp
new file mode 100644
index 00000000..04329acc
--- /dev/null
+++ b/examples/src/main/native/com_example_ExampleFuzzerWithNative.cpp
@@ -0,0 +1,36 @@
+// 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.
+
+#include "com_example_ExampleFuzzerWithNative.h"
+
+#include <string>
+
+// simple function containing a crash that requires coverage and string compare
+// instrumentation for the fuzzer to find
+void parseInternal(const std::string &input) {
+ if (input[0] == 'a' && input[1] == 'b' && input[5] == 'c') {
+ if (input.find("secret_in_native_library") != std::string::npos) {
+ // BOOM
+ *(char *)1 = 2;
+ }
+ }
+}
+
+JNIEXPORT jboolean JNICALL Java_com_example_ExampleFuzzerWithNative_parse(
+ JNIEnv *env, jobject o, jstring bytes) {
+ const char *input(env->GetStringUTFChars(bytes, nullptr));
+ parseInternal(input);
+ env->ReleaseStringUTFChars(bytes, input);
+ return false;
+}
diff --git a/examples/src/main/native/com_example_ExampleFuzzerWithNative.h b/examples/src/main/native/com_example_ExampleFuzzerWithNative.h
new file mode 100644
index 00000000..2a7b2bed
--- /dev/null
+++ b/examples/src/main/native/com_example_ExampleFuzzerWithNative.h
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ */
+
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include "third_party/jni/jni.h"
+/* Header for class com_example_ExampleFuzzerWithNative */
+
+#ifndef _Included_com_example_ExampleFuzzerWithNative
+#define _Included_com_example_ExampleFuzzerWithNative
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: com_example_ExampleFuzzerWithNative
+ * Method: parse
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL
+Java_com_example_ExampleFuzzerWithNative_parse(JNIEnv *, jobject, jstring);
+
+#ifdef __cplusplus
+}
+#endif
+#endif