aboutsummaryrefslogtreecommitdiff
path: root/examples/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'examples/src/main/java')
-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.java36
-rw-r--r--examples/src/main/java/com/example/ExampleOutOfMemoryFuzzer.java28
-rw-r--r--examples/src/main/java/com/example/ExamplePathTraversalFuzzer.java43
-rw-r--r--examples/src/main/java/com/example/ExamplePathTraversalFuzzerHooks.java46
-rw-r--r--examples/src/main/java/com/example/ExampleStackOverflowFuzzer.java33
-rw-r--r--examples/src/main/java/com/example/ExampleValueProfileFuzzer.java53
-rw-r--r--examples/src/main/java/com/example/FastJsonFuzzer.java30
-rw-r--r--examples/src/main/java/com/example/GifImageParserFuzzer.java32
-rw-r--r--examples/src/main/java/com/example/JacksonCborFuzzer.java34
-rw-r--r--examples/src/main/java/com/example/JpegImageParserFuzzer.java45
-rw-r--r--examples/src/main/java/com/example/JsonSanitizerCrashFuzzer.java30
-rw-r--r--examples/src/main/java/com/example/JsonSanitizerDenylistFuzzer.java45
-rw-r--r--examples/src/main/java/com/example/JsonSanitizerIdempotenceFuzzer.java34
-rw-r--r--examples/src/main/java/com/example/JsonSanitizerValidJsonFuzzer.java42
-rw-r--r--examples/src/main/java/com/example/KlaxonFuzzer.kt31
-rw-r--r--examples/src/main/java/com/example/Log4jFuzzer.java82
-rw-r--r--examples/src/main/java/com/example/TiffImageParserFuzzer.java31
-rw-r--r--examples/src/main/java/com/example/TurboJpegFuzzer.java59
20 files changed, 804 insertions, 0 deletions
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..073d924a
--- /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 com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium;
+import java.security.SecureRandom;
+
+public class ExampleFuzzer {
+ public static void fuzzerInitialize() {
+ // Optional initialization to be run before the first call to fuzzerTestOneInput.
+ }
+
+ public static void 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();
+ }
+ }
+
+ private static void mustNeverBeCalled() {
+ throw new FuzzerSecurityIssueMedium("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..b9a13e24
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleFuzzerWithNative.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.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.github.fmeum.rules_jni.RulesJni;
+
+public class ExampleFuzzerWithNative {
+ static {
+ String native_lib = System.getProperty("jazzer.native_lib");
+ RulesJni.loadLibrary(native_lib, ExampleFuzzerWithNative.class);
+ }
+
+ public static void 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);
+ }
+ }
+
+ private native boolean parse(String bytes);
+} \ No newline at end of file
diff --git a/examples/src/main/java/com/example/ExampleOutOfMemoryFuzzer.java b/examples/src/main/java/com/example/ExampleOutOfMemoryFuzzer.java
new file mode 100644
index 00000000..d704da39
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleOutOfMemoryFuzzer.java
@@ -0,0 +1,28 @@
+// 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.util.ArrayList;
+
+public class ExampleOutOfMemoryFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ ArrayList<Byte> bytes = new ArrayList<>();
+ int pos = 0;
+ while (pos >= 0 && pos < input.length) {
+ bytes.add(input[pos]);
+ pos += input[pos] + 1;
+ }
+ }
+}
diff --git a/examples/src/main/java/com/example/ExamplePathTraversalFuzzer.java b/examples/src/main/java/com/example/ExamplePathTraversalFuzzer.java
new file mode 100644
index 00000000..f53ccb3c
--- /dev/null
+++ b/examples/src/main/java/com/example/ExamplePathTraversalFuzzer.java
@@ -0,0 +1,43 @@
+// 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.io.File;
+import java.io.IOException;
+
+public class ExamplePathTraversalFuzzer {
+ /**
+ * The root path for all files that this application is allowed to upload.
+ */
+ public static final String publicFilesRootPath = "/app/upload/";
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String relativePath = data.consumeRemainingAsAsciiString();
+ // Upload the file and try very hard to ignore errors thrown during the upload.
+ try {
+ uploadFile(relativePath);
+ } catch (Throwable ignored) {
+ }
+ }
+
+ private static void uploadFile(String relativePathToFile) throws IOException {
+ File fileToUpload = new File(publicFilesRootPath + relativePathToFile);
+ if (!fileToUpload.exists()) {
+ throw new IOException("File not found");
+ }
+ // In a real application, the file would be uploaded to a public server here.
+ }
+}
diff --git a/examples/src/main/java/com/example/ExamplePathTraversalFuzzerHooks.java b/examples/src/main/java/com/example/ExamplePathTraversalFuzzerHooks.java
new file mode 100644
index 00000000..b027de5b
--- /dev/null
+++ b/examples/src/main/java/com/example/ExamplePathTraversalFuzzerHooks.java
@@ -0,0 +1,46 @@
+// 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.FuzzerSecurityIssueHigh;
+import com.code_intelligence.jazzer.api.HookType;
+import com.code_intelligence.jazzer.api.Jazzer;
+import com.code_intelligence.jazzer.api.MethodHook;
+import java.lang.invoke.MethodHandle;
+import java.nio.file.InvalidPathException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+public class ExamplePathTraversalFuzzerHooks {
+ @MethodHook(type = HookType.BEFORE, targetClassName = "java.io.File", targetMethod = "<init>",
+ targetMethodDescriptor = "(Ljava/lang/String;)V")
+ public static void
+ fileConstructorHook(MethodHandle handle, Object thisObject, Object[] args, int hookId) {
+ String path = (String) args[0];
+ Path normalizedPath;
+ try {
+ normalizedPath = Paths.get(path).normalize();
+ } catch (InvalidPathException e) {
+ // Invalid paths are correctly rejected by the application.
+ return;
+ }
+ if (!normalizedPath.startsWith(ExamplePathTraversalFuzzer.publicFilesRootPath)) {
+ // Simply throwing an exception from here would not work as the calling code catches and
+ // ignores all Throwables. Instead, use the Jazzer API to report a finding from a hook.
+ Jazzer.reportFindingFromHook(new FuzzerSecurityIssueHigh(
+ "Path traversal discovered: '" + path + "' --> '" + normalizedPath + "'"));
+ }
+ }
+}
diff --git a/examples/src/main/java/com/example/ExampleStackOverflowFuzzer.java b/examples/src/main/java/com/example/ExampleStackOverflowFuzzer.java
new file mode 100644
index 00000000..47166af4
--- /dev/null
+++ b/examples/src/main/java/com/example/ExampleStackOverflowFuzzer.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.math.BigDecimal;
+
+public class ExampleStackOverflowFuzzer {
+ public static void fuzzerTestOneInput(byte[] input) {
+ step1();
+ }
+
+ private static void step1() {
+ BigDecimal unused = BigDecimal.valueOf(10, 100);
+ step2();
+ }
+
+ private static void step2() {
+ boolean unused = "foobar".contains("bar");
+ step1();
+ }
+}
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..acc023a2
--- /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 com.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;
+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 void 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;
+ 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();
+ }
+ }
+ }
+ }
+
+ private static void mustNeverBeCalled() {
+ throw new FuzzerSecurityIssueLow("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..2e5d4797
--- /dev/null
+++ b/examples/src/main/java/com/example/FastJsonFuzzer.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.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 void fuzzerTestOneInput(FuzzedDataProvider data) {
+ try {
+ JSON.parse(data.consumeRemainingAsString());
+ } catch (JSONException ignored) {
+ }
+ }
+}
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..ab7de907
--- /dev/null
+++ b/examples/src/main/java/com/example/GifImageParserFuzzer.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 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 void fuzzerTestOneInput(byte[] input) {
+ try {
+ new GifImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
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..902c1d96
--- /dev/null
+++ b/examples/src/main/java/com/example/JacksonCborFuzzer.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 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 void fuzzerTestOneInput(byte[] input) {
+ CBORFactory factory = new CBORFactory();
+ ObjectMapper mapper = new ObjectMapper(factory);
+ mapper.enableDefaultTyping();
+ try {
+ mapper.readTree(input);
+ } catch (IOException ignored) {
+ }
+ }
+}
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..a6898bf0
--- /dev/null
+++ b/examples/src/main/java/com/example/JpegImageParserFuzzer.java
@@ -0,0 +1,45 @@
+// 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 void fuzzerInitialize() {
+ String foo = System.getProperty("foo");
+ String bar = System.getProperty("bar");
+ String baz = System.getProperty("baz");
+ // Only used to verify that arguments are correctly passed down to child processes.
+ if (foo == null || bar == null || baz == null || !foo.equals("foo")
+ || !(bar.equals("b;ar") || bar.equals("b:ar")) || !baz.equals("baz")) {
+ // Exit the process with an exit code different from that for a finding.
+ System.err.println("ERROR: Did not correctly pass all jvm_args to child process.");
+ System.err.printf("foo: %s%nbar: %s%nbaz: %s%n", foo, bar, baz);
+ System.exit(3);
+ }
+ }
+
+ public static void fuzzerTestOneInput(byte[] input) {
+ try {
+ new JpegImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
diff --git a/examples/src/main/java/com/example/JsonSanitizerCrashFuzzer.java b/examples/src/main/java/com/example/JsonSanitizerCrashFuzzer.java
new file mode 100644
index 00000000..05ac4611
--- /dev/null
+++ b/examples/src/main/java/com/example/JsonSanitizerCrashFuzzer.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.FuzzedDataProvider;
+import com.google.json.JsonSanitizer;
+
+public class JsonSanitizerCrashFuzzer {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ try {
+ JsonSanitizer.sanitize(input, 10);
+ } catch (ArrayIndexOutOfBoundsException ignored) {
+ // ArrayIndexOutOfBoundsException is expected if nesting depth is
+ // exceeded.
+ }
+ }
+}
diff --git a/examples/src/main/java/com/example/JsonSanitizerDenylistFuzzer.java b/examples/src/main/java/com/example/JsonSanitizerDenylistFuzzer.java
new file mode 100644
index 00000000..e715b1d9
--- /dev/null
+++ b/examples/src/main/java/com/example/JsonSanitizerDenylistFuzzer.java
@@ -0,0 +1,45 @@
+// 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.code_intelligence.jazzer.api.FuzzerSecurityIssueHigh;
+import com.code_intelligence.jazzer.api.FuzzerSecurityIssueMedium;
+import com.google.json.JsonSanitizer;
+
+public class JsonSanitizerDenylistFuzzer {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ String validJson;
+ try {
+ validJson = JsonSanitizer.sanitize(input, 10);
+ } catch (Exception e) {
+ return;
+ }
+
+ // Check for forbidden substrings. As these would enable Cross-Site Scripting, treat every
+ // finding as a high severity vulnerability.
+ assert !validJson.contains("</script")
+ : new FuzzerSecurityIssueHigh("Output contains </script");
+ assert !validJson.contains("]]>") : new FuzzerSecurityIssueHigh("Output contains ]]>");
+
+ // Check for more forbidden substrings. As these would not directly enable Cross-Site Scripting
+ // in general, but may impact script execution on the embedding page, treat each finding as a
+ // medium severity vulnerability.
+ assert !validJson.contains("<script")
+ : new FuzzerSecurityIssueMedium("Output contains <script");
+ assert !validJson.contains("<!--") : new FuzzerSecurityIssueMedium("Output contains <!--");
+ }
+}
diff --git a/examples/src/main/java/com/example/JsonSanitizerIdempotenceFuzzer.java b/examples/src/main/java/com/example/JsonSanitizerIdempotenceFuzzer.java
new file mode 100644
index 00000000..111d3de2
--- /dev/null
+++ b/examples/src/main/java/com/example/JsonSanitizerIdempotenceFuzzer.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 com.code_intelligence.jazzer.api.FuzzedDataProvider;
+import com.google.json.JsonSanitizer;
+
+public class JsonSanitizerIdempotenceFuzzer {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ String validJson;
+ try {
+ validJson = JsonSanitizer.sanitize(input, 10);
+ } catch (Exception e) {
+ return;
+ }
+
+ // Ensure that sanitizing twice does not give different output (idempotence). Since failure to
+ // be idempotent is not a security issue in itself, fail with a regular AssertionError.
+ assert JsonSanitizer.sanitize(validJson).equals(validJson) : "Not idempotent";
+ }
+}
diff --git a/examples/src/main/java/com/example/JsonSanitizerValidJsonFuzzer.java b/examples/src/main/java/com/example/JsonSanitizerValidJsonFuzzer.java
new file mode 100644
index 00000000..2d270966
--- /dev/null
+++ b/examples/src/main/java/com/example/JsonSanitizerValidJsonFuzzer.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.code_intelligence.jazzer.api.FuzzerSecurityIssueLow;
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.json.JsonSanitizer;
+
+public class JsonSanitizerValidJsonFuzzer {
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ String input = data.consumeRemainingAsString();
+ String validJson;
+ try {
+ validJson = JsonSanitizer.sanitize(input, 10);
+ } catch (Exception e) {
+ return;
+ }
+
+ // Check that the output is valid JSON. Invalid JSON may crash other parts of the application
+ // that trust the output of the sanitizer.
+ try {
+ Gson gson = new Gson();
+ gson.fromJson(validJson, JsonElement.class);
+ } catch (Exception e) {
+ throw new FuzzerSecurityIssueLow("Output is invalid JSON", e);
+ }
+ }
+}
diff --git a/examples/src/main/java/com/example/KlaxonFuzzer.kt b/examples/src/main/java/com/example/KlaxonFuzzer.kt
new file mode 100644
index 00000000..39216eea
--- /dev/null
+++ b/examples/src/main/java/com/example/KlaxonFuzzer.kt
@@ -0,0 +1,31 @@
+// 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.beust.klaxon.KlaxonException
+import com.beust.klaxon.Parser
+import com.code_intelligence.jazzer.api.FuzzedDataProvider
+
+// Reproduces https://github.com/cbeust/klaxon/pull/330
+object KlaxonFuzzer {
+
+ @JvmStatic
+ fun fuzzerTestOneInput(data: FuzzedDataProvider) {
+ try {
+ Parser.default().parse(StringBuilder(data.consumeRemainingAsString()))
+ } catch (_: KlaxonException) {
+ }
+ }
+}
diff --git a/examples/src/main/java/com/example/Log4jFuzzer.java b/examples/src/main/java/com/example/Log4jFuzzer.java
new file mode 100644
index 00000000..41870c9c
--- /dev/null
+++ b/examples/src/main/java/com/example/Log4jFuzzer.java
@@ -0,0 +1,82 @@
+// 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.apache.logging.log4j.Level;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+import org.apache.logging.log4j.core.Appender;
+import org.apache.logging.log4j.core.Core;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.appender.AbstractAppender;
+import org.apache.logging.log4j.core.config.Configurator;
+import org.apache.logging.log4j.core.config.builder.api.AppenderComponentBuilder;
+import org.apache.logging.log4j.core.config.builder.api.RootLoggerComponentBuilder;
+import org.apache.logging.log4j.core.config.builder.impl.DefaultConfigurationBuilder;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
+import org.apache.logging.log4j.core.config.plugins.PluginFactory;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.status.StatusLogger;
+
+// This fuzzer reproduces the log4j RCE vulnerability CVE-2021-44228.
+public class Log4jFuzzer {
+ private final static Logger log = LogManager.getLogger(Log4jFuzzer.class.getName());
+
+ public static void fuzzerTestOneInput(FuzzedDataProvider data) {
+ log.error(data.consumeRemainingAsString());
+ }
+
+ public static void fuzzerInitialize() {
+ // Install a logger that constructs the log message, but never prints it.
+ // This noticeably increases the fuzzing performance
+ DefaultConfigurationBuilder configBuilder = new DefaultConfigurationBuilder();
+ configBuilder.setPackages(FuzzingAppender.class.getPackage().getName());
+ AppenderComponentBuilder fuzzingAppender =
+ configBuilder.newAppender("nullAppender", "FuzzingAppender");
+ configBuilder.add(fuzzingAppender);
+ RootLoggerComponentBuilder rootLogger = configBuilder.newRootLogger();
+ rootLogger.add(configBuilder.newAppenderRef("nullAppender"));
+ configBuilder.add(rootLogger);
+ Configurator.reconfigure(configBuilder.build());
+
+ // Disable logging of exceptions caught in log4j itself.
+ StatusLogger.getLogger().reset();
+ StatusLogger.getLogger().setLevel(Level.OFF);
+ }
+
+ @Plugin(
+ name = "FuzzingAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
+ public static class FuzzingAppender extends AbstractAppender {
+ protected FuzzingAppender(String name) {
+ super(name, null, PatternLayout.createDefaultLayout(), true);
+ }
+
+ @PluginFactory
+ public static FuzzingAppender createAppender(@PluginAttribute("name") String name) {
+ return new FuzzingAppender(name);
+ }
+
+ @Override
+ public void append(LogEvent event) {
+ try {
+ getLayout().toByteArray(event);
+ } catch (Exception ignored) {
+ // Prevent exceptions from being logged to stderr.
+ }
+ }
+ }
+}
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..5fa1af2d
--- /dev/null
+++ b/examples/src/main/java/com/example/TiffImageParserFuzzer.java
@@ -0,0 +1,31 @@
+// 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 void fuzzerTestOneInput(byte[] input) {
+ try {
+ new TiffImageParser().getBufferedImage(new ByteSourceArray(input), new HashMap<>());
+ } catch (IOException | ImageReadException ignored) {
+ }
+ }
+}
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..b9ea715b
--- /dev/null
+++ b/examples/src/main/java/com/example/TurboJpegFuzzer.java
@@ -0,0 +1,59 @@
+// 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 void 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 ignored) {
+ // We are not looking for Java exceptions, but segfaults and ASan reports.
+ }
+ }
+}