Coverage Report

Created: 2026-09-14 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/MapServer/fuzzers/owsfuzzer.c
Line
Count
Source
1
#include <stdint.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
#include "src/mapserver.h"
6
#include "src/cgiutil.h"
7
#include "src/mapows.h"
8
#include "src/mapio.h"
9
#include "src/maphash.h"
10
#include "src/maptemplate.h"
11
12
9.76k
#define kMaxInputLength 65536
13
// Stay under MS_DEFAULT_CGI_PARAMS (100) so ParamNames/ParamValues don't
14
// overflow
15
46.2k
#define kMaxParams 90
16
17
extern int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
18
extern int LLVMFuzzerInitialize(int *argc, char ***argv);
19
20
7
int LLVMFuzzerInitialize(int *argc, char ***argv) {
21
7
  (void)argc;
22
7
  (void)argv;
23
7
  msIO_setHeaderEnabled(MS_FALSE);
24
7
  return 0;
25
7
}
26
27
9.76k
static mapObj *buildMap(void) {
28
9.76k
  mapObj *map = msNewMapObj();
29
9.76k
  if (!map)
30
0
    return NULL;
31
32
9.76k
  msInsertHashTable(&(map->web.metadata), "ows_enable_request", "*");
33
9.76k
  msInsertHashTable(&(map->web.metadata), "ows_onlineresource",
34
9.76k
                    "http://localhost/?");
35
9.76k
  msInsertHashTable(&(map->web.metadata), "ows_srs", "EPSG:4326");
36
9.76k
  msInsertHashTable(&(map->web.metadata), "ows_title", "fuzz");
37
38
9.76k
  if (!map->name)
39
0
    map->name = msStrdup("fuzz");
40
41
9.76k
  return map;
42
9.76k
}
43
44
9.76k
static void parseParams(cgiRequestObj *request, const char *buf, size_t size) {
45
9.76k
  size_t i = 0;
46
56.0k
  while (i < size && request->NumParams < kMaxParams) {
47
46.2k
    size_t start = i;
48
3.42M
    while (i < size && buf[i] != '&')
49
3.37M
      i++;
50
46.2k
    size_t pairLen = i - start;
51
46.2k
    if (i < size)
52
36.7k
      i++;
53
54
46.2k
    if (pairLen == 0)
55
2.23k
      continue;
56
57
44.0k
    const char *pair = buf + start;
58
44.0k
    size_t eq = 0;
59
812k
    while (eq < pairLen && pair[eq] != '=')
60
768k
      eq++;
61
62
44.0k
    size_t keyLen = eq;
63
44.0k
    if (keyLen == 0)
64
3.54k
      continue;
65
66
40.4k
    size_t valLen = (eq < pairLen) ? (pairLen - eq - 1) : 0;
67
40.4k
    const char *valPtr = (eq < pairLen) ? (pair + eq + 1) : "";
68
69
40.4k
    char *key = (char *)malloc(keyLen + 1);
70
40.4k
    char *val = (char *)malloc(valLen + 1);
71
40.4k
    if (!key || !val) {
72
0
      free(key);
73
0
      free(val);
74
0
      return;
75
0
    }
76
40.4k
    memcpy(key, pair, keyLen);
77
40.4k
    key[keyLen] = '\0';
78
40.4k
    if (valLen)
79
26.7k
      memcpy(val, valPtr, valLen);
80
40.4k
    val[valLen] = '\0';
81
82
40.4k
    request->ParamNames[request->NumParams] = key;
83
40.4k
    request->ParamValues[request->NumParams] = val;
84
40.4k
    request->NumParams++;
85
40.4k
  }
86
9.76k
}
87
88
9.76k
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
89
9.76k
  if (Size == 0 || Size > kMaxInputLength)
90
5
    return 0;
91
92
9.76k
  mapObj *map = buildMap();
93
9.76k
  if (!map) {
94
0
    msResetErrorList();
95
0
    return 0;
96
0
  }
97
98
9.76k
  cgiRequestObj *request = msAllocCgiObj();
99
9.76k
  if (!request) {
100
0
    msFreeMap(map);
101
0
    msResetErrorList();
102
0
    return 0;
103
0
  }
104
9.76k
  request->type = MS_GET_REQUEST;
105
106
9.76k
  parseParams(request, (const char *)Data, Size);
107
108
  // capture dispatcher output so nothing leaks to real stdout. Use only the
109
  // public (MS_DLL_EXPORT) msIO buffer API so the reproducer links on Windows.
110
9.76k
  msIO_installStdoutToBuffer();
111
112
9.76k
  (void)msOWSDispatch(map, request, OWS);
113
114
9.76k
  char *content_type = msIO_stripStdoutBufferContentType();
115
9.76k
  if (content_type)
116
0
    msFree(content_type);
117
  // reset stdout back to the default stdio context and free the buffer
118
9.76k
  msIO_resetHandlers();
119
120
9.76k
  msFreeCgiObj(request);
121
9.76k
  msFreeMap(map);
122
9.76k
  msResetErrorList();
123
124
9.76k
  return 0;
125
9.76k
}