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