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