2828#include " curl_fuzzer.h"
2929#include " curl_fuzzer_scenario.h"
3030
31+ #if defined(__has_include)
32+ # if __has_include(<sanitizer/lsan_interface.h>)
33+ # include < sanitizer/lsan_interface.h>
34+ # define CURL_FUZZER_HAS_LSAN 1
35+ # else
36+ # define CURL_FUZZER_HAS_LSAN 0
37+ # endif
38+ #else
39+ # define CURL_FUZZER_HAS_LSAN 0
40+ #endif
41+
3142#include < libprotobuf-mutator/src/libfuzzer/libfuzzer_macro.h>
3243
44+ namespace {
45+
46+ bool ShouldRunPerScenarioLeakCheck ()
47+ {
48+ static int cached = -1 ;
49+ if (cached == -1 ) {
50+ const char *env = getenv (" FUZZ_PER_SCENARIO_LEAK_CHECK" );
51+ cached = (env != NULL && env[0 ] != ' \0 ' && strcmp (env, " 0" ) != 0 ) ? 1 : 0 ;
52+ }
53+ return cached == 1 ;
54+ }
55+
56+ bool FuzzOptionIsSet (const FUZZ_DATA *fuzz, CURLoption opt)
57+ {
58+ size_t idx = static_cast <size_t >(opt % 1000 );
59+ if (idx >= FUZZ_CURLOPT_TRACKER_SPACE) {
60+ return false ;
61+ }
62+ return fuzz->options [idx] != 0 ;
63+ }
64+
65+ void EnforceScenarioLeakCleanliness ()
66+ {
67+ #if CURL_FUZZER_HAS_LSAN
68+ if (ShouldRunPerScenarioLeakCheck ()) {
69+ __lsan_do_leak_check ();
70+ }
71+ #else
72+ (void )ShouldRunPerScenarioLeakCheck ();
73+ #endif
74+ }
75+
76+ } // namespace
77+
3378DEFINE_BINARY_PROTO_FUZZER (const curl::fuzzer::proto::Scenario &scenario)
3479{
3580 CurlFuzzerRunScenario (scenario);
@@ -54,6 +99,14 @@ int CurlFuzzerRunScenario(const curl::fuzzer::proto::Scenario &scenario)
5499 FV_PRINTF (&fuzz, " SCENARIO: ApplyScenario failed with rc=%d\n " , rc);
55100 goto EXIT_LABEL;
56101 }
102+
103+ if (!FuzzOptionIsSet (&fuzz, CURLOPT_URL)) {
104+ if (fuzz.verbose ) {
105+ FV_PRINTF (&fuzz, " SCENARIO: skipping transfer due to missing CURLOPT_URL\n " );
106+ }
107+ goto EXIT_LABEL;
108+ }
109+
57110 FV_PRINTF (&fuzz,
58111 " SCENARIO: successfully applied scenario, starting transfer\n " );
59112
@@ -90,6 +143,7 @@ int CurlFuzzerRunScenario(const curl::fuzzer::proto::Scenario &scenario)
90143EXIT_LABEL:
91144
92145 fuzz_terminate_fuzz_data (&fuzz);
146+ EnforceScenarioLeakCleanliness ();
93147
94148 /* This function must always return 0. Non-zero codes are reserved. */
95149 return 0 ;
@@ -282,6 +336,7 @@ void fuzz_terminate_fuzz_data(FUZZ_DATA *fuzz)
282336 curl_formfree (fuzz->httppost );
283337 fuzz->httppost = NULL ;
284338 }
339+ fuzz->last_post_part = NULL ;
285340
286341 // free after httppost and last_post_part.
287342 if (fuzz->post_body != NULL ) {
0 commit comments