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