Coverage Report

Created: 2026-08-31 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl_fuzzer/proto_fuzzer/fuzzer_main.cc
Line
Count
Source
1
/*
2
 * Copyright (C) Max Dymond, <cmeister2@gmail.com>, et al.
3
 *
4
 * SPDX-License-Identifier: curl
5
 */
6
7
/// @file
8
/// @brief Shared libFuzzer entrypoint for the policy-split protobuf targets.
9
///        Wires each binary's LPM policy to ScenarioRunner::Run.
10
11
#include <curl/curl.h>
12
#include <libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h>
13
14
#include <csignal>
15
16
#include "curl_fuzzer.pb.h"
17
#include "proto_fuzzer/option_apply.h"
18
#include "proto_fuzzer/scenario_runner.h"
19
#include "proto_fuzzer/target_policy.h"
20
21
namespace {
22
23
#if defined(PROTO_FUZZER_TARGET_COMPATIBILITY)
24
// The original target deliberately has no policy. Its OSS-Fuzz corpus and
25
// regression testcases contain mixed schemes and timing controls whose exact
26
// semantics must remain stable across the target split.
27
#elif defined(PROTO_FUZZER_TARGET_FAST_HTTP)
28
constexpr proto_fuzzer::TargetPolicy kTargetPolicy = proto_fuzzer::TargetPolicy::kFastHttp;
29
#elif defined(PROTO_FUZZER_TARGET_DEEP_HTTP)
30
constexpr proto_fuzzer::TargetPolicy kTargetPolicy = proto_fuzzer::TargetPolicy::kDeepHttp;
31
#elif defined(PROTO_FUZZER_TARGET_FAST_HTTPS)
32
constexpr proto_fuzzer::TargetPolicy kTargetPolicy = proto_fuzzer::TargetPolicy::kFastHttps;
33
#elif defined(PROTO_FUZZER_TARGET_FAST_WEBSOCKET)
34
constexpr proto_fuzzer::TargetPolicy kTargetPolicy = proto_fuzzer::TargetPolicy::kFastWebSocket;
35
#elif defined(PROTO_FUZZER_TARGET_FAST_SECURE_WEBSOCKET)
36
constexpr proto_fuzzer::TargetPolicy kTargetPolicy = proto_fuzzer::TargetPolicy::kFastSecureWebSocket;
37
#elif defined(PROTO_FUZZER_TARGET_TIMING)
38
constexpr proto_fuzzer::TargetPolicy kTargetPolicy = proto_fuzzer::TargetPolicy::kTiming;
39
#else
40
#error "A proto fuzzer target policy must be selected"
41
#endif
42
43
// The fast HTTP binary trades the post-transfer getinfo/header probes for
44
// throughput. Every other compiled lane retains them, so the aggregate proto
45
// suite still covers those APIs without charging the hottest mutation loop.
46
#if defined(PROTO_FUZZER_TARGET_FAST_HTTP)
47
constexpr bool kProbeTransferResults = false;
48
#else
49
constexpr bool kProbeTransferResults = true;
50
#endif
51
52
#if !defined(PROTO_FUZZER_TARGET_COMPATIBILITY)
53
/// Restore the target's protocol and timing invariants after every mutation.
54
/// Registering this during static initialization matters: corpus inputs pass
55
/// through LPM's Fix() before the first fuzz callback, so a function-local
56
/// registration would let the first input bypass the target policy.
57
0
void PostProcessScenario(curl::fuzzer::proto::Scenario* scenario, unsigned int /*seed*/) {
58
0
  proto_fuzzer::ApplyTargetPolicy(scenario, kTargetPolicy);
59
0
  proto_fuzzer::CanonicalizeOptionValueCases(scenario);
60
0
}
61
62
const protobuf_mutator::libfuzzer::PostProcessorRegistration<curl::fuzzer::proto::Scenario> kPolicyRegistration(
63
    &PostProcessScenario);
64
#endif
65
66
// Wire curl_global_init once so repeated fuzz iterations don't pay for it on every call. libFuzzer reuses the process;
67
// static ctors run once.
68
struct CurlGlobalBootstrap {
69
8
  CurlGlobalBootstrap() {
70
    // Keep parity with the legacy harness. libcurl normally suppresses
71
    // SIGPIPE for its own writes, but fuzzed connection lifecycles also race
72
    // mock-peer teardown; those failures should be reported as socket errors,
73
    // not mistaken for process crashes.
74
8
    std::signal(SIGPIPE, SIG_IGN);
75
8
    curl_global_init(CURL_GLOBAL_ALL);
76
8
  }
77
};
78
const CurlGlobalBootstrap kGlobalBootstrap;
79
80
}  // namespace
81
82
/// @brief libFuzzer entry point. libFuzzer will call this function with a valid Scenario protobuf message on each
83
/// fuzzing iteration. The function is expected to run the scenario and return. Any crashes or undefined behavior during
84
/// scenario execution will be reported by libFuzzer as fuzzing bugs.
85
/// @param scenario The Scenario describing the curl operations to perform.
86
10.1k
DEFINE_BINARY_PROTO_FUZZER(const curl::fuzzer::proto::Scenario& scenario) {
87
10.1k
  proto_fuzzer::ScenarioRunner().Run(scenario, kProbeTransferResults);
88
10.1k
}