• 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 #include "src/core/SkMipmap.h"
318 
319 // If we see a corrupt stream, we return null (fail). If we just fail trying to decode
320 // the image, we don't fail, but return a 1x1 empty image.
readImage()321 sk_sp<SkImage> SkReadBuffer::readImage() {
322     uint32_t flags = this->read32();
323 
324     sk_sp<SkImage> image;
325     {
326         sk_sp<SkData> data = this->readByteArrayAsData();
327         if (!data) {
328             this->validate(false);
329             return nullptr;
330         }
331         if (fProcs.fImageProc) {
332             image = fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx);
333         }
334         if (!image) {
335             image = SkImage::MakeFromEncoded(std::move(data));
336         }
337     }
338 
339     if (flags & SkWriteBufferImageFlags::kHasSubsetRect) {
340         SkIRect subset;
341         this->readIRect(&subset);
342         if (image) {
343             image = image->makeSubset(subset);
344         }
345     }
346 
347     if (flags & SkWriteBufferImageFlags::kHasMipmap) {
348         sk_sp<SkData> data = this->readByteArrayAsData();
349         if (!data) {
350             this->validate(false);
351             return nullptr;
352         }
353         if (image) {
354             SkMipmapBuilder builder(image->imageInfo());
355             if (SkMipmap::Deserialize(&builder, data->data(), data->size())) {
356                 // TODO: need to make lazy images support mips
357                 if (auto ri = image->makeRasterImage()) {
358                     image = ri;
359                 }
360                 image = builder.attachTo(image);
361                 SkASSERT(image);    // withMipmaps should never return null
362             }
363         }
364     }
365     return image ? image : MakeEmptyImage(1, 1);
366 }
367 
readTypeface()368 sk_sp<SkTypeface> SkReadBuffer::readTypeface() {
369     // Read 32 bits (signed)
370     //   0 -- return null (default font)
371     //  >0 -- index
372     //  <0 -- custom (serial procs) : negative size in bytes
373 
374     int32_t index = this->read32();
375     if (index == 0) {
376         return nullptr;
377     } else if (index > 0) {
378         if (!this->validate(index <= fTFCount)) {
379             return nullptr;
380         }
381         return fTFArray[index - 1];
382     } else {    // custom
383         size_t size = sk_negate_to_size_t(index);
384         const void* data = this->skip(size);
385         if (!this->validate(data != nullptr && fProcs.fTypefaceProc)) {
386             return nullptr;
387         }
388         return fProcs.fTypefaceProc(data, size, fProcs.fTypefaceCtx);
389     }
390 }
391 
readFlattenable(SkFlattenable::Type ft)392 SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
393     SkFlattenable::Factory factory = nullptr;
394 
395     if (fFactoryCount > 0) {
396         int32_t index = this->read32();
397         if (0 == index || !this->isValid()) {
398             return nullptr; // writer failed to give us the flattenable
399         }
400         index -= 1;     // we stored the index-base-1
401         if ((unsigned)index >= (unsigned)fFactoryCount) {
402             this->validate(false);
403             return nullptr;
404         }
405         factory = fFactoryArray[index];
406     } else {
407         if (this->peekByte() != 0) {
408             // If the first byte is non-zero, the flattenable is specified by a string.
409             size_t ignored_length;
410             if (const char* name = this->readString(&ignored_length)) {
411                 factory = SkFlattenable::NameToFactory(name);
412                 fFlattenableDict.set(fFlattenableDict.count() + 1, factory);
413             }
414         } else {
415             // Read the index.  We are guaranteed that the first byte
416             // is zeroed, so we must shift down a byte.
417             uint32_t index = this->readUInt() >> 8;
418             if (index == 0) {
419                 return nullptr; // writer failed to give us the flattenable
420             }
421 
422             if (SkFlattenable::Factory* found = fFlattenableDict.find(index)) {
423                 factory = *found;
424             }
425         }
426 
427         if (!this->validate(factory != nullptr)) {
428             return nullptr;
429         }
430     }
431 
432     // if we get here, factory may still be null, but if that is the case, the
433     // failure was ours, not the writer.
434     sk_sp<SkFlattenable> obj;
435     uint32_t sizeRecorded = this->read32();
436     if (factory) {
437         size_t offset = this->offset();
438         obj = (*factory)(*this);
439         // check that we read the amount we expected
440         size_t sizeRead = this->offset() - offset;
441         if (sizeRecorded != sizeRead) {
442             this->validate(false);
443             return nullptr;
444         }
445         if (obj && obj->getFlattenableType() != ft) {
446             this->validate(false);
447             return nullptr;
448         }
449     } else {
450         // we must skip the remaining data
451         this->skip(sizeRecorded);
452     }
453     if (!this->isValid()) {
454         return nullptr;
455     }
456     return obj.release();
457 }
458 
459 ///////////////////////////////////////////////////////////////////////////////////////////////////
460 
checkInt(int32_t min,int32_t max)461 int32_t SkReadBuffer::checkInt(int32_t min, int32_t max) {
462     SkASSERT(min <= max);
463     int32_t value = this->read32();
464     if (value < min || value > max) {
465         this->validate(false);
466         value = min;
467     }
468     return value;
469 }
470 
checkFilterQuality()471 SkLegacyFQ SkReadBuffer::checkFilterQuality() {
472     return this->checkRange<SkLegacyFQ>(kNone_SkLegacyFQ, kLast_SkLegacyFQ);
473 }
474