• 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 "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