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