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