RawSpeed
fast raw decoding library
Loading...
Searching...
No Matches
BitVacuumerRoundtrip.cpp
Go to the documentation of this file.
1/*
2 RawSpeed - RAW file decoder.
3
4 Copyright (C) 2024 Roman Lebedev
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public
17 License along with this library; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19*/
20
21#include "rawspeedconfig.h"
22#include "adt/Bit.h"
23#include "adt/Array1DRef.h"
24#include "adt/Casts.h"
25#include "adt/Invariant.h"
39#include "io/Buffer.h"
40#include "io/ByteStream.h"
41#include "io/Endianness.h"
42#include <cassert>
43#include <cstdint>
44#include <cstdio>
45#include <iterator>
46#include <utility>
47#include <vector>
48
49extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size);
50
51namespace rawspeed {
52namespace {
53
54struct BitstreamFlavorLSB;
55struct BitstreamFlavorMSB;
56struct BitstreamFlavorMSB16;
57struct BitstreamFlavorMSB32;
58struct BitstreamFlavorJPEG;
59
60template <typename T> struct BitStreamRoundtripTypes final {};
61
62template <> struct BitStreamRoundtripTypes<BitstreamFlavorLSB> final {
64
65 template <typename OutputIterator>
67};
68
69template <> struct BitStreamRoundtripTypes<BitstreamFlavorMSB> final {
71
72 template <typename OutputIterator>
74};
75
76template <> struct BitStreamRoundtripTypes<BitstreamFlavorMSB16> final {
78
79 template <typename OutputIterator>
81};
82
83template <> struct BitStreamRoundtripTypes<BitstreamFlavorMSB32> final {
85
86 template <typename OutputIterator>
88};
89
90template <> struct BitStreamRoundtripTypes<BitstreamFlavorJPEG> final {
92
93 template <typename OutputIterator>
95};
96
97class InputWrapper final {
100
101public:
102 InputWrapper() = delete;
103
104 InputWrapper(const InputWrapper&) = delete;
108
109 InputWrapper(ByteStream bitLengths_, ByteStream bitVals_)
110 : bitLengths(bitLengths_), bitVals(bitVals_) {
111 invariant(size() >= 0);
112 }
113
114 [[nodiscard]] int size() const RAWSPEED_READNONE {
115 invariant(bitVals.getSize() == 4 * bitLengths.getSize());
116 return bitLengths.getSize();
117 }
118
119 [[nodiscard]] std::pair<uint32_t, int>
120 operator[](int i) const RAWSPEED_READNONE {
121 invariant(i >= 0);
122 invariant(i < size());
123
124 auto len = implicit_cast<int>(bitLengths.peekByte(i) % 33); // 0-32 bits
125 uint32_t val = extractLowBitsSafe(bitVals.peekU32(i), len);
126
127 return {val, len};
128 }
129};
130
131template <typename flavor>
132std::vector<uint8_t> produceBitstream(const InputWrapper& w) {
133 std::vector<uint8_t> bitstream;
134
135 {
136 auto bsInserter = PartitioningOutputIterator(std::back_inserter(bitstream));
137 using BitVacuumer = typename BitStreamRoundtripTypes<
138 flavor>::template vacuumer<decltype(bsInserter)>;
139 auto bv = BitVacuumer(bsInserter);
140
141 for (int i = 0; i != w.size(); ++i) {
142 const auto [val, len] = w[i];
143 bv.put(val, len);
144 }
145 }
146
148 if (constexpr int MinSize = BitStreamerTraits<BitStreamer>::MaxProcessBytes;
149 bitstream.size() < MinSize)
150 bitstream.resize(MinSize, uint8_t(0));
151
152 return bitstream;
153}
154
155template <typename flavor>
158 auto bs = BitStreamer(input);
159 for (int i = 0; i != w.size(); ++i) {
160 const auto [expectedVal, len] = w[i];
161 bs.fill(32);
162 const auto actualVal = len != 0 ? bs.getBitsNoFill(len) : 0;
163 invariant(actualVal == expectedVal);
164 }
165}
166
167template <typename flavor> void checkFlavourImpl(const InputWrapper& w) {
168 const std::vector<uint8_t> bitstream = produceBitstream<flavor>(w);
169 const auto input =
170 Array1DRef(bitstream.data(), implicit_cast<int>(bitstream.size()));
171 reparseBitstream<flavor>(input, w);
172}
173
174template <typename flavor> void checkFlavour(const InputWrapper& w) {
175 try {
177 } catch (const RawspeedException&) {
178 assert(false && "Unexpected exception in `checkFlavourImpl()`.");
179 }
180}
181
182extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) {
183 assert(Data);
184
185 try {
186 const Buffer b(Data, implicit_cast<Buffer::size_type>(Size));
187 const DataBuffer db(b, Endianness::little);
188 ByteStream bs(db);
189
190 const auto flavor = bs.getByte();
191
192 const auto numValues = bs.getU32();
193 const auto bitLengths = bs.getStream(numValues, sizeof(uint8_t));
194 const auto bitVals = bs.getStream(numValues, sizeof(uint32_t));
195 const InputWrapper w(bitLengths, bitVals);
196
197 // Which flavor?
198 switch (flavor) {
199 case 0:
201 return 0;
202 case 1:
204 return 0;
205 case 2:
207 return 0;
208 case 3:
210 return 0;
211 case 4:
213 return 0;
214 default:
215 ThrowRSE("Unknown flavor");
216 }
217 } catch (const RawspeedException&) {
218 return 0;
219 }
220
221 __builtin_unreachable();
222}
223
224} // namespace
225
226} // namespace rawspeed
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Definition Dual.cpp:161
#define invariant(expr)
Definition Invariant.h:27
#define ThrowRSE(...)
assert(dim.area() >=area)
ByteStream getStream(size_type size_)
Definition ByteStream.h:119
std::pair< uint32_t, int > operator[](int i) const RAWSPEED_READNONE
std::vector< uint8_t > produceBitstream(const InputWrapper &w)
void reparseBitstream(Array1DRef< const uint8_t > input, const InputWrapper &w)
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32
constexpr RAWSPEED_READNONE T extractLowBitsSafe(T value, unsigned nBits)
Definition Bit.h:110
int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size)
Array1DRef(T *data_, int numElts_) -> Array1DRef< T >
PartitioningOutputIterator(T) -> PartitioningOutputIterator< T >
constexpr RAWSPEED_READNONE Ttgt implicit_cast(Tsrc value)
Definition Casts.h:32