• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <stdio.h>
16 #include <stdlib.h>
17 
18 #include <algorithm>
19 #include <cstdint>
20 #include <string>
21 #include <vector>
22 
23 #include "absl/strings/str_cat.h"
24 #include "absl/strings/str_join.h"
25 #include "absl/types/optional.h"
26 #include "src/core/ext/transport/chttp2/transport/decode_huff.h"
27 #include "src/core/ext/transport/chttp2/transport/huffsyms.h"
28 
29 bool squelch = true;
30 bool leak_check = true;
31 
DecodeHuffSlow(const uint8_t * begin,const uint8_t * end)32 absl::optional<std::vector<uint8_t>> DecodeHuffSlow(const uint8_t* begin,
33                                                     const uint8_t* end) {
34   uint64_t bits = 0;
35   size_t bits_left = 0u;
36   std::vector<uint8_t> out;
37   while (true) {
38     while (begin != end && bits_left < 30) {
39       bits <<= 8;
40       bits |= begin[0];
41       ++begin;
42       bits_left += 8;
43     }
44     if (bits_left < 5) break;
45     bool found = false;
46     for (int i = 0; i < GRPC_CHTTP2_NUM_HUFFSYMS; i++) {
47       const auto& sym = grpc_chttp2_huffsyms[i];
48       if (sym.length > bits_left) continue;
49       if (((bits >> (bits_left - sym.length)) & ((1 << sym.length) - 1)) ==
50           sym.bits) {
51         found = true;
52         bits_left -= sym.length;
53         if (i == 256) {
54           return out;
55         }
56         out.push_back(i);
57         break;
58       }
59     }
60     if (!found) {
61       break;
62     }
63   }
64   while (bits_left > 0) {
65     if ((bits & 1) == 0) {
66       return absl::nullopt;
67     }
68     bits >>= 1;
69     bits_left--;
70   }
71   return out;
72 }
73 
ToString(absl::optional<std::vector<uint8_t>> s)74 std::string ToString(absl::optional<std::vector<uint8_t>> s) {
75   if (s == absl::nullopt) return "nullopt";
76   return absl::StrCat("{", absl::StrJoin(*s, ","), "}");
77 }
78 
DecodeHuffFast(const uint8_t * begin,const uint8_t * end)79 absl::optional<std::vector<uint8_t>> DecodeHuffFast(const uint8_t* begin,
80                                                     const uint8_t* end) {
81   std::vector<uint8_t> v;
82   auto f = [&](uint8_t x) { v.push_back(x); };
83   if (!grpc_core::HuffDecoder<decltype(f)>(f, begin, end).Run()) {
84     return absl::nullopt;
85   }
86   return v;
87 }
88 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)89 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
90   auto slow = DecodeHuffSlow(data, data + size);
91   auto fast = DecodeHuffFast(data, data + size);
92   if (slow != fast) {
93     fprintf(stderr, "MISMATCH:\ninpt: %s\nslow: %s\nfast: %s\n",
94             ToString(std::vector<uint8_t>(data, data + size)).c_str(),
95             ToString(slow).c_str(), ToString(fast).c_str());
96     abort();
97   }
98   return 0;
99 }
100