1 // Copyright 2022 gRPC authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include <grpc/slice.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19
20 #include <algorithm>
21 #include <cstdint>
22 #include <string>
23 #include <vector>
24
25 #include "absl/strings/str_cat.h"
26 #include "absl/strings/str_join.h"
27 #include "absl/types/optional.h"
28 #include "src/core/ext/transport/chttp2/transport/bin_encoder.h"
29 #include "src/core/ext/transport/chttp2/transport/decode_huff.h"
30
31 bool squelch = true;
32 bool leak_check = true;
33
ToString(absl::optional<std::vector<uint8_t>> s)34 std::string ToString(absl::optional<std::vector<uint8_t>> s) {
35 if (s == absl::nullopt) return "nullopt";
36 return absl::StrCat("{", absl::StrJoin(*s, ","), "}");
37 }
38
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)39 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
40 grpc_slice uncompressed =
41 grpc_slice_from_copied_buffer(reinterpret_cast<const char*>(data), size);
42 grpc_slice compressed = grpc_chttp2_huffman_compress(uncompressed);
43 std::vector<uint8_t> uncompressed_again;
44 auto add = [&uncompressed_again](uint8_t c) {
45 uncompressed_again.push_back(c);
46 };
47 auto fail = [&](const char* reason) {
48 fprintf(stderr,
49 "Failed: %s\nuncompressed: %s\ncompressed: %s\nuncompressed_again: "
50 "%s\n",
51 reason, ToString(std::vector<uint8_t>(data, data + size)).c_str(),
52 ToString(std::vector<uint8_t>(GRPC_SLICE_START_PTR(compressed),
53 GRPC_SLICE_START_PTR(compressed) +
54 GRPC_SLICE_LENGTH(compressed)))
55 .c_str(),
56 ToString(uncompressed_again).c_str());
57 abort();
58 };
59 if (!grpc_core::HuffDecoder<decltype(add)>(add,
60 GRPC_SLICE_START_PTR(compressed),
61 GRPC_SLICE_END_PTR(compressed))
62 .Run()) {
63 fail("decoding");
64 }
65 if (uncompressed_again.size() != size) {
66 fail("size mismatch");
67 }
68 if (memcmp(uncompressed_again.data(), data, size) != 0) {
69 fail("data mismatch");
70 }
71 grpc_slice_unref(uncompressed);
72 grpc_slice_unref(compressed);
73 return 0;
74 }
75