1 #include <string>
2 #include <fuzzer/FuzzedDataProvider.h>
3
4 extern "C" {
5 #include <string.h>
6 #include "nghttp2_hd.h"
7 #include "nghttp2_frame.h"
8
9 #include "nghttp2_test_helper.h"
10
11 #define HEADERS_LENGTH 7
12
fuzz_make_nv(std::string s1,std::string s2)13 static nghttp2_nv fuzz_make_nv(std::string s1, std::string s2) {
14 nghttp2_nv nv;
15 uint8_t *n = (uint8_t *)malloc(s1.size());
16 memcpy(n, s1.c_str(), s1.size());
17
18 uint8_t *v = (uint8_t *)malloc(s2.size());
19 memcpy(v, s2.c_str(), s2.size());
20
21 nv.name = n;
22 nv.value = v;
23 nv.namelen = s1.size();
24 nv.valuelen = s2.size();
25 nv.flags = NGHTTP2_NV_FLAG_NONE;
26
27 return nv;
28 }
29
fuzz_free_nv(nghttp2_nv * nv)30 static void fuzz_free_nv(nghttp2_nv *nv) {
31 free(nv->name);
32 free(nv->value);
33 }
34
check_frame_pack_headers(FuzzedDataProvider * data_provider)35 void check_frame_pack_headers(FuzzedDataProvider *data_provider) {
36 nghttp2_hd_deflater deflater;
37 nghttp2_hd_inflater inflater;
38 nghttp2_headers frame, oframe;
39 nghttp2_bufs bufs;
40 nghttp2_nv *nva;
41 nghttp2_priority_spec pri_spec;
42 size_t nvlen;
43 nva_out out;
44 size_t hdblocklen;
45 int rv;
46 nghttp2_mem *mem;
47
48 mem = nghttp2_mem_default();
49 frame_pack_bufs_init(&bufs);
50
51 nva_out_init(&out);
52 nghttp2_hd_deflate_init(&deflater, mem);
53 nghttp2_hd_inflate_init(&inflater, mem);
54
55 /* Create a set of headers seeded with data from the fuzzer */
56 nva = (nghttp2_nv *)mem->malloc(sizeof(nghttp2_nv) * HEADERS_LENGTH, NULL);
57 for (int i = 0; i < HEADERS_LENGTH; i++) {
58 nva[i] = fuzz_make_nv(data_provider->ConsumeRandomLengthString(30),
59 data_provider->ConsumeRandomLengthString(300));
60 }
61
62 nvlen = HEADERS_LENGTH;
63 nghttp2_priority_spec_default_init(&pri_spec);
64 nghttp2_frame_headers_init(
65 &frame, NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS, 1000000007,
66 NGHTTP2_HCAT_REQUEST, &pri_spec, nva, nvlen);
67
68 /* Perform a set of operations with the fuzz data */
69 rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
70 if (rv == 0) {
71 unpack_framebuf((nghttp2_frame *)&oframe, &bufs);
72
73 inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN, mem);
74 nva_out_reset(&out, mem);
75 nghttp2_bufs_reset(&bufs);
76 }
77
78 nghttp2_nv *nva2 = NULL;
79 rv = nghttp2_nv_array_copy(&nva2, nva, nvlen, mem);
80 if (rv == 0) {
81 nghttp2_nv_array_del(nva2, mem);
82 }
83
84 /* Cleanup */
85 for (int i = 0; i < HEADERS_LENGTH; i++) {
86 fuzz_free_nv(&nva[i]);
87 }
88
89 nghttp2_bufs_free(&bufs);
90 nghttp2_frame_headers_free(&frame, mem);
91 nghttp2_hd_inflate_free(&inflater);
92 nghttp2_hd_deflate_free(&deflater);
93 }
94
check_frame_push_promise(FuzzedDataProvider * data_provider)95 void check_frame_push_promise(FuzzedDataProvider *data_provider) {
96 nghttp2_hd_deflater deflater;
97 nghttp2_hd_inflater inflater;
98 nghttp2_push_promise frame, oframe;
99 nghttp2_bufs bufs;
100 nghttp2_nv *nva;
101 nghttp2_priority_spec pri_spec;
102 size_t nvlen;
103 nva_out out;
104 size_t hdblocklen;
105 int rv;
106 nghttp2_mem *mem;
107
108 mem = nghttp2_mem_default();
109 frame_pack_bufs_init(&bufs);
110
111 nva_out_init(&out);
112 nghttp2_hd_deflate_init(&deflater, mem);
113 nghttp2_hd_inflate_init(&inflater, mem);
114
115 /* Create a set of headers seeded with data from the fuzzer */
116 nva = (nghttp2_nv *)mem->malloc(sizeof(nghttp2_nv) * HEADERS_LENGTH, NULL);
117 for (int i = 0; i < HEADERS_LENGTH; i++) {
118 nva[i] = fuzz_make_nv(data_provider->ConsumeRandomLengthString(30),
119 data_provider->ConsumeRandomLengthString(300));
120 }
121 nvlen = HEADERS_LENGTH;
122 nghttp2_priority_spec_default_init(&pri_spec);
123
124 /* Perform a set of operations with the fuzz data */
125 nghttp2_frame_push_promise_init(&frame, NGHTTP2_FLAG_END_HEADERS, 1000000007,
126 (1U << 31) - 1, nva, nvlen);
127
128 rv = nghttp2_frame_pack_push_promise(&bufs, &frame, &deflater);
129 if (rv == 0) {
130 unpack_framebuf((nghttp2_frame *)&oframe, &bufs);
131 }
132
133 nghttp2_nv *nva2 = NULL;
134 rv = nghttp2_nv_array_copy(&nva2, nva, nvlen, mem);
135 if (rv == 0) {
136 nghttp2_nv_array_del(nva2, mem);
137 }
138
139 /* Cleanup */
140 for (int i = 0; i < HEADERS_LENGTH; i++) {
141 fuzz_free_nv(&nva[i]);
142 }
143
144 nghttp2_bufs_reset(&bufs);
145 nghttp2_bufs_free(&bufs);
146
147 nghttp2_frame_push_promise_free(&frame, mem);
148 nghttp2_hd_inflate_free(&inflater);
149 nghttp2_hd_deflate_free(&deflater);
150 }
151
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)152 int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
153 FuzzedDataProvider data_provider(data, size);
154
155 check_frame_pack_headers(&data_provider);
156 check_frame_push_promise(&data_provider);
157 return 0;
158 }
159
160 } // extern C
161