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