• 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/include/puffin/common.h"
11 #include "puffin/src/include/puffin/puffpatch.h"
12 #include "puffin/src/memory_stream.h"
13 
14 using puffin::BitExtent;
15 using puffin::Buffer;
16 using puffin::ByteExtent;
17 using puffin::MemoryStream;
18 using std::vector;
19 
20 namespace puffin {
21 // From puffpatch.cc
22 bool DecodePatch(const uint8_t* patch,
23                  size_t patch_length,
24                  size_t* bsdiff_patch_offset,
25                  size_t* bsdiff_patch_size,
26                  vector<BitExtent>* src_deflates,
27                  vector<BitExtent>* dst_deflates,
28                  vector<ByteExtent>* src_puffs,
29                  vector<ByteExtent>* dst_puffs,
30                  uint64_t* src_puff_size,
31                  uint64_t* dst_puff_size);
32 }  // namespace puffin
33 
34 namespace {
35 template <typename T>
TestExtentsArrayForFuzzer(const vector<T> & extents)36 bool TestExtentsArrayForFuzzer(const vector<T>& extents) {
37   const size_t kMaxArraySize = 100;
38   if (extents.size() > kMaxArraySize) {
39     return false;
40   }
41 
42   const size_t kMaxBufferSize = 1024;  // 1Kb
43   for (const auto& ext : extents) {
44     if (ext.length > kMaxBufferSize) {
45       return false;
46     }
47   }
48   return true;
49 }
50 
FuzzPuffPatch(const uint8_t * data,size_t size)51 void FuzzPuffPatch(const uint8_t* data, size_t size) {
52   // First decode the header and make sure the deflate and puff buffer sizes do
53   // not excede some limits. This is to prevent the fuzzer complain with
54   // out-of-memory errors when the fuzz data is in such a way that causes a huge
55   // random size memory be allocated.
56 
57   size_t bsdiff_patch_offset;
58   size_t bsdiff_patch_size = 0;
59   vector<BitExtent> src_deflates, dst_deflates;
60   vector<ByteExtent> src_puffs, dst_puffs;
61   uint64_t src_puff_size, dst_puff_size;
62   if (DecodePatch(data, size, &bsdiff_patch_offset, &bsdiff_patch_size,
63                   &src_deflates, &dst_deflates, &src_puffs, &dst_puffs,
64                   &src_puff_size, &dst_puff_size) &&
65       TestExtentsArrayForFuzzer(src_deflates) &&
66       TestExtentsArrayForFuzzer(dst_deflates) &&
67       TestExtentsArrayForFuzzer(src_puffs) &&
68       TestExtentsArrayForFuzzer(dst_puffs)) {
69     const size_t kBufferSize = 1000;
70     if ((!src_deflates.empty() &&
71          kBufferSize <
72              src_deflates.back().offset + src_deflates.back().length) ||
73         (!dst_deflates.empty() &&
74          kBufferSize <
75              dst_deflates.back().offset + dst_deflates.back().length)) {
76       return;
77     }
78 
79     Buffer src_buffer(kBufferSize);
80     Buffer dst_buffer(kBufferSize);
81     auto src = MemoryStream::CreateForRead(src_buffer);
82     auto dst = MemoryStream::CreateForWrite(&dst_buffer);
83     puffin::PuffPatch(std::move(src), std::move(dst), data, size, kBufferSize);
84   }
85 }
86 
87 class Environment {
88  public:
Environment()89   Environment() {
90     // To turn off the logging.
91     logging::SetMinLogLevel(logging::LOG_FATAL);
92 
93     // To turn off logging for bsdiff library.
94     std::cerr.setstate(std::ios_base::failbit);
95   }
96 };
97 
98 }  // namespace
99 
LLVMFuzzerTestOneInput(const uint8_t * data,size_t size)100 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
101   static Environment env;
102 
103   FuzzPuffPatch(data, size);
104   return 0;
105 }
106