Coverage Report

Created: 2026-10-28 07:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl_fuzzer/proto_fuzzer/api_coverage_probes.cc
Line
Count
Source
1
/*
2
 * Copyright (C) Max Dymond, <cmeister2@gmail.com>, et al.
3
 *
4
 * SPDX-License-Identifier: curl
5
 */
6
7
#include "proto_fuzzer/api_coverage_probes.h"
8
9
#include <curl/curl.h>
10
11
#include "full_coverage/dynamic_formatting.h"
12
#include "full_coverage/public_api.h"
13
#include "full_coverage/utility_api.h"
14
#include "proto_fuzzer/allocation_fault_injection.h"
15
#include "proto_fuzzer/curl_global_lifecycle.h"
16
17
namespace proto_fuzzer {
18
namespace {
19
20
/** Balance the API probe's public global reference only at process exit. */
21
class DeferredCurlGlobalReference final {
22
 public:
23
2
  DeferredCurlGlobalReference() : initialized_(curl_global_init(CURL_GLOBAL_ALL) == CURLE_OK) {}
24
25
2
  ~DeferredCurlGlobalReference() {
26
2
    if (initialized_) {
27
      // Drop this probe's public reference, then ask the registered owner to
28
      // release its own base reference. This destructor was registered from
29
      // LLVMFuzzerInitialize, so final resolver/TLS cleanup runs before LLVM's
30
      // profile writer. The owner's later destructor is then a no-op.
31
2
      curl_global_cleanup();
32
2
      FinalizeRegisteredCurlGlobalLifecyclesForExit();
33
2
    }
34
2
  }
35
36
  DeferredCurlGlobalReference(const DeferredCurlGlobalReference&) = delete;
37
  DeferredCurlGlobalReference& operator=(const DeferredCurlGlobalReference&) = delete;
38
39
 private:
40
  bool initialized_;
41
};
42
43
}  // namespace
44
45
/**
46
 * Run bounded curl API probes once without tearing down global state.
47
 *
48
 * The caller normally owns an initialized curl runtime. This function retains
49
 * one public global reference until process exit, so repeated calls are safe
50
 * and perform no additional work. Both LLVMFuzzerInitialize and the first
51
 * input callback can therefore provide reachability without per-input cost.
52
 */
53
11.9k
void RunApiCoverageProbesOnce() {
54
  // This function-local lifetime begins after the proto runtime's static
55
  // bootstrap, so its destructor can finalize curl before the bootstrap's
56
  // idempotent destructor and LLVM's profile write.
57
11.9k
  static const DeferredCurlGlobalReference global_reference;
58
11.9k
  static const bool completed = [] {
59
    // These are harness-owned deterministic allocations, not part of a
60
    // Scenario's fault plan. The initialization hook normally runs before a
61
    // plan can be armed; suppression also makes the callback fallback safe.
62
2
    allocation_fault_injection::ScopedFailureSuppression suppress_failures;
63
2
    full_coverage::ExercisePublicApiCoverageWithInitializedCurl();
64
2
    full_coverage::ExerciseUtilityApiCoverageWithInitializedCurl();
65
2
    full_coverage::ExerciseDynamicFormattingCoverage();
66
2
    return true;
67
2
  }();
68
11.9k
  (void)global_reference;
69
11.9k
  (void)completed;
70
11.9k
}
71
72
}  // namespace proto_fuzzer