Coverage Report

Created: 2026-10-22 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/curl_fuzzer/full_coverage/utility_api.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 "full_coverage/utility_api.h"
8
9
#include <ctime>
10
11
#include <curl/curl.h>
12
13
namespace full_coverage {
14
namespace {
15
16
/** Replay ordinary formats documented by curl and its date-parser tests. */
17
void ExerciseDates()
18
1
{
19
  // Valid formats and ordinary calendar variants follow
20
  // curl/docs/libcurl/curl_getdate.md. Epoch,
21
  // unsupported-format, calendar-range, and time_t-range examples come from
22
  // curl/tests/libtest/lib517.c. Every input is a short, fixed date string.
23
1
  const char *const dates[] = {
24
1
      "Sun, 06 Nov 1994 08:49:37 GMT",
25
1
      "Sunday, 06-Nov-94 08:49:37 GMT",
26
1
      "Sun Nov  6 08:49:37 1994",
27
1
      "06-Jul-94 08:49:37",
28
1
      "GMT 08:49:37 06-Aug-95 Sunday",
29
1
      "94 6 Oct 08:49:37",
30
1
      "1994 Mar 6",
31
1
      "1994.Feb.6",
32
1
      "Sun/Jun/6/93/GMT",
33
1
      "Mon, 06 Nov 1995 08:49:37 CET",
34
1
      "Tue, 06 Nov 2001 08:49:37 EST",
35
1
      "Sun, 12 Sep 2004 15:05:58 -0700",
36
1
      "Fri, 11 Sep 2009 21:32:11 +0200",
37
1
      "20040912 15:05:58 -0700",
38
1
      "20040911 +0200",
39
1
      "Saturday, May 5 GMT 11:56:27 2035",
40
1
      "Sat, 15-Apr-17 21:01:22 GMT",
41
1
      "Wed, 31 Dec 2008 23:59:60 GMT",
42
1
      "Thu, 01-Jan-1970 00:00:00 GMT",
43
1
      "Thu, 31-Dec-1969 23:59:59 GMT",
44
1
      "IAintNoDateFool",
45
1
      "1994-11-06T08:49:37Z",
46
1
      "Thu, 01-Jan-1499 00:00:00 GMT",
47
1
      "Sun, 06 Nov 1900 08:49:37 GMT",
48
1
      "Sun, 06 Nov 2044 08:49:37 GMT",
49
1
      ""};
50
26
  for(const char *date : dates) {
51
26
    const volatile std::time_t parsed = curl_getdate(date, nullptr);
52
26
    (void)parsed;
53
26
  }
54
1
  const volatile std::time_t missing = curl_getdate(nullptr, nullptr);
55
1
  (void)missing;
56
1
}
57
58
/** Cover compatibility aliases and the explicit binary-length API contract. */
59
void ExerciseEscaping()
60
1
{
61
1
  const char *const strings[] = {
62
1
      "",
63
1
      "data to convert",
64
1
      "a/b?c=d&reserved=+ %#",
65
1
      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~"};
66
4
  for(const char *text : strings) {
67
4
    char *encoded = curl_escape(text, 0);
68
4
    if(encoded) {
69
4
      curl_free(curl_unescape(encoded, 0));
70
4
      int length = 0;
71
4
      curl_free(curl_easy_unescape(nullptr, encoded, 0, &length));
72
4
    }
73
4
    curl_free(encoded);
74
4
  }
75
76
  // The escaping documentation specifies byte-oriented encoding. Explicit
77
  // lengths preserve an embedded NUL and a non-ASCII byte through decoding.
78
1
  const char binary[] = {'a', '\0', '%', static_cast<char>(0xff)};
79
1
  char *encoded = curl_escape(binary, static_cast<int>(sizeof(binary)));
80
1
  if(encoded) {
81
1
    int length = 0;
82
1
    curl_free(curl_easy_unescape(nullptr, encoded, 0, &length));
83
1
    curl_free(curl_unescape(encoded, 0));
84
1
  }
85
1
  curl_free(encoded);
86
1
  curl_free(curl_unescape("%00%FF%41", 9));
87
88
  // These rejected length values are ordinary API-contract checks from
89
  // curl/tests/libtest/lib1605.c; no memory or operating-system faults occur.
90
1
  curl_free(curl_easy_escape(nullptr, "", -1));
91
1
  int length = 0;
92
1
  curl_free(curl_easy_unescape(nullptr, "%41%41%41%41", -1, &length));
93
1
}
94
95
}  // namespace
96
97
void ExerciseUtilityApiCoverage()
98
1
{
99
1
  if(curl_global_init(CURL_GLOBAL_DEFAULT) != CURLE_OK)
100
0
    return;
101
102
  // The returned version string has static storage and must not be freed.
103
1
  const char *volatile version = curl_version();
104
1
  (void)version;
105
1
  ExerciseDates();
106
1
  ExerciseEscaping();
107
1
  curl_global_cleanup();
108
1
}
109
110
}  // namespace full_coverage