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