15c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Copyright 2014 The Chromium Authors. All rights reserved.
25c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// Use of this source code is governed by a BSD-style license that can be
35c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// found in the LICENSE file.
45c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
55c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "net/spdy/fuzzing/hpack_fuzz_util.h"
65c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
75c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <map>
85c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/base_paths.h"
105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/files/file.h"
111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/path_service.h"
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/spdy/spdy_test_utils.h"
145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gmock/include/gmock/gmock.h"
155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "testing/gtest/include/gtest/gtest.h"
165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liunamespace net {
185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)namespace {
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing base::StringPiece;
225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing std::map;
235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuusing std::string;
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)using test::a2b_hex;
255c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, GeneratorContextInitialization) {
275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::GeneratorContext context;
285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::InitializeGeneratorContext(&context);
295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Context was seeded with initial name & value fixtures.
315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_LT(0u, context.names.size());
325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_LT(0u, context.values.size());
335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtil, GeneratorContextExpansion) {
365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::GeneratorContext context;
375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  map<string, string> headers = HpackFuzzUtil::NextGeneratedHeaderSet(&context);
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Headers were generated, and the generator context was expanded.
415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_LT(0u, headers.size());
425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_LT(0u, context.names.size());
435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_LT(0u, context.values.size());
445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// TODO(jgraettinger): A better test would mock a random generator and
475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu// evaluate SampleExponential along fixed points of the [0,1] domain.
485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, SampleExponentialRegression) {
495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // TODO(jgraettinger): Upstream uses a seeded random generator here to pin
505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // the behavior of SampleExponential. Chromium's random generation utilities
515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // are strongly secure, but provide no way to seed the generator.
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (size_t i = 0; i != 100; ++i) {
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EXPECT_GE(30u, HpackFuzzUtil::SampleExponential(10, 30));
545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, ParsesSequenceOfHeaderBlocks) {
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  char fixture[] =
595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x05""aaaaa"
605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x04""bbbb"
615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x03""ccc"
625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x02""dd"
635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x01""e"
645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x00"""
655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      "\x00\x00\x00\x03""fin";
665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::Input input;
685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  input.input.assign(fixture, arraysize(fixture) - 1);
695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  StringPiece block;
715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("aaaaa", block);
745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("bbbb", block);
765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("ccc", block);
785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("dd", block);
805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("e", block);
825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("", block);
845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_TRUE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ("fin", block);
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_FALSE(HpackFuzzUtil::NextHeaderBlock(&input, &block));
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, SerializedHeaderBlockPrefixes) {
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(string("\x00\x00\x00\x00", 4), HpackFuzzUtil::HeaderBlockPrefix(0));
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(string("\x00\x00\x00\x05", 4), HpackFuzzUtil::HeaderBlockPrefix(5));
925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(string("\x4f\xb3\x0a\x91", 4),
935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu            HpackFuzzUtil::HeaderBlockPrefix(1337133713));
945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, PassValidInputThroughAllStages) {
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  // Example lifted from HpackDecoderTest.SectionD4RequestHuffmanExamples.
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  string input = a2b_hex("828684418cf1e3c2e5f23a6ba0ab90f4"
99116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                         "ff");
1005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::FuzzerContext context;
1025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::InitializeFuzzerContext(&context);
1035c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_TRUE(
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(&context, input));
1065c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1075c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  std::map<string, string> expect;
1085c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  expect[":method"] = "GET";
1095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  expect[":scheme"] = "http";
1105c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  expect[":path"] = "/";
1115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  expect[":authority"] = "www.example.com";
1125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(expect, context.third_stage->decoded_block());
1135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, ValidFuzzExamplesRegressionTest) {
1165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  base::FilePath source_root;
1175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &source_root));
1185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Load the example fixtures versioned with the source tree.
1205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::Input input;
1215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_TRUE(base::ReadFileToString(
1225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      source_root.Append(FILE_PATH_LITERAL("net"))
1235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 .Append(FILE_PATH_LITERAL("data"))
1245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                 .Append(FILE_PATH_LITERAL("spdy_tests"))
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 .Append(FILE_PATH_LITERAL("examples_07.hpack")),
1265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      &input.input));
1275c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1285c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::FuzzerContext context;
1295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::InitializeFuzzerContext(&context);
1305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  StringPiece block;
1325c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  while (HpackFuzzUtil::NextHeaderBlock(&input, &block)) {
1335c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    // As these are valid examples, all fuzz stages should succeed.
1345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EXPECT_TRUE(HpackFuzzUtil::RunHeaderBlockThroughFuzzerStages(
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        &context, block));
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST(HpackFuzzUtilTest, FlipBitsMutatesBuffer) {
1405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  char buffer[] = "testbuffer1234567890";
1415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  string unmodified(buffer, arraysize(buffer) - 1);
1425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_EQ(unmodified, buffer);
1445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  HpackFuzzUtil::FlipBits(reinterpret_cast<uint8*>(buffer),
1455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          arraysize(buffer) - 1,
1465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                          1);
1475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  EXPECT_NE(unmodified, buffer);
1485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}  // namespace
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}  // namespace net
153