Coverage Report

Created: 2026-04-29 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/uWebSockets/fuzzing/EpollHelloWorld.cpp
Line
Count
Source
1
/* We rely on wrapped syscalls */
2
#include "libEpollFuzzer/epoll_fuzzer.h"
3
4
#include "App.h"
5
6
/* We keep this one for teardown later on */
7
struct us_listen_socket_t *listen_socket;
8
struct us_socket_t *client;
9
10
/* This test is run by libEpollFuzzer */
11
6.54k
void test() {
12
  /* ws->getUserData returns one of these */
13
6.54k
    struct PerSocketData {
14
        /* Fill with user data */
15
6.54k
    };
16
17
6.54k
    {
18
        /* Keep in mind that uWS::SSLApp({options}) is the same as uWS::App() when compiled without SSL support.
19
        * You may swap to using uWS:App() if you don't need SSL */
20
6.54k
        auto app = uWS::App({
21
            /* There are example certificates in uWebSockets.js repo */
22
6.54k
            .key_file_name = "../misc/key.pem",
23
6.54k
            .cert_file_name = "../misc/cert.pem",
24
6.54k
            .passphrase = "1234"
25
6.54k
        }).ws<PerSocketData>("/empty", {
26
        /* Having no handlers here should not crash */
27
9.24k
        }).get("/*", [](auto *res, auto *req) {
28
9.24k
            if (req->getHeader("write").length()) {
29
1.66k
                res->writeStatus("200 OK")->writeHeader("write", "true")->write("Hello");
30
1.66k
                res->write(" world!");
31
1.66k
                res->end();
32
7.57k
            } else if (req->getQuery().length()) {
33
773
                res->close();
34
6.80k
            } else {
35
6.80k
                res->end("Hello world!");
36
6.80k
            }
37
9.24k
        }).post("/*", [](auto *res, auto *req) {
38
3.03k
            res->onAborted([]() {
39
                /* We might as well use this opportunity to stress the loop a bit */
40
1.47k
                uWS::Loop::get()->defer([]() {
41
42
1.19k
                });
43
1.47k
            });
44
32.8k
            res->onData([res](std::string_view chunk, bool isEnd) {
45
32.8k
                if (isEnd) {
46
1.56k
                    res->cork([res, chunk]() {
47
1.56k
                        res->write("something ahead");
48
1.56k
                        res->end(chunk);
49
1.56k
                    });
50
1.56k
                }
51
32.8k
            });
52
3.03k
        }).any("/:candy/*", [](auto *res, auto *req) {
53
2.12k
            if (req->getParameter(0).length() == 0) {
54
0
                free((void *) -1);
55
0
            }
56
            /* Some invalid queries */
57
2.12k
            req->getParameter(30000);
58
2.12k
            req->getParameter((unsigned short) -34234);
59
2.12k
            req->getHeader("yhello");
60
2.12k
            req->getQuery();
61
2.12k
            req->getQuery("assd");
62
63
2.12k
            res->end("done");
64
2.12k
        }).ws<PerSocketData>("/*", {
65
            /* Settings */
66
6.54k
            .compression = uWS::SHARED_COMPRESSOR,
67
6.54k
            .maxPayloadLength = 16 * 1024,
68
6.54k
            .idleTimeout = 12,
69
6.54k
            .maxBackpressure = 1024,
70
            /* Handlers */
71
39.6k
            .open = [](auto *ws) {
72
                /* Open event here, you may access ws->getUserData() which points to a PerSocketData struct */
73
39.6k
                ws->getNativeHandle();
74
39.6k
                ws->getRemoteAddressAsText();
75
39.6k
                us_poll_ext((struct us_poll_t *) ws);
76
39.6k
            },
77
10.4k
            .message = [](auto *ws, std::string_view message, uWS::OpCode opCode) {
78
10.4k
                ws->send(message, opCode, true);
79
10.4k
            },
80
6.54k
            .drain = [](auto *ws) {
81
                /* Check ws->getBufferedAmount() here */
82
2.80k
            },
83
24.4k
            .ping = [](auto *ws, std::string_view) {
84
                /* We use this to trigger the async/wakeup feature */
85
24.4k
                uWS::Loop::get()->defer([]() {
86
                    /* Do nothing */
87
13.3k
                });
88
24.4k
            },
89
6.54k
            .pong = [](auto *ws, std::string_view) {
90
                /* Not implemented yet */
91
1.63k
            },
92
39.6k
            .close = [](auto *ws, int code, std::string_view message) {
93
                /* You may access ws->getUserData() here */
94
39.6k
            }
95
6.54k
        }).listen(9001, [](auto *listenSocket) {
96
6.54k
            listen_socket = listenSocket;
97
6.54k
        });
98
99
        /* Here we want to stress the connect feature, since nothing else stresses it */
100
6.54k
        struct us_loop_t *loop = (struct us_loop_t *) uWS::Loop::get();
101
        /* This function is stupid */
102
6.54k
        us_loop_iteration_number(loop);
103
6.54k
        struct us_socket_context_t *client_context = us_create_socket_context(0, loop, 0, {});
104
6.54k
        us_socket_context_timestamp(0, client_context);
105
6.54k
        client = us_socket_context_connect(0, client_context, "hostname", 5000, "localhost", 0, 0);
106
      
107
6.54k
        if (client) {
108
1.89k
            us_socket_is_established(0, client);
109
1.89k
            us_socket_local_port(0, client);
110
1.89k
        }
111
112
6.54k
        us_socket_context_on_connect_error(0, client_context, [](struct us_socket_t *s, int code) {
113
1.63k
            client = nullptr;
114
1.63k
            return s;
115
1.63k
        });
116
117
6.54k
        us_socket_context_on_open(0, client_context, [](struct us_socket_t *s, int is_client, char *ip, int ip_length) {
118
215
            us_socket_flush(0, s);
119
215
            return s;
120
215
        });
121
122
6.54k
        us_socket_context_on_end(0, client_context, [](struct us_socket_t *s) {
123
            /* Someone sent is a FIN, but we can still send data */
124
1.26k
            us_socket_write(0, s, "asdadasdasdasdaddfgdfhdfgdfg", 28, false);
125
1.26k
            return s;
126
1.26k
        });
127
128
6.54k
        us_socket_context_on_data(0, client_context, [](struct us_socket_t *s, char *data, int length) {
129
224
            return s;
130
224
        });
131
132
6.54k
        us_socket_context_on_writable(0, client_context, [](struct us_socket_t *s) {
133
            /* Let's defer a close here */
134
1.16k
            us_socket_shutdown_read(0, s);
135
1.16k
            return s;
136
1.16k
        });
137
138
6.54k
        us_socket_context_on_close(0, client_context, [](struct us_socket_t *s, int code, void *reason) {
139
260
            client = NULL;
140
260
            return s;
141
260
        });
142
143
        /* Trigger some context functions */
144
6.54k
        app.addServerName("servername", {});
145
6.54k
        app.removeServerName("servername");
146
6.54k
        app.missingServerName(nullptr);
147
6.54k
        app.getNativeHandle();
148
149
6.54k
        app.run();
150
151
        /* After done we also free the client context */
152
6.54k
        us_socket_context_free(0, client_context);
153
6.54k
    }
154
6.54k
    uWS::Loop::get()->setSilent(true);
155
6.54k
    uWS::Loop::get()->free();
156
6.54k
}
157
158
/* Thus function should shutdown the event-loop and let the test fall through */
159
6.49k
void teardown() {
160
  /* If we are called twice there's a bug (it potentially could if
161
   * all open sockets cannot be error-closed in one epoll_wait call).
162
   * But we only allow 1k FDs and we have a buffer of 1024 from epoll_wait */
163
6.49k
  if (!listen_socket && !client) {
164
0
    exit(-1);
165
0
  }
166
167
6.49k
    if (client) {
168
135
        us_socket_close(0, client, 0, 0);
169
135
        client = NULL;
170
135
    }
171
172
  /* We might have open sockets still, and these will be error-closed by epoll_wait */
173
  // us_socket_context_close - close all open sockets created with this socket context
174
6.49k
    if (listen_socket) {
175
6.39k
        us_listen_socket_close(0, listen_socket);
176
        listen_socket = NULL;
177
6.39k
    }
178
6.49k
}