• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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