SERVER-109955 Fuzztest support and libfuzzer depreciation (#46638)

GitOrigin-RevId: 0b7dbc51c35fde2f50d80ec68a184678165896c0
This commit is contained in:
Mike Merrill 2026-02-20 10:48:46 -05:00 committed by MongoDB Bot
parent 72933b606e
commit 5b9acb40b4
16 changed files with 100 additions and 88 deletions

View File

@ -598,6 +598,7 @@ common:fission --fission=yes
common:fission --remote_download_regex=.*\.dwo$
--config=fuzztest
common:fuzztest --no@fuzztest//fuzztest:use_riegeli
common:fuzztest --@fuzztest//fuzztest:centipede_integration=True
# Avoid failing builds when BES metadata fails to upload.

View File

@ -1376,47 +1376,62 @@ def mongo_cc_integration_test(
**kwargs
)
def mongo_cc_fuzzer_test(
name,
srcs = [],
def mongo_cc_fuzzer_test_deprecated(
deps = [],
private_hdrs = [],
visibility = None,
data = [],
tags = [],
copts = [],
linkopts = [],
includes = [],
linkstatic = False,
local_defines = [],
target_compatible_with = [],
defines = [],
additional_linker_inputs = [],
features = [],
exec_properties = {},
provides_main = False,
**kwargs):
"""Deprecated: Wrapper around mongo_cc_test supporting old libfuzzer based tests.
Implements the libfuzzer API with fuzztest and centipede as the fuzzing engine.
Should not be used for new tests. See mongo_cc_fuzztest.
"""
mongo_cc_test(
name = name,
srcs = srcs,
deps = deps,
private_hdrs = private_hdrs,
visibility = visibility,
data = data,
deps = deps + [
"@fuzztest//centipede:centipede_runner_no_main",
"@fuzztest//fuzztest:llvm_fuzzer_main",
"@fuzztest//fuzztest:llvm_fuzzer_wrapper",
],
tags = tags + ["mongo_fuzzer_test"],
copts = copts,
linkopts = linkopts + ["-fsanitize=fuzzer"],
includes = includes,
linkstatic = linkstatic,
local_defines = local_defines,
copts = copts + ["-Wno-sign-compare"],
linkopts = linkopts + ["-fsanitize-coverage=control-flow"],
target_compatible_with = target_compatible_with + select({
"//bazel/config:fsan_enabled": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
**kwargs
)
def mongo_cc_fuzztest(
deps = [],
tags = [],
linkopts = [],
target_compatible_with = [],
copts = [],
**kwargs):
"""Wrapper around mongo_cc_test for Fuzztest based fuzzers.
Creates a binary that uses fuzztest and centipede as the fuzzing engine.
Compatible with resmoke's CPPLibfuzzerTestCase.
Additional information about fuzztest can be found at:
https://github.com/google/fuzztest
"""
mongo_cc_test(
deps = deps + [
"@fuzztest//fuzztest",
"@fuzztest//fuzztest:fuzztest_gtest_main",
"@com_google_googletest//:gtest",
"@fuzztest//centipede:centipede_runner_no_main",
],
tags = tags + ["mongo_fuzzer_test"],
copts = copts + ["-Wno-sign-compare"],
linkopts = linkopts + ["-fsanitize-coverage=control-flow"],
target_compatible_with = target_compatible_with + select({
"//bazel/config:fsan_enabled": [],
"//conditions:default": ["@platforms//:incompatible"],
}),
defines = defines,
additional_linker_inputs = additional_linker_inputs,
features = features,
exec_properties = exec_properties,
**kwargs
)

View File

@ -1,8 +1,5 @@
"""Test hook that does maintainence tasks for libfuzzer tests."""
import os
from buildscripts.resmokelib import core
from buildscripts.resmokelib.testing.hooks import interface
@ -38,22 +35,4 @@ class LibfuzzerHook(interface.Hook):
def after_test(self, test, test_report):
"""After test."""
self._merge_corpus(test)
def _merge_corpus(self, test):
self.logger.info(
f"Merge for {test.short_name()} libfuzzer test started, "
f"merging to {test.merged_corpus_directory}."
)
os.makedirs(test.merged_corpus_directory, exist_ok=True)
default_args = [
test.program_executable,
"-merge=1",
test.merged_corpus_directory,
test.corpus_directory,
"-artifact-prefix=./out/fuzzer-",
]
process = core.programs.make_process(self.logger, default_args, **test.program_options)
process.start()
process.wait()
self.logger.info(f"Merge for {test.short_name()} libfuzzer test finished.")
pass # this will eventually be used to generate code coverage

View File

@ -19,7 +19,6 @@ class CPPLibfuzzerTestCase(interface.ProcessTestCase):
logger: logging.Logger,
program_executables: list[str],
program_options: Optional[dict] = None,
runs: int = 1000000,
corpus_directory_stem="corpora",
):
"""Initialize the CPPLibfuzzerTestCase with the executable to run."""
@ -32,10 +31,22 @@ class CPPLibfuzzerTestCase(interface.ProcessTestCase):
self.program_executable = program_executables[0]
self.program_options = utils.default_if_none(program_options, {}).copy()
self.runs = runs
# disable writing of profraw during fuzzing unless specifically asked for
self.program_options.setdefault("env_vars", {})
self.program_options["env_vars"].setdefault("LLVM_PROFILE_FILE", "/dev/null")
self.corpus_directory = f"{corpus_directory_stem}/corpus-{self.short_name()}"
self.merged_corpus_directory = f"{corpus_directory_stem}-merged/corpus-{self.short_name()}"
self.corpus_directory = corpus_directory_stem
self.seed_directory = os.path.join(
self.corpus_directory, self.short_name(), "LLVMFuzzer.TestOneInput", "seeds"
)
old_corpus_dir = f"{corpus_directory_stem}/corpus-{self.short_name()}"
if os.path.exists(old_corpus_dir):
os.makedirs(self.seed_directory, exist_ok=True)
os.rename(old_corpus_dir, self.seed_directory)
if not os.path.exists(self.seed_directory):
self.seed_directory = ""
os.makedirs(self.corpus_directory, exist_ok=True)
@ -44,10 +55,8 @@ class CPPLibfuzzerTestCase(interface.ProcessTestCase):
def _make_process(self):
default_args = [
self.program_executable,
"-max_len=100000",
"-rss_limit_mb=5000",
"-max_total_time=3600", # 1 hour is the maximum amount of time to allow a fuzzer to run
f"-runs={self.runs}",
self.corpus_directory,
"--fuzz_for=1h",
f"--corpus_database={self.corpus_directory}",
f"--llvm_fuzzer_wrapper_corpus_dir={self.seed_directory}",
]
return core.programs.make_process(self.logger, default_args, **self.program_options)

View File

@ -513,7 +513,7 @@ functions:
display_name: "archive new corpus"
params:
target: corpora.tgz
source_dir: src/corpora-merged
source_dir: src/corpora
include:
- "**"

View File

@ -498,6 +498,8 @@ tasks:
bazel_args: >-
--config=evg
--include_autogenerated_targets=True
--config=fuzztest
--compiler_type=clang
# Store the fuzzer executable, which we use to generate and run fuzzer inputs.
- command: s3.put
params:

View File

@ -564,6 +564,7 @@ buildvariants:
san_options: *aubsan_options
bazel_compile_flags: >-
--config=dbg_aubsan
--linkstatic=True
--opt=on
--fission=no
--fsan=True

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_benchmark", "mongo_cc_fuzzer_test", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_benchmark", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -71,7 +71,7 @@ mongo_cc_integration_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "bson_validate_fuzzer",
srcs = [
"bson_validate_fuzzer.cpp",
@ -83,7 +83,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "fromjson_fuzzer",
srcs = [
"fromjson_fuzzer.cpp",

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "mongo_cc_benchmark", "mongo_cc_binary", "mongo_cc_fuzzer_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "mongo_cc_benchmark", "mongo_cc_binary", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -130,7 +130,7 @@ mongo_cc_benchmark(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "simple8b_fuzzer",
srcs = [
"simple8b_fuzzer.cpp",
@ -141,7 +141,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "bson_column_validate_fuzzer",
srcs = [
"bson_column_validate_fuzzer.cpp",
@ -153,7 +153,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "bsoncolumn_decompress_fuzzer",
srcs = [
"bsoncolumn_decompress_fuzzer.cpp",
@ -165,7 +165,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "bsoncolumn_builder_fuzzer",
srcs = [
"bsoncolumn_builder_fuzzer.cpp",
@ -178,7 +178,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "bsoncolumn_decompress_paths_fuzzer",
srcs = [
"bsoncolumn_decompress_paths_fuzzer.cpp",
@ -192,7 +192,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "bsoncolumnbuilder_reopen_fuzzer",
srcs = [
"bsoncolumnbuilder_reopen_fuzzer.cpp",

View File

@ -1,5 +1,5 @@
load("@poetry//:dependencies.bzl", "dependency")
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_benchmark", "mongo_cc_binary", "mongo_cc_fuzzer_test", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test", "mongo_idl_library", "windows_rc")
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_benchmark", "mongo_cc_binary", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test", "mongo_idl_library", "windows_rc")
load("//bazel/config:render_template.bzl", "render_template")
package(default_visibility = ["//visibility:public"])
@ -3484,7 +3484,7 @@ mongo_cc_library(
deps = ["//src/mongo:base"],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "op_msg_fuzzer_shard",
srcs = [
"op_msg_fuzzer_shard.cpp",
@ -3495,7 +3495,7 @@ mongo_cc_fuzzer_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "op_msg_fuzzer_router",
srcs = [
"op_msg_fuzzer_router.cpp",

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_benchmark", "mongo_cc_fuzzer_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_benchmark", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -276,13 +276,14 @@ mongo_cc_library(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "convert_string_to_object_fuzzer",
srcs = [
"//src/mongo/db/exec:convert_string_to_object_fuzzer.cpp",
],
deps = [
":convert_utils",
"//src/mongo/db/shard_role/lock_manager",
"//src/mongo/transport:transport_layer_common",
],
)

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "mongo_cc_fuzzer_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -45,7 +45,7 @@ mongo_cc_unit_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "date_time_support_fuzzer",
srcs = [
"date_time_support_fuzzer.cpp",

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "mongo_cc_benchmark", "mongo_cc_binary", "mongo_cc_fuzzer_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "mongo_cc_benchmark", "mongo_cc_binary", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -84,7 +84,7 @@ mongo_cc_binary(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "key_string_to_bson_fuzzer",
srcs = [
"key_string_to_bson_fuzzer.cpp",

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_fuzzer_test", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_fuzzer_test_deprecated", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -267,7 +267,7 @@ filegroup(
srcs = [":op_msg.h"],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzzer_test_deprecated(
name = "protocol_fuzzer",
srcs = [
"protocol_fuzzer.cpp",

View File

@ -1,4 +1,4 @@
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_fuzzer_test", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test")
load("//bazel:mongo_src_rules.bzl", "idl_generator", "mongo_cc_fuzztest", "mongo_cc_integration_test", "mongo_cc_library", "mongo_cc_unit_test")
package(default_visibility = ["//visibility:public"])
@ -412,7 +412,7 @@ mongo_cc_unit_test(
],
)
mongo_cc_fuzzer_test(
mongo_cc_fuzztest(
name = "asn1_parser_fuzzer",
srcs = [
"asn1_parser_fuzzer.cpp",

View File

@ -26,12 +26,16 @@
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#include "mongo/base/data_range.h"
#include "mongo/util/net/ssl_manager.h"
extern "C" int LLVMFuzzerTestOneInput(const char* Data, size_t Size) {
mongo::ConstDataRange dr = mongo::ConstDataRange(Data, Size);
#include <vector>
#include "fuzztest/fuzztest.h"
#include "gtest/gtest.h"
void PeerRoleParse(std::vector<char> Data) {
mongo::ConstDataRange dr = mongo::ConstDataRange(Data);
auto ret = mongo::parsePeerRoles(dr);
return 0;
}
FUZZ_TEST(ASN1FuzzSuite, PeerRoleParse);