aboutsummaryrefslogtreecommitdiff
path: root/packages/bun-uws/fuzzing/Http.cpp
blob: 68c5c5d9819d2920717982da01c62baa07702594 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
/* This is a fuzz test of the http parser */

#define WIN32_EXPORT

#include "helpers.h"

/* We test the websocket parser */
#include "../src/HttpParser.h"

/* And the router */
#include "../src/HttpRouter.h"

/* Also ProxyParser */
#include "../src/ProxyParser.h"

struct StaticData {

    struct RouterData {

    };

    uWS::HttpRouter<RouterData> router;

    StaticData() {

        router.add({"get"}, "/:hello/:hi", [](auto *h) mutable {
            auto [paramsTop, params] = h->getParameters();

            /* Something is horribly wrong */
            if (paramsTop != 1 || !params[0].length() || !params[1].length()) {
                exit(-1);
            }

            /* This route did handle it */
            return true;
        });

        router.add({"post"}, "/:hello/:hi/*", [](auto *h) mutable {
            auto [paramsTop, params] = h->getParameters();

            /* Something is horribly wrong */
            if (paramsTop != 1 || !params[0].length() || !params[1].length()) {
                exit(-1);
            }

            /* This route did handle it */
            return true;
        });

        router.add({"get"}, "/*", [](auto *h) mutable {
            auto [paramsTop, params] = h->getParameters();

            /* Something is horribly wrong */
            if (paramsTop != -1) {
                exit(-1);
            }

            /* This route did not handle it */
            return false;
        });

        router.add({"get"}, "/hi", [](auto *h) mutable {
            auto [paramsTop, params] = h->getParameters();

            /* Something is horribly wrong */
            if (paramsTop != -1) {
                exit(-1);
            }

            /* This route did handle it */
            return true;
        });
    }
} staticData;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
    /* Create parser */
    uWS::HttpParser httpParser;
    /* User data */
    void *user = (void *) 13;

    /* If we are built with WITH_PROXY, pass a ProxyParser as reserved */
    void *reserved = nullptr;
#ifdef UWS_WITH_PROXY
    uWS::ProxyParser pp;
    reserved = (void *) &pp;
#endif

    /* Iterate the padded fuzz as chunks */
    makeChunked(makePadded(data, size), size, [&httpParser, &user, reserved](const uint8_t *data, size_t size) {
        /* We need at least 1 byte post padding */
        if (size) {
            size--;
        } else {
            /* We might be given zero length chunks */
            return;
        }

        /* If user is null then ignore this chunk */
        if (!user) {
            return;
        }

        /* Parse it */
        void *returnedUser = httpParser.consumePostPadded((char *) data, size, user, reserved, [reserved](void *s, uWS::HttpRequest *httpRequest) -> void * {

            readBytes(httpRequest->getHeader(httpRequest->getUrl()));
            readBytes(httpRequest->getMethod());
            readBytes(httpRequest->getQuery());
            readBytes(httpRequest->getQuery("hello"));
            readBytes(httpRequest->getQuery(""));
            //readBytes(httpRequest->getParameter(0));

#ifdef UWS_WITH_PROXY
            auto *pp = (uWS::ProxyParser *) reserved;
            readBytes(pp->getSourceAddress());
#endif

            /* Route the method and URL in two passes */
            staticData.router.getUserData() = {};
            if (!staticData.router.route(httpRequest->getMethod(), httpRequest->getUrl())) {
                /* It was not handled */
                return nullptr;
            }

            for (auto p : *httpRequest) {

            }

            /* Return ok */
            return s;

        }, [](void *user, std::string_view data, bool fin) -> void * {

            /* Return ok */
            return user;

        }, [](void *user) -> void * {

            /* Return break */
            return nullptr;
        });

        if (!returnedUser) {
            /* It is of uttermost importance that if and when we return nullptr from the httpParser we must not
             * ever use the httpParser ever again. It is in a broken state as returning nullptr is only used
             * for signalling early closure. You must absolutely must throw it away. Here we just mark user as
             * null so that we can ignore further chunks of data */
            user = nullptr;
        }
    });

    return 0;
}