xref: /third_party/nghttp2/fuzz/fuzz_frames.cc (revision 2c593315)
1#include <string>
2#include <fuzzer/FuzzedDataProvider.h>
3
4extern "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
13static 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
30static void fuzz_free_nv(nghttp2_nv *nv) {
31  free(nv->name);
32  free(nv->value);
33}
34
35void 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
95void 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
152int 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