diff options
author | Fabian Meumertzheim <meumertzheim@code-intelligence.com> | 2021-01-29 16:20:19 +0100 |
---|---|---|
committer | Fabian Meumertzheim <meumertzheim@code-intelligence.com> | 2021-02-09 17:20:51 +0100 |
commit | 5246e52be3bf4427791000355cbef86626b43eca (patch) | |
tree | e0683ad15664f2c3deecf3a6ce8c56f2a9597d85 /examples | |
download | jazzer-api-5246e52be3bf4427791000355cbef86626b43eca.tar.gz |
Initial commit
Diffstat (limited to 'examples')
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 |