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