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