/work/obj-fuzz/dist/include/BufferReader.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifndef BUFFER_READER_H_ |
6 | | #define BUFFER_READER_H_ |
7 | | |
8 | | #include "mozilla/EndianUtils.h" |
9 | | #include "nscore.h" |
10 | | #include "nsTArray.h" |
11 | | #include "MediaData.h" |
12 | | #include "mozilla/Logging.h" |
13 | | #include "mozilla/Result.h" |
14 | | |
15 | | namespace mozilla { |
16 | | |
17 | | extern mozilla::LazyLogModule gMP4MetadataLog; |
18 | | |
19 | | class MOZ_RAII BufferReader |
20 | | { |
21 | | public: |
22 | | BufferReader() |
23 | | : mPtr(nullptr) |
24 | | , mRemaining(0) |
25 | | , mLength(0) |
26 | 0 | { |
27 | 0 | } |
28 | | BufferReader(const uint8_t* aData, size_t aSize) |
29 | | : mPtr(aData), mRemaining(aSize), mLength(aSize) |
30 | 0 | { |
31 | 0 | } |
32 | | template<size_t S> |
33 | | explicit BufferReader(const AutoTArray<uint8_t, S>& aData) |
34 | | : mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length()) |
35 | 0 | { |
36 | 0 | } |
37 | | explicit BufferReader(const nsTArray<uint8_t>& aData) |
38 | | : mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length()) |
39 | 0 | { |
40 | 0 | } |
41 | | explicit BufferReader(const mozilla::MediaByteBuffer* aData) |
42 | | : mPtr(aData->Elements()), mRemaining(aData->Length()), mLength(aData->Length()) |
43 | 0 | { |
44 | 0 | } |
45 | | |
46 | | void SetData(const nsTArray<uint8_t>& aData) |
47 | 0 | { |
48 | 0 | MOZ_ASSERT(!mPtr && !mRemaining); |
49 | 0 | mPtr = aData.Elements(); |
50 | 0 | mRemaining = aData.Length(); |
51 | 0 | mLength = mRemaining; |
52 | 0 | } |
53 | | |
54 | | ~BufferReader() |
55 | 0 | {} |
56 | | |
57 | | size_t Offset() const |
58 | 0 | { |
59 | 0 | return mLength - mRemaining; |
60 | 0 | } |
61 | | |
62 | 0 | size_t Remaining() const { return mRemaining; } |
63 | | |
64 | | mozilla::Result<uint8_t, nsresult> ReadU8() |
65 | 0 | { |
66 | 0 | auto ptr = Read(1); |
67 | 0 | if (!ptr) { |
68 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
69 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
70 | 0 | } |
71 | 0 | return *ptr; |
72 | 0 | } |
73 | | |
74 | | mozilla::Result<uint16_t, nsresult> ReadU16() |
75 | 0 | { |
76 | 0 | auto ptr = Read(2); |
77 | 0 | if (!ptr) { |
78 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
79 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
80 | 0 | } |
81 | 0 | return mozilla::BigEndian::readUint16(ptr); |
82 | 0 | } |
83 | | |
84 | | mozilla::Result<int16_t, nsresult> ReadLE16() |
85 | 0 | { |
86 | 0 | auto ptr = Read(2); |
87 | 0 | if (!ptr) { |
88 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
89 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
90 | 0 | } |
91 | 0 | return mozilla::LittleEndian::readInt16(ptr); |
92 | 0 | } |
93 | | |
94 | | mozilla::Result<uint32_t, nsresult> ReadU24() |
95 | 0 | { |
96 | 0 | auto ptr = Read(3); |
97 | 0 | if (!ptr) { |
98 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
99 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
100 | 0 | } |
101 | 0 | return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; |
102 | 0 | } |
103 | | |
104 | | mozilla::Result<int32_t, nsresult> Read24() |
105 | 0 | { |
106 | 0 | return ReadU24().map([] (uint32_t x) { return (int32_t)x; }); |
107 | 0 | } |
108 | | |
109 | | mozilla::Result<int32_t, nsresult> ReadLE24() |
110 | 0 | { |
111 | 0 | auto ptr = Read(3); |
112 | 0 | if (!ptr) { |
113 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
114 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
115 | 0 | } |
116 | 0 | int32_t result = int32_t(ptr[2] << 16 | ptr[1] << 8 | ptr[0]); |
117 | 0 | if (result & 0x00800000u) { |
118 | 0 | result -= 0x1000000; |
119 | 0 | } |
120 | 0 | return result; |
121 | 0 | } |
122 | | |
123 | | mozilla::Result<uint32_t, nsresult> ReadU32() |
124 | 0 | { |
125 | 0 | auto ptr = Read(4); |
126 | 0 | if (!ptr) { |
127 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
128 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
129 | 0 | } |
130 | 0 | return mozilla::BigEndian::readUint32(ptr); |
131 | 0 | } |
132 | | |
133 | | mozilla::Result<int32_t, nsresult> Read32() |
134 | 0 | { |
135 | 0 | auto ptr = Read(4); |
136 | 0 | if (!ptr) { |
137 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
138 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
139 | 0 | } |
140 | 0 | return mozilla::BigEndian::readInt32(ptr); |
141 | 0 | } |
142 | | |
143 | | mozilla::Result<uint64_t, nsresult> ReadU64() |
144 | 0 | { |
145 | 0 | auto ptr = Read(8); |
146 | 0 | if (!ptr) { |
147 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
148 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
149 | 0 | } |
150 | 0 | return mozilla::BigEndian::readUint64(ptr); |
151 | 0 | } |
152 | | |
153 | | mozilla::Result<int64_t, nsresult> Read64() |
154 | 0 | { |
155 | 0 | auto ptr = Read(8); |
156 | 0 | if (!ptr) { |
157 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
158 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
159 | 0 | } |
160 | 0 | return mozilla::BigEndian::readInt64(ptr); |
161 | 0 | } |
162 | | |
163 | | const uint8_t* Read(size_t aCount) |
164 | 0 | { |
165 | 0 | if (aCount > mRemaining) { |
166 | 0 | mRemaining = 0; |
167 | 0 | return nullptr; |
168 | 0 | } |
169 | 0 | mRemaining -= aCount; |
170 | 0 |
|
171 | 0 | const uint8_t* result = mPtr; |
172 | 0 | mPtr += aCount; |
173 | 0 |
|
174 | 0 | return result; |
175 | 0 | } |
176 | | |
177 | | const uint8_t* Rewind(size_t aCount) |
178 | 0 | { |
179 | 0 | MOZ_ASSERT(aCount <= Offset()); |
180 | 0 | size_t rewind = Offset(); |
181 | 0 | if (aCount < rewind) { |
182 | 0 | rewind = aCount; |
183 | 0 | } |
184 | 0 | mRemaining += rewind; |
185 | 0 | mPtr -= rewind; |
186 | 0 | return mPtr; |
187 | 0 | } |
188 | | |
189 | | mozilla::Result<uint8_t, nsresult> PeekU8() const |
190 | 0 | { |
191 | 0 | auto ptr = Peek(1); |
192 | 0 | if (!ptr) { |
193 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
194 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
195 | 0 | } |
196 | 0 | return *ptr; |
197 | 0 | } |
198 | | |
199 | | mozilla::Result<uint16_t, nsresult> PeekU16() const |
200 | 0 | { |
201 | 0 | auto ptr = Peek(2); |
202 | 0 | if (!ptr) { |
203 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
204 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
205 | 0 | } |
206 | 0 | return mozilla::BigEndian::readUint16(ptr); |
207 | 0 | } |
208 | | |
209 | | mozilla::Result<uint32_t, nsresult> PeekU24() const |
210 | 0 | { |
211 | 0 | auto ptr = Peek(3); |
212 | 0 | if (!ptr) { |
213 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
214 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
215 | 0 | } |
216 | 0 | return ptr[0] << 16 | ptr[1] << 8 | ptr[2]; |
217 | 0 | } |
218 | | |
219 | | mozilla::Result<int32_t, nsresult> Peek24() const |
220 | 0 | { |
221 | 0 | return PeekU24().map([] (uint32_t x) { return (int32_t)x; }); |
222 | 0 | } |
223 | | |
224 | | mozilla::Result<uint32_t, nsresult> PeekU32() |
225 | 0 | { |
226 | 0 | auto ptr = Peek(4); |
227 | 0 | if (!ptr) { |
228 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
229 | 0 | return mozilla::Err(NS_ERROR_FAILURE); |
230 | 0 | } |
231 | 0 | return mozilla::BigEndian::readUint32(ptr); |
232 | 0 | } |
233 | | |
234 | | const uint8_t* Peek(size_t aCount) const |
235 | 0 | { |
236 | 0 | if (aCount > mRemaining) { |
237 | 0 | return nullptr; |
238 | 0 | } |
239 | 0 | return mPtr; |
240 | 0 | } |
241 | | |
242 | | const uint8_t* Seek(size_t aOffset) |
243 | 0 | { |
244 | 0 | if (aOffset >= mLength) { |
245 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure, offset: %zu", __func__, aOffset)); |
246 | 0 | return nullptr; |
247 | 0 | } |
248 | 0 |
|
249 | 0 | mPtr = mPtr - Offset() + aOffset; |
250 | 0 | mRemaining = mLength - aOffset; |
251 | 0 | return mPtr; |
252 | 0 | } |
253 | | |
254 | | const uint8_t* Reset() |
255 | 0 | { |
256 | 0 | mPtr -= Offset(); |
257 | 0 | mRemaining = mLength; |
258 | 0 | return mPtr; |
259 | 0 | } |
260 | | |
261 | | uint32_t Align() const |
262 | 0 | { |
263 | 0 | return 4 - ((intptr_t)mPtr & 3); |
264 | 0 | } |
265 | | |
266 | 0 | template <typename T> bool CanReadType() const { return mRemaining >= sizeof(T); } |
267 | | |
268 | | template <typename T> T ReadType() |
269 | 0 | { |
270 | 0 | auto ptr = Read(sizeof(T)); |
271 | 0 | if (!ptr) { |
272 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
273 | 0 | return 0; |
274 | 0 | } |
275 | 0 | return *reinterpret_cast<const T*>(ptr); |
276 | 0 | } |
277 | | |
278 | | template <typename T> |
279 | | MOZ_MUST_USE bool ReadArray(nsTArray<T>& aDest, size_t aLength) |
280 | 0 | { |
281 | 0 | auto ptr = Read(aLength * sizeof(T)); |
282 | 0 | if (!ptr) { |
283 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
284 | 0 | return false; |
285 | 0 | } |
286 | 0 |
|
287 | 0 | aDest.Clear(); |
288 | 0 | aDest.AppendElements(reinterpret_cast<const T*>(ptr), aLength); |
289 | 0 | return true; |
290 | 0 | } |
291 | | |
292 | | template <typename T> |
293 | | MOZ_MUST_USE bool ReadArray(FallibleTArray<T>& aDest, size_t aLength) |
294 | 0 | { |
295 | 0 | auto ptr = Read(aLength * sizeof(T)); |
296 | 0 | if (!ptr) { |
297 | 0 | MOZ_LOG(gMP4MetadataLog, mozilla::LogLevel::Error, ("%s: failure", __func__)); |
298 | 0 | return false; |
299 | 0 | } |
300 | 0 |
|
301 | 0 | aDest.Clear(); |
302 | 0 | if (!aDest.SetCapacity(aLength, mozilla::fallible)) { |
303 | 0 | return false; |
304 | 0 | } |
305 | 0 | MOZ_ALWAYS_TRUE(aDest.AppendElements(reinterpret_cast<const T*>(ptr), |
306 | 0 | aLength, |
307 | 0 | mozilla::fallible)); |
308 | 0 | return true; |
309 | 0 | } |
310 | | |
311 | | private: |
312 | | const uint8_t* mPtr; |
313 | | size_t mRemaining; |
314 | | size_t mLength; |
315 | | }; |
316 | | |
317 | | } // namespace mozilla |
318 | | |
319 | | #endif |