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