1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/core/SkBitmap.h"
9#include "include/core/SkData.h"
10#include "include/core/SkImage.h"
11#include "include/core/SkImageGenerator.h"
12#include "include/core/SkStream.h"
13#include "include/core/SkTypeface.h"
14#include "src/core/SkAutoMalloc.h"
15#include "src/core/SkMathPriv.h"
16#include "src/core/SkMatrixPriv.h"
17#include "src/core/SkReadBuffer.h"
18#include "src/core/SkSafeMath.h"
19
20#ifndef SK_DISABLE_READBUFFER
21
22namespace {
23 // This generator intentionally should always fail on all attempts to get its pixels,
24 // simulating a bad or empty codec stream.
25 class EmptyImageGenerator final : public SkImageGenerator {
26 public:
27 EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { }
28
29 private:
30 typedef SkImageGenerator INHERITED;
31 };
32
33 static sk_sp<SkImage> MakeEmptyImage(int width, int height) {
34 return SkImage::MakeFromGenerator(
35 std::make_unique<EmptyImageGenerator>(SkImageInfo::MakeN32Premul(width, height)));
36 }
37
38} // anonymous namespace
39
40
41SkReadBuffer::SkReadBuffer() {
42 fVersion = 0;
43
44 fTFArray = nullptr;
45 fTFCount = 0;
46
47 fFactoryArray = nullptr;
48 fFactoryCount = 0;
49}
50
51SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
52 fVersion = 0;
53 this->setMemory(data, size);
54
55 fTFArray = nullptr;
56 fTFCount = 0;
57
58 fFactoryArray = nullptr;
59 fFactoryCount = 0;
60}
61
62void SkReadBuffer::setMemory(const void* data, size_t size) {
63 this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
64 if (!fError) {
65 fReader.setMemory(data, size);
66 }
67}
68void SkReadBuffer::setInvalid() {
69 if (!fError) {
70 // When an error is found, send the read cursor to the end of the stream
71 fReader.skip(fReader.available());
72 fError = true;
73 }
74}
75
76const void* SkReadBuffer::skip(size_t size) {
77 size_t inc = SkAlign4(size);
78 this->validate(inc >= size);
79 const void* addr = fReader.peek();
80 this->validate(IsPtrAlign4(addr) && fReader.isAvailable(inc));
81 if (fError) {
82 return nullptr;
83 }
84
85 fReader.skip(size);
86 return addr;
87}
88
89const void* SkReadBuffer::skip(size_t count, size_t size) {
90 return this->skip(SkSafeMath::Mul(count, size));
91}
92
93void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
94 fProcs = procs;
95}
96
97bool SkReadBuffer::readBool() {
98 uint32_t value = this->readUInt();
99 // Boolean value should be either 0 or 1
100 this->validate(!(value & ~1));
101 return value != 0;
102}
103
104SkColor SkReadBuffer::readColor() {
105 return this->readUInt();
106}
107
108int32_t SkReadBuffer::readInt() {
109 const size_t inc = sizeof(int32_t);
110 this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
111 return fError ? 0 : fReader.readInt();
112}
113
114SkScalar SkReadBuffer::readScalar() {
115 const size_t inc = sizeof(SkScalar);
116 this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
117 return fError ? 0 : fReader.readScalar();
118}
119
120uint32_t SkReadBuffer::readUInt() {
121 return this->readInt();
122}
123
124int32_t SkReadBuffer::read32() {
125 return this->readInt();
126}
127
128uint8_t SkReadBuffer::peekByte() {
129 if (fReader.available() <= 0) {
130 fError = true;
131 return 0;
132 }
133 return *((uint8_t*) fReader.peek());
134}
135
136bool SkReadBuffer::readPad32(void* buffer, size_t bytes) {
137 if (const void* src = this->skip(bytes)) {
138 // buffer might be null if bytes is zero (see SkAutoMalloc), hence we call
139 // the careful version of memcpy.
140 sk_careful_memcpy(buffer, src, bytes);
141 return true;
142 }
143 return false;
144}
145
146const char* SkReadBuffer::readString(size_t* len) {
147 *len = this->readUInt();
148
149 // The string is len characters and a terminating \0.
150 const char* c_str = this->skipT<char>(*len+1);
151
152 if (this->validate(c_str && c_str[*len] == '\0')) {
153 return c_str;
154 }
155 return nullptr;
156}
157
158void SkReadBuffer::readString(SkString* string) {
159 size_t len;
160 if (const char* c_str = this->readString(&len)) {
161 string->set(c_str, len);
162 return;
163 }
164 string->reset();
165}
166
167void SkReadBuffer::readColor4f(SkColor4f* color) {
168 if (!this->readPad32(color, sizeof(SkColor4f))) {
169 *color = {0, 0, 0, 0};
170 }
171}
172
173void SkReadBuffer::readPoint(SkPoint* point) {
174 point->fX = this->readScalar();
175 point->fY = this->readScalar();
176}
177
178void SkReadBuffer::readPoint3(SkPoint3* point) {
179 this->readPad32(point, sizeof(SkPoint3));
180}
181
182void SkReadBuffer::readMatrix(SkMatrix* matrix) {
183 size_t size = 0;
184 if (this->isValid()) {
185 size = SkMatrixPriv::ReadFromMemory(matrix, fReader.peek(), fReader.available());
186 (void)this->validate((SkAlign4(size) == size) && (0 != size));
187 }
188 if (!this->isValid()) {
189 matrix->reset();
190 }
191 (void)this->skip(size);
192}
193
194void SkReadBuffer::readIRect(SkIRect* rect) {
195 if (!this->readPad32(rect, sizeof(SkIRect))) {
196 rect->setEmpty();
197 }
198}
199
200void SkReadBuffer::readRect(SkRect* rect) {
201 if (!this->readPad32(rect, sizeof(SkRect))) {
202 rect->setEmpty();
203 }
204}
205
206void SkReadBuffer::readRRect(SkRRect* rrect) {
207 if (!this->validate(fReader.readRRect(rrect))) {
208 rrect->setEmpty();
209 }
210}
211
212void SkReadBuffer::readRegion(SkRegion* region) {
213 size_t size = 0;
214 if (!fError) {
215 size = region->readFromMemory(fReader.peek(), fReader.available());
216 if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
217 region->setEmpty();
218 }
219 }
220 (void)this->skip(size);
221}
222
223void SkReadBuffer::readPath(SkPath* path) {
224 size_t size = 0;
225 if (!fError) {
226 size = path->readFromMemory(fReader.peek(), fReader.available());
227 if (!this->validate((SkAlign4(size) == size) && (0 != size))) {
228 path->reset();
229 }
230 }
231 (void)this->skip(size);
232}
233
234bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
235 const uint32_t count = this->readUInt();
236 return this->validate(size == count) &&
237 this->readPad32(value, SkSafeMath::Mul(size, elementSize));
238}
239
240bool SkReadBuffer::readByteArray(void* value, size_t size) {
241 return this->readArray(value, size, sizeof(uint8_t));
242}
243
244bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
245 return this->readArray(colors, size, sizeof(SkColor));
246}
247
248bool SkReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
249 return this->readArray(colors, size, sizeof(SkColor4f));
250}
251
252bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
253 return this->readArray(values, size, sizeof(int32_t));
254}
255
256bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) {
257 return this->readArray(points, size, sizeof(SkPoint));
258}
259
260bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
261 return this->readArray(values, size, sizeof(SkScalar));
262}
263
264sk_sp<SkData> SkReadBuffer::readByteArrayAsData() {
265 size_t numBytes = this->getArrayCount();
266 if (!this->validate(fReader.isAvailable(numBytes))) {
267 return nullptr;
268 }
269
270 SkAutoMalloc buffer(numBytes);
271 if (!this->readByteArray(buffer.get(), numBytes)) {
272 return nullptr;
273 }
274 return SkData::MakeFromMalloc(buffer.release(), numBytes);
275}
276
277uint32_t SkReadBuffer::getArrayCount() {
278 const size_t inc = sizeof(uint32_t);
279 fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
280 return fError ? 0 : *(uint32_t*)fReader.peek();
281}
282
283/* Format:
284 * (subset) width, height
285 * (subset) origin x, y
286 * size (31bits)
287 * data [ encoded, with raw width/height ]
288 */
289sk_sp<SkImage> SkReadBuffer::readImage() {
290 SkIRect bounds;
291 if (this->isVersionLT(SkPicturePriv::kStoreImageBounds_Version)) {
292 bounds.fLeft = bounds.fTop = 0;
293 bounds.fRight = this->read32();
294 bounds.fBottom = this->read32();
295 } else {
296 this->readIRect(&bounds);
297 }
298 const int width = bounds.width();
299 const int height = bounds.height();
300 if (width <= 0 || height <= 0) { // SkImage never has a zero dimension
301 this->validate(false);
302 return nullptr;
303 }
304
305 int32_t size = this->read32();
306 if (size == SK_NaN32) {
307 // 0x80000000 is never valid, since it cannot be passed to abs().
308 this->validate(false);
309 return nullptr;
310 }
311 if (size == 0) {
312 // The image could not be encoded at serialization time - return an empty placeholder.
313 return MakeEmptyImage(width, height);
314 }
315
316 // we used to negate the size for "custom" encoded images -- ignore that signal (Dec-2017)
317 size = SkAbs32(size);
318 if (size == 1) {
319 // legacy check (we stopped writing this for "raw" images Nov-2017)
320 this->validate(false);
321 return nullptr;
322 }
323
324 // Preflight check to make sure there's enough stuff in the buffer before
325 // we allocate the memory. This helps the fuzzer avoid OOM when it creates
326 // bad/corrupt input.
327 if (!this->validateCanReadN<uint8_t>(size)) {
328 return nullptr;
329 }
330
331 sk_sp<SkData> data = SkData::MakeUninitialized(size);
332 if (!this->readPad32(data->writable_data(), size)) {
333 this->validate(false);
334 return nullptr;
335 }
336 if (this->isVersionLT(SkPicturePriv::kDontNegateImageSize_Version)) {
337 (void)this->read32(); // originX
338 (void)this->read32(); // originY
339 }
340
341 sk_sp<SkImage> image;
342 if (fProcs.fImageProc) {
343 image = fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx);
344 }
345 if (!image) {
346 image = SkImage::MakeFromEncoded(std::move(data));
347 }
348 if (image) {
349 if (bounds.x() || bounds.y() || width < image->width() || height < image->height()) {
350 image = image->makeSubset(bounds);
351 }
352 }
353 // Question: are we correct to return an "empty" image instead of nullptr, if the decoder
354 // failed for some reason?
355 return image ? image : MakeEmptyImage(width, height);
356}
357
358sk_sp<SkTypeface> SkReadBuffer::readTypeface() {
359 // Read 32 bits (signed)
360 // 0 -- return null (default font)
361 // >0 -- index
362 // <0 -- custom (serial procs) : negative size in bytes
363
364 int32_t index = this->read32();
365 if (index == 0) {
366 return nullptr;
367 } else if (index > 0) {
368 if (!this->validate(index <= fTFCount)) {
369 return nullptr;
370 }
371 return fTFArray[index - 1];
372 } else { // custom
373 size_t size = sk_negate_to_size_t(index);
374 const void* data = this->skip(size);
375 if (!this->validate(data != nullptr && fProcs.fTypefaceProc)) {
376 return nullptr;
377 }
378 return fProcs.fTypefaceProc(data, size, fProcs.fTypefaceCtx);
379 }
380}
381
382SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
383 SkFlattenable::Factory factory = nullptr;
384
385 if (fFactoryCount > 0) {
386 int32_t index = this->read32();
387 if (0 == index || !this->isValid()) {
388 return nullptr; // writer failed to give us the flattenable
389 }
390 index -= 1; // we stored the index-base-1
391 if ((unsigned)index >= (unsigned)fFactoryCount) {
392 this->validate(false);
393 return nullptr;
394 }
395 factory = fFactoryArray[index];
396 } else {
397 if (this->peekByte() != 0) {
398 // If the first byte is non-zero, the flattenable is specified by a string.
399 size_t ignored_length;
400 if (const char* name = this->readString(&ignored_length)) {
401 factory = SkFlattenable::NameToFactory(name);
402 fFlattenableDict.set(fFlattenableDict.count() + 1, factory);
403 }
404 } else {
405 // Read the index. We are guaranteed that the first byte
406 // is zeroed, so we must shift down a byte.
407 uint32_t index = this->readUInt() >> 8;
408 if (index == 0) {
409 return nullptr; // writer failed to give us the flattenable
410 }
411
412 if (SkFlattenable::Factory* found = fFlattenableDict.find(index)) {
413 factory = *found;
414 }
415 }
416
417 if (!this->validate(factory != nullptr)) {
418 return nullptr;
419 }
420 }
421
422 // if we get here, factory may still be null, but if that is the case, the
423 // failure was ours, not the writer.
424 sk_sp<SkFlattenable> obj;
425 uint32_t sizeRecorded = this->read32();
426 if (factory) {
427 size_t offset = fReader.offset();
428 obj = (*factory)(*this);
429 // check that we read the amount we expected
430 size_t sizeRead = fReader.offset() - offset;
431 if (sizeRecorded != sizeRead) {
432 this->validate(false);
433 return nullptr;
434 }
435 if (obj && obj->getFlattenableType() != ft) {
436 this->validate(false);
437 return nullptr;
438 }
439 } else {
440 // we must skip the remaining data
441 fReader.skip(sizeRecorded);
442 }
443 if (!this->isValid()) {
444 return nullptr;
445 }
446 return obj.release();
447}
448
449///////////////////////////////////////////////////////////////////////////////////////////////////
450
451int32_t SkReadBuffer::checkInt(int32_t min, int32_t max) {
452 SkASSERT(min <= max);
453 int32_t value = this->read32();
454 if (value < min || value > max) {
455 this->validate(false);
456 value = min;
457 }
458 return value;
459}
460
461SkFilterQuality SkReadBuffer::checkFilterQuality() {
462 return this->checkRange<SkFilterQuality>(kNone_SkFilterQuality, kLast_SkFilterQuality);
463}
464
465#endif // #ifndef SK_DISABLE_READBUFFER
466