diff --git a/.bazelrc b/.bazelrc index d07e43ac9..4683cc01e 100644 --- a/.bazelrc +++ b/.bazelrc @@ -26,6 +26,8 @@ build --features=layering_check build:macos --apple_crosstool_top=@local_config_apple_cc//:toolchain build:macos --crosstool_top=@local_config_apple_cc//:toolchain build:macos --host_crosstool_top=@local_config_apple_cc//:toolchain +build:macos --cxxopt=-std=c++17 +build:macos --host_cxxopt=-std=c++17 # Java # Always build for Java 8, even with a newer JDK. This ensures that all artifacts we release are @@ -64,6 +66,8 @@ build --android_platforms=//:android_arm64 build:windows --extra_toolchains=@local_config_cc//:cc-toolchain-x64_windows-clang-cl build:windows --extra_execution_platforms=//bazel/platforms:x64_windows-clang-cl build:windows --features=static_link_msvcrt +build:windows --cxxopt=/std:c++17 +build:windows --host_cxxopt=/std:c++17 # Required as PATH doubles as the shared library search path on Windows and the # Java agent functionality depends on system-provided shared libraries. test:windows --noincompatible_strict_action_env diff --git a/MODULE.bazel b/MODULE.bazel index 062950ea9..7d25f1d63 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -6,15 +6,15 @@ module(name = "jazzer") # Kept up-to-date by Renovate ################################################################################ -bazel_dep(name = "abseil-cpp", version = "20230802.1") +bazel_dep(name = "abseil-cpp", version = "20250814.1") bazel_dep(name = "apple_support", version = "1.11.1") bazel_dep(name = "bazel_jar_jar", version = "0.1.0") bazel_dep(name = "bazel_skylib", version = "1.7.1") bazel_dep(name = "buildifier_prebuilt", version = "6.4.0") bazel_dep(name = "contrib_rules_jvm", version = "0.24.0") -bazel_dep(name = "googletest", version = "1.14.0.bcr.1") +bazel_dep(name = "googletest", version = "1.17.0.bcr.1") bazel_dep(name = "platforms", version = "0.0.10") -bazel_dep(name = "protobuf") +bazel_dep(name = "protobuf", version = "32.1") bazel_dep(name = "rules_android", version = "0.1.1") bazel_dep(name = "rules_android_ndk", version = "0.1.2") bazel_dep(name = "rules_foreign_cc", version = "0.11.1") @@ -35,17 +35,6 @@ bazel_dep(name = "rules_license", version = "1.0.0") bazel_dep(name = "rules_pkg", version = "0.9.1") bazel_dep(name = "toolchains_llvm", version = "0.10.3") -# TODO: Remove after a release that includes https://github.com/protocolbuffers/protobuf/commit/a7b0421c78412baa48704d727601a17ac0f451d1. -single_version_override( - module_name = "protobuf", - patch_strip = 1, - patches = [ - # https://github.com/protocolbuffers/protobuf/pull/15332 - "//third_party:protobuf-disable-layering_check.patch", - ], - version = "23.1", -) - ################################################################################ # Maven dependencies ################################################################################ @@ -371,9 +360,9 @@ cc_library( visibility = ["//visibility:public"], ) """, - sha256 = "21bfdfef25554fa2e30aec2a9f9b58f4a17c1d8c8593763fa94a6dd74b226594", - strip_prefix = "libprotobuf-mutator-3b28530531b154a748fe9884bc9219b4966f0754", - urls = ["https://github.com/google/libprotobuf-mutator/archive/3b28530531b154a748fe9884bc9219b4966f0754.tar.gz"], + integrity = "sha256-iVlYiBtJk99wtPZSwtgsW9l9IvgByk9DDWVGgJ3yk9U=", + strip_prefix = "libprotobuf-mutator-1.5", + urls = ["https://github.com/google/libprotobuf-mutator/archive/refs/tags/v1.5.tar.gz"], ) ################################################################################ diff --git a/maven_install.json b/maven_install.json index 58d0858a5..f64d1aa3e 100755 --- a/maven_install.json +++ b/maven_install.json @@ -1,14 +1,11 @@ { "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL", - "__INPUT_ARTIFACTS_HASH": 285652305, - "__RESOLVED_ARTIFACTS_HASH": -2054117877, + "__INPUT_ARTIFACTS_HASH": -1379382746, + "__RESOLVED_ARTIFACTS_HASH": -930880548, "conflict_resolution": { "com.google.code.gson:gson:2.8.6": "com.google.code.gson:gson:2.8.9", - "com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.26.1", - "com.google.guava:guava:31.1-jre": "com.google.guava:guava:33.0.0-android", - "com.google.j2objc:j2objc-annotations:1.3": "com.google.j2objc:j2objc-annotations:2.8", - "com.google.truth:truth:1.1.2": "com.google.truth:truth:1.4.2", - "org.mockito:mockito-core:4.3.1": "org.mockito:mockito-core:5.11.0" + "com.google.errorprone:error_prone_annotations:2.5.1": "com.google.errorprone:error_prone_annotations:2.26.1", + "com.google.guava:guava:32.0.1-jre": "com.google.guava:guava:33.0.0-android" }, "artifacts": { "com.alibaba:fastjson": { @@ -101,12 +98,6 @@ }, "version": "33.0.0-android" }, - "com.google.guava:guava-testlib": { - "shasums": { - "jar": "aadc71b10d5c3ac474dd16be84cfb18d257e584d1e0a59f8cab64ef4376226ce" - }, - "version": "31.1-jre" - }, "com.google.guava:listenablefuture": { "shasums": { "jar": "b372a037d4230aa57fbeffdef30fd6123f9c0c2db85d0aced00c91b974f33f99" @@ -669,14 +660,6 @@ "com.google.j2objc:j2objc-annotations", "org.checkerframework:checker-qual" ], - "com.google.guava:guava-testlib": [ - "com.google.code.findbugs:jsr305", - "com.google.errorprone:error_prone_annotations", - "com.google.guava:guava", - "com.google.j2objc:j2objc-annotations", - "junit:junit", - "org.checkerframework:checker-qual" - ], "com.google.truth.extensions:truth-java8-extension": [ "com.google.truth:truth", "org.checkerframework:checker-qual" @@ -1123,15 +1106,6 @@ "com.google.common.xml", "com.google.thirdparty.publicsuffix" ], - "com.google.guava:guava-testlib": [ - "com.google.common.collect.testing", - "com.google.common.collect.testing.features", - "com.google.common.collect.testing.google", - "com.google.common.collect.testing.testers", - "com.google.common.escape.testing", - "com.google.common.testing", - "com.google.common.util.concurrent.testing" - ], "com.google.j2objc:j2objc-annotations": [ "com.google.j2objc.annotations" ], @@ -2595,7 +2569,6 @@ "com.google.errorprone:error_prone_type_annotations", "com.google.guava:failureaccess", "com.google.guava:guava", - "com.google.guava:guava-testlib", "com.google.guava:listenablefuture", "com.google.j2objc:j2objc-annotations", "com.google.protobuf:protobuf-java", diff --git a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/collection/BUILD.bazel b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/collection/BUILD.bazel index 523818b02..3b0e222d6 100644 --- a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/collection/BUILD.bazel +++ b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/collection/BUILD.bazel @@ -2,7 +2,7 @@ java_library( name = "collection", srcs = glob(["*.java"]), visibility = [ - "//src/main/java/com/code_intelligence/jazzer/mutation/mutator:__pkg__", + "//src/main/java/com/code_intelligence/jazzer/mutation/mutator:__subpackages__", "//src/test/java/com/code_intelligence/jazzer/mutation/mutator:__subpackages__", ], deps = [ diff --git a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/lang/BUILD.bazel b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/lang/BUILD.bazel index 31d5a7264..dd80c4fb8 100644 --- a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/lang/BUILD.bazel +++ b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/lang/BUILD.bazel @@ -2,7 +2,7 @@ java_library( name = "lang", srcs = glob(["*.java"]), visibility = [ - "//src/main/java/com/code_intelligence/jazzer/mutation/mutator:__pkg__", + "//src/main/java/com/code_intelligence/jazzer/mutation/mutator:__subpackages__", "//src/test/java/com/code_intelligence/jazzer/mutation/mutator:__subpackages__", ], deps = [ diff --git a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel index 0f4e5ef4a..1459f7b25 100644 --- a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel +++ b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel @@ -13,6 +13,8 @@ java_library( "//src/main/java/com/code_intelligence/jazzer/mutation/api", "//src/main/java/com/code_intelligence/jazzer/mutation/combinator", "//src/main/java/com/code_intelligence/jazzer/mutation/engine", + "//src/main/java/com/code_intelligence/jazzer/mutation/mutator/collection", + "//src/main/java/com/code_intelligence/jazzer/mutation/mutator/lang", "//src/main/java/com/code_intelligence/jazzer/mutation/support", "//src/main/java/com/code_intelligence/jazzer/mutation/utils", ], diff --git a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BuilderMutatorFactory.java b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BuilderMutatorFactory.java index 415166100..e1d4bae75 100644 --- a/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BuilderMutatorFactory.java +++ b/src/main/java/com/code_intelligence/jazzer/mutation/mutator/proto/BuilderMutatorFactory.java @@ -53,6 +53,8 @@ import com.code_intelligence.jazzer.mutation.api.SerializingInPlaceMutator; import com.code_intelligence.jazzer.mutation.api.SerializingMutator; import com.code_intelligence.jazzer.mutation.engine.ChainedMutatorFactory; +import com.code_intelligence.jazzer.mutation.mutator.collection.CollectionMutators; +import com.code_intelligence.jazzer.mutation.mutator.lang.LangMutators; import com.code_intelligence.jazzer.mutation.support.Preconditions; import com.google.protobuf.Any; import com.google.protobuf.Descriptors.Descriptor; @@ -140,31 +142,35 @@ private ExtendedMutatorFactory withDescriptorDependentMutatorFactoryIfNeeded( if (field.getJavaType() == JavaType.ENUM) { // Proto enum fields are special as their type (EnumValueDescriptor) does not encode their // domain - we need the actual EnumDescriptor instance. + MutatorFactory enumFactory = + (type, factory) -> + asSubclassOrEmpty(type, EnumValueDescriptor.class) + .map( + unused -> { + EnumDescriptor enumType = field.getEnumType(); + List values = enumType.getValues(); + String name = enumType.getName(); + if (values.size() == 1) { + // While we generally prefer to error out instead of creating a + // mutator that can't actually mutate its domain, we can't do that + // for proto enum fields as the user creating the fuzz test may not be + // in a position to modify the existing proto definition. + return fixedValue(values.get(0)); + } else { + return mutateThenMapToImmutable( + mutateIndices(values.size()), + values::get, + EnumValueDescriptor::getIndex, + unused2 -> "Enum<" + name + ">"); + } + }); + // Apart from the specific enum factory we need handling for `null` and other collection + // types. Note, that we don't include the full original factory here because we don't want + // to follow constructors or builders of the EnumValueDescriptor class. return ChainedMutatorFactory.of( - originalFactory.getCache(), - Stream.of( - originalFactory, - (type, factory) -> - asSubclassOrEmpty(type, EnumValueDescriptor.class) - .map( - unused -> { - EnumDescriptor enumType = field.getEnumType(); - List values = enumType.getValues(); - String name = enumType.getName(); - if (values.size() == 1) { - // While we generally prefer to error out instead of creating a - // mutator that can't actually mutate its domain, we can't do that for - // proto enum fields as the user creating the fuzz test may not be in - // a position to modify the existing proto definition. - return fixedValue(values.get(0)); - } else { - return mutateThenMapToImmutable( - mutateIndices(values.size()), - values::get, - EnumValueDescriptor::getIndex, - unused2 -> "Enum<" + name + ">"); - } - }))); + Stream.concat( + Stream.concat(LangMutators.newFactories(), CollectionMutators.newFactories()), + Stream.of(enumFactory))); } else if (field.getJavaType() == JavaType.MESSAGE) { Descriptor messageDescriptor; if (field.isMapField()) { diff --git a/src/test/java/com/code_intelligence/jazzer/mutation/ArgumentsMutatorTest.java b/src/test/java/com/code_intelligence/jazzer/mutation/ArgumentsMutatorTest.java index d2920de69..fe9cd895e 100644 --- a/src/test/java/com/code_intelligence/jazzer/mutation/ArgumentsMutatorTest.java +++ b/src/test/java/com/code_intelligence/jazzer/mutation/ArgumentsMutatorTest.java @@ -23,6 +23,8 @@ import com.code_intelligence.jazzer.mutation.annotation.NotNull; import com.code_intelligence.jazzer.mutation.mutator.Mutators; import com.code_intelligence.jazzer.mutation.support.TestSupport.MockPseudoRandom; +import com.code_intelligence.jazzer.protobuf.Proto2.TestProtobuf; +import com.google.protobuf.DescriptorProtos; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.lang.reflect.Method; @@ -347,4 +349,26 @@ void testReadEmptyBeanWithRuntimeError() throws NoSuchMethodException { // expected } } + + // Regression: ensure we can build an ArgumentsMutator for a fuzz target that + // takes a protobuf message and a protobuf descriptor as parameters. + @SuppressWarnings("unused") + public static void complexProtoFuzzTest( + @NotNull TestProtobuf proto, @NotNull DescriptorProtos.DescriptorProto descriptor) {} + + @Test + void testProtoAndDescriptorParameters() throws NoSuchMethodException { + Method method = + ArgumentsMutatorTest.class.getMethod( + "complexProtoFuzzTest", TestProtobuf.class, DescriptorProtos.DescriptorProto.class); + Optional maybeMutator = + ArgumentsMutator.forMethod(Mutators.newFactory(), method); + assertThat(maybeMutator).isPresent(); + // Ensure that the mutator debug string can be generated. This would fail with the error: + // Caused by: java.lang.NullPointerException: Cannot invoke + // + // "com.code_intelligence.jazzer.mutation.api.SerializingMutator.toDebugString(java.util.function.Predicate)" + // because "productMutator" is null + assertThat(maybeMutator.toString()).contains("-> Message"); + } } diff --git a/src/test/java/com/code_intelligence/jazzer/mutation/BUILD.bazel b/src/test/java/com/code_intelligence/jazzer/mutation/BUILD.bazel index 9d3975703..e8027069f 100644 --- a/src/test/java/com/code_intelligence/jazzer/mutation/BUILD.bazel +++ b/src/test/java/com/code_intelligence/jazzer/mutation/BUILD.bazel @@ -10,6 +10,8 @@ java_test_suite( "//src/main/java/com/code_intelligence/jazzer/mutation/annotation", "//src/main/java/com/code_intelligence/jazzer/mutation/api", "//src/main/java/com/code_intelligence/jazzer/mutation/mutator", + "//src/test/java/com/code_intelligence/jazzer/mutation/mutator/proto:proto2_java_proto", "//src/test/java/com/code_intelligence/jazzer/mutation/support:test_support", + "@protobuf//java/core", ], ) diff --git a/src/test/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel b/src/test/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel index 17081d854..69d243fba 100644 --- a/src/test/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel +++ b/src/test/java/com/code_intelligence/jazzer/mutation/mutator/proto/BUILD.bazel @@ -28,7 +28,7 @@ java_proto_library( testonly = True, visibility = [ "//selffuzz:__subpackages__", - "//src/test/java/com/code_intelligence/jazzer/mutation/mutator:__pkg__", + "//src/test/java/com/code_intelligence/jazzer/mutation:__subpackages__", "//tests:__pkg__", ], deps = [":proto2_proto"], diff --git a/third_party/protobuf-disable-layering_check.patch b/third_party/protobuf-disable-layering_check.patch deleted file mode 100644 index c16b44a34..000000000 --- a/third_party/protobuf-disable-layering_check.patch +++ /dev/null @@ -1,29 +0,0 @@ -From f4444a81218ede5eb58306bd57eaefb5d9ffd9e2 Mon Sep 17 00:00:00 2001 -From: Fabian Meumertzheim -Date: Mon, 8 Jan 2024 13:30:32 +0100 -Subject: [PATCH] Disable unsupported `layering_check` Bazel feature - -This allows downstream projects to use `layering_check` without having -to patch Protobuf to disable the feature for the repository. ---- - REPO.bazel | 11 +++++++++++ - 1 file changed, 11 insertions(+) - create mode 100644 REPO.bazel - -diff --git a/REPO.bazel b/REPO.bazel -new file mode 100644 -index 00000000000..a537ac745fa ---- /dev/null -+++ b/REPO.bazel -@@ -0,0 +1,11 @@ -+# This file is read by Bazel 7 and newer, both if Protobuf is the main -+# repository and if it is an external repository. -+repo( -+ features = [ -+ # Protobuf cc_* targets do not specify all dependencies from which they -+ # include headers. This causes builds of downstream projects with -+ # --feature=layering_check to fail, which can be avoided by disabling -+ # the feature for the entire repository. -+ "-layering_check", -+ ], -+)