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