• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/spdy/fuzzing/hpack_fuzz_util.h"
6 
7 #include <map>
8 
9 #include "base/base_paths.h"
10 #include "base/files/file.h"
11 #include "base/files/file_util.h"
12 #include "base/path_service.h"
13 #include "net/base/hex_utils.h"
14 #include "net/third_party/quiche/src/quiche/common/http/http_header_block.h"
15 #include "testing/gmock/include/gmock/gmock.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 
18 namespace spdy::test {
19 
20 using quiche::HttpHeaderBlock;
21 using std::map;
22 
TEST(HpackFuzzUtilTest,GeneratorContextInitialization)23 TEST(HpackFuzzUtilTest, GeneratorContextInitialization) {
24   HpackFuzzUtil::GeneratorContext context;
25   HpackFuzzUtil::InitializeGeneratorContext(&context);
26 
27   // Context was seeded with initial name & value fixtures.
28   EXPECT_LT(0u, context.names.size());
29   EXPECT_LT(0u, context.values.size());
30 }
31 
TEST(HpackFuzzUtil,GeneratorContextExpansion)32 TEST(HpackFuzzUtil, GeneratorContextExpansion) {
33   HpackFuzzUtil::GeneratorContext context;
34 
35   HttpHeaderBlock headers = HpackFuzzUtil::NextGeneratedHeaderSet(&context);
36 
37   // Headers were generated, and the generator context was expanded.
38   EXPECT_LT(0u, headers.size());
39   EXPECT_LT(0u, context.names.size());
40   EXPECT_LT(0u, context.values.size());
41 }
42 
43 // TODO(jgraettinger): A better test would mock a random generator and
44 // evaluate SampleExponential along fixed points of the [0,1] domain.
TEST(HpackFuzzUtilTest,SampleExponentialRegression)45 TEST(HpackFuzzUtilTest, SampleExponentialRegression) {
46   // TODO(jgraettinger): Upstream uses a seeded random generator here to pin
47   // the behavior of SampleExponential. Chromium's random generation utilities
48   // are strongly secure, but provide no way to seed the generator.
49   for (size_t i = 0; i != 100; ++i) {
50     EXPECT_GE(30u, HpackFuzzUtil::SampleExponential(10, 30));
51   }
52 }
53 
TEST(HpackFuzzUtilTest,ParsesSequenceOfHeaderBlocks)54 TEST(HpackFuzzUtilTest, ParsesSequenceOfHeaderBlocks) {
55   char fixture[] =
56       "\x00\x00\x00\x05"
57       "aaaaa"
58       "\x00\x00\x00\x04"
59       "bbbb"
60       "\x00\x00\x00\x03"
61       "ccc"
62       "\x00\x00\x00\x02"
63       "dd"
64       "\x00\x00\x00\x01"
65       "e"
66       "\x00\x00\x00\x00"
67       ""
68       "\x00\x00\x00\x03"
69       "fin";
70 
71   HpackFuzzUtil::Input input;
72   input.input.assign(fixture, std::size(fixture) - 1);
73 
74   std::string_view block;
75 
76   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
77   EXPECT_EQ("aaaaa", block);
78   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
79   EXPECT_EQ("bbbb", block);
80   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
81   EXPECT_EQ("ccc", block);
82   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
83   EXPECT_EQ("dd", block);
84   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
85   EXPECT_EQ("e", block);
86   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
87   EXPECT_EQ("", block);
88   EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
89   EXPECT_EQ("fin", block);
90   EXPECT_FALSE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
91 }
92 
TEST(HpackFuzzUtilTest,SerializedHeaderBlockPrefixes)93 TEST(HpackFuzzUtilTest, SerializedHeaderBlockPrefixes) {
94   EXPECT_EQ(std::string("\x00\x00\x00\x00", 4),
95             HpackFuzzUtil::HeaderBlockPrefix(0));
96   EXPECT_EQ(std::string("\x00\x00\x00\x05", 4),
97             HpackFuzzUtil::HeaderBlockPrefix(5));
98   EXPECT_EQ("\x4f\xb3\x0a\x91", HpackFuzzUtil::HeaderBlockPrefix(1337133713));
99 }
100 
TEST(HpackFuzzUtilTest,PassValidInputThroughAllStages)101 TEST(HpackFuzzUtilTest, PassValidInputThroughAllStages) {
102   // Example lifted from HpackDecoderTest.SectionD4RequestHuffmanExamples.
103   std::string input = net::HexDecode("828684418cf1e3c2e5f23a6ba0ab90f4ff");
104 
105   HpackFuzzUtil::FuzzerContext context;
106   HpackFuzzUtil::InitializeFuzzerContext(&context);
107 
108   EXPECT_TRUE(
109       HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(&context, input));
110 
111   HttpHeaderBlock expect;
112   expect[":method"] = "GET";
113   expect[":scheme"] = "http";
114   expect[":path"] = "/";
115   expect[":authority"] = "www.example.com";
116   EXPECT_EQ(expect, context.third_stage_handler->decoded_block());
117 }
118 
TEST(HpackFuzzUtilTest,ValidFuzzExamplesRegressionTest)119 TEST(HpackFuzzUtilTest, ValidFuzzExamplesRegressionTest) {
120   base::FilePath source_root;
121   ASSERT_TRUE(
122       base::PathService::Get(base::DIR_SRC_TEST_DATA_ROOT, &source_root));
123 
124   // Load the example fixtures versioned with the source tree.
125   HpackFuzzUtil::Input input;
126   ASSERT_TRUE(base::ReadFileToString(
127       source_root.Append(FILE_PATH_LITERAL("net"))
128           .Append(FILE_PATH_LITERAL("data"))
129           .Append(FILE_PATH_LITERAL("spdy_tests"))
130           .Append(FILE_PATH_LITERAL("examples_07.hpack")),
131       &input.input));
132 
133   HpackFuzzUtil::FuzzerContext context;
134   HpackFuzzUtil::InitializeFuzzerContext(&context);
135 
136   std::string_view block;
137   while (HpackFuzzUtil::NextHeaderBlock(&input, &block)) {
138     // As these are valid examples, all fuzz stages should succeed.
139     EXPECT_TRUE(
140         HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(&context, block));
141   }
142 }
143 
TEST(HpackFuzzUtilTest,FlipBitsMutatesBuffer)144 TEST(HpackFuzzUtilTest, FlipBitsMutatesBuffer) {
145   char buffer[] = "testbuffer1234567890";
146   std::string unmodified(buffer, std::size(buffer) - 1);
147 
148   EXPECT_EQ(unmodified, buffer);
149   HpackFuzzUtil::FlipBits(reinterpret_cast<uint8_t*>(buffer),
150                           std::size(buffer) - 1, 1);
151   EXPECT_NE(unmodified, buffer);
152 }
153 
154 }  // namespace spdy::test
155