• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2018 The Chromium OS Authors. All rights reserved.
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 <vector>
6 
7 #include "base/logging.h"
8 #include "brillo/test_helpers.h"
9 
10 #include "puffin/src/bit_reader.h"
11 #include "puffin/src/bit_writer.h"
12 #include "puffin/src/include/puffin/common.h"
13 #include "puffin/src/include/puffin/huffer.h"
14 #include "puffin/src/include/puffin/puffer.h"
15 #include "puffin/src/include/puffin/puffpatch.h"
16 #include "puffin/src/memory_stream.h"
17 #include "puffin/src/puff_reader.h"
18 #include "puffin/src/puff_writer.h"
19 
20 using puffin::BitExtent;
21 using puffin::Buffer;
22 using puffin::BufferBitReader;
23 using puffin::BufferBitWriter;
24 using puffin::BufferPuffReader;
25 using puffin::BufferPuffWriter;
26 using puffin::ByteExtent;
27 using puffin::Huffer;
28 using puffin::MemoryStream;
29 using puffin::Puffer;
30 using puffin::UniqueStreamPtr;
31 using std::vector;
32 
33 namespace puffin {
34 // From puffpatch.cc
35 bool DecodePatch(const uint8_t* patch,
36                  size_t patch_length,
37                  size_t* bsdiff_patch_offset,
38                  size_t* bsdiff_patch_size,
39                  vector<BitExtent>* src_deflates,
40                  vector<BitExtent>* dst_deflates,
41                  vector<ByteExtent>* src_puffs,
42                  vector<ByteExtent>* dst_puffs,
43                  uint64_t* src_puff_size,
44                  uint64_t* dst_puff_size);
45 }  // namespace puffin
46 
47 namespace {
FuzzPuff(const uint8_t * data,size_t size)48 void FuzzPuff(const uint8_t* data, size_t size) {
49   BufferBitReader bit_reader(data, size);
50   Buffer puff_buffer(size * 2);
51   BufferPuffWriter puff_writer(puff_buffer.data(), puff_buffer.size());
52   vector<BitExtent> bit_extents;
53   Puffer puffer;
54   puffer.PuffDeflate(&bit_reader, &puff_writer, &bit_extents);
55 }
56 
FuzzHuff(const uint8_t * data,size_t size)57 void FuzzHuff(const uint8_t* data, size_t size) {
58   BufferPuffReader puff_reader(data, size);
59   Buffer deflate_buffer(size);
60   BufferBitWriter bit_writer(deflate_buffer.data(), deflate_buffer.size());
61   Huffer huffer;
62   huffer.HuffDeflate(&puff_reader, &bit_writer);
63 }
64 
65 template <typename T>
TestExtentsArrayForFuzzer(const vector<T> & extents)66 bool TestExtentsArrayForFuzzer(const vector<T>& extents) {
67   const size_t kMaxArraySize = 100;
68   if (extents.size() > kMaxArraySize) {
69     return false;
70   }
71 
72   const size_t kMaxBufferSize = 1024;  // 1Kb
73   for (const auto& ext : extents) {
74     if (ext.length > kMaxBufferSize) {
75       return false;
76     }
77   }
78   return true;
79 }
80 
FuzzPuffPatch(const uint8_t * data,size_t size)81 void FuzzPuffPatch(const uint8_t* data, size_t size) {
82   // First decode the header and make sure the deflate and puff buffer sizes do
83   // not excede some limits. This is to prevent the fuzzer complain with
84   // out-of-memory errors when the fuzz data is in such a way that causes a huge
85   // random size memory be allocated.
86 
87   size_t bsdiff_patch_offset;
88   size_t bsdiff_patch_size = 0;
89   vector<BitExtent> src_deflates, dst_deflates;
90   vector<ByteExtent> src_puffs, dst_puffs;
91   uint64_t src_puff_size, dst_puff_size;
92   if (DecodePatch(data, size, &bsdiff_patch_offset, &bsdiff_patch_size,
93                   &src_deflates, &dst_deflates, &src_puffs, &dst_puffs,
94                   &src_puff_size, &dst_puff_size) &&
95       TestExtentsArrayForFuzzer(src_deflates) &&
96       TestExtentsArrayForFuzzer(dst_deflates) &&
97       TestExtentsArrayForFuzzer(src_puffs) &&
98       TestExtentsArrayForFuzzer(dst_puffs)) {
99     const size_t kBufferSize = 1000;
100     if ((!src_deflates.empty() &&
101          kBufferSize <
102              src_deflates.back().offset + src_deflates.back().length) ||
103         (!dst_deflates.empty() &&
104          kBufferSize <
105              dst_deflates.back().offset + dst_deflates.back().length)) {
106       return;
107     }
108 
109     Buffer src_buffer(kBufferSize);
110     Buffer dst_buffer(kBufferSize);
111     auto src = MemoryStream::CreateForRead(src_buffer);
112     auto dst = MemoryStream::CreateForWrite(&dst_buffer);
113     puffin::PuffPatch(std::move(src), std::move(dst), data, size, kBufferSize);
114   }
115 }
116 
117 struct Environment {
Environment__anon03010de20111::Environment118   Environment() {
119     // To turn off the logging.
120     logging::SetMinLogLevel(logging::LOG_FATAL);
121 
122     // To turn off logging for bsdiff library.
123     std::cerr.setstate(std::ios_base::failbit);
124   }
125 };
126 Environment* env = new Environment();
127 
128 }  // namespace
129 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)130 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
131   FuzzPuff(data, size);
132   FuzzHuff(data, size);
133   FuzzPuffPatch(data, size);
134   return 0;
135 }
136