Coverage Report

Created: 2023-06-06 06:17

/src/uWebSockets/fuzzing/Http.cpp
Line
Count
Source (jump to first uncovered line)
1
/* This is a fuzz test of the http parser */
2
3
#define WIN32_EXPORT
4
5
#include "helpers.h"
6
7
/* We test the websocket parser */
8
#include "../src/HttpParser.h"
9
10
/* And the router */
11
#include "../src/HttpRouter.h"
12
13
/* Also ProxyParser */
14
#include "../src/ProxyParser.h"
15
16
struct StaticData {
17
18
    struct RouterData {
19
20
    };
21
22
    uWS::HttpRouter<RouterData> router;
23
24
4
    StaticData() {
25
26
5.11k
        router.add({"get"}, "/:hello/:hi", [](auto *h) mutable {
27
5.11k
            auto [paramsTop, params] = h->getParameters();
28
29
            /* Something is horribly wrong */
30
5.11k
            if (paramsTop != 1 || !params[0].length() || !params[1].length()) {
31
0
                exit(-1);
32
0
            }
33
34
            /* This route did handle it */
35
5.11k
            return true;
36
5.11k
        });
37
38
2.35k
        router.add({"post"}, "/:hello/:hi/*", [](auto *h) mutable {
39
2.35k
            auto [paramsTop, params] = h->getParameters();
40
41
            /* Something is horribly wrong */
42
2.35k
            if (paramsTop != 1 || !params[0].length() || !params[1].length()) {
43
0
                exit(-1);
44
0
            }
45
46
            /* This route did handle it */
47
2.35k
            return true;
48
2.35k
        });
49
50
342
        router.add({"get"}, "/*", [](auto *h) mutable {
51
342
            auto [paramsTop, params] = h->getParameters();
52
53
            /* Something is horribly wrong */
54
342
            if (paramsTop != -1) {
55
0
                exit(-1);
56
0
            }
57
58
            /* This route did not handle it */
59
342
            return false;
60
342
        });
61
62
10.6k
        router.add({"get"}, "/hi", [](auto *h) mutable {
63
10.6k
            auto [paramsTop, params] = h->getParameters();
64
65
            /* Something is horribly wrong */
66
10.6k
            if (paramsTop != -1) {
67
0
                exit(-1);
68
0
            }
69
70
            /* This route did handle it */
71
10.6k
            return true;
72
10.6k
        });
73
4
    }
74
} staticData;
75
76
7.50k
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
77
    /* Create parser */
78
7.50k
    uWS::HttpParser httpParser;
79
    /* User data */
80
7.50k
    void *user = (void *) 13;
81
82
    /* If we are built with WITH_PROXY, pass a ProxyParser as reserved */
83
7.50k
    void *reserved = nullptr;
84
#ifdef UWS_WITH_PROXY
85
    uWS::ProxyParser pp;
86
    reserved = (void *) &pp;
87
#endif
88
89
    /* Iterate the padded fuzz as chunks */
90
246k
    makeChunked(makePadded(data, size), size, [&httpParser, &user, reserved](const uint8_t *data, size_t size) {
91
        /* We need at least 1 byte post padding */
92
246k
        if (size) {
93
246k
            size--;
94
246k
        } else {
95
            /* We might be given zero length chunks */
96
41
            return;
97
41
        }
98
99
        /* If user is null then ignore this chunk */
100
246k
        if (!user) {
101
970
            return;
102
970
        }
103
104
        /* Parse it */
105
245k
        auto [err, returnedUser] = httpParser.consumePostPadded((char *) data, size, user, reserved, [reserved](void *s, uWS::HttpRequest *httpRequest) -> void * {
106
107
19.8k
            readBytes(httpRequest->getHeader(httpRequest->getUrl()));
108
19.8k
            readBytes(httpRequest->getMethod());
109
19.8k
            readBytes(httpRequest->getQuery());
110
19.8k
            readBytes(httpRequest->getQuery("hello"));
111
19.8k
            readBytes(httpRequest->getQuery(""));
112
            //readBytes(httpRequest->getParameter(0));
113
114
#ifdef UWS_WITH_PROXY
115
            auto *pp = (uWS::ProxyParser *) reserved;
116
            readBytes(pp->getSourceAddress());
117
#endif
118
119
            /* Route the method and URL in two passes */
120
19.8k
            staticData.router.getUserData() = {};
121
19.8k
            if (!staticData.router.route(httpRequest->getMethod(), httpRequest->getUrl())) {
122
                /* It was not handled */
123
1.82k
                return nullptr;
124
1.82k
            }
125
126
35.8k
            for (auto p : *httpRequest) {
127
128
35.8k
            }
129
130
            /* Return ok */
131
18.0k
            return s;
132
133
51.3k
        }, [](void *user, std::string_view data, bool fin) -> void * {
134
135
            /* Return ok */
136
51.3k
            return user;
137
138
51.3k
        });
139
140
245k
        if (!returnedUser) {
141
            /* It is of uttermost importance that if and when we return nullptr from the httpParser we must not
142
             * ever use the httpParser ever again. It is in a broken state as returning nullptr is only used
143
             * for signalling early closure. You must absolutely must throw it away. Here we just mark user as
144
             * null so that we can ignore further chunks of data */
145
1.82k
            user = nullptr;
146
1.82k
        }
147
245k
    });
148
149
7.50k
    return 0;
150
7.50k
}
151