xref: /third_party/skia/src/core/SkReadBuffer.cpp (revision cb93a386)
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
21namespace {
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:
26        EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { }
27
28    private:
29        using INHERITED = SkImageGenerator;
30    };
31
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
39void 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
47void 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
55const 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
68const void* SkReadBuffer::skip(size_t count, size_t size) {
69    return this->skip(SkSafeMath::Mul(count, size));
70}
71
72void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
73    fProcs = procs;
74}
75
76bool 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
83SkColor SkReadBuffer::readColor() {
84    return this->readUInt();
85}
86
87int32_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
97SkScalar 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
107uint32_t SkReadBuffer::readUInt() {
108    return this->readInt();
109}
110
111int32_t SkReadBuffer::read32() {
112    return this->readInt();
113}
114
115uint8_t SkReadBuffer::peekByte() {
116    if (this->available() <= 0) {
117        fError = true;
118        return 0;
119    }
120    return *((uint8_t*)fCurr);
121}
122
123bool 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
133const 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
145void 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
154void SkReadBuffer::readColor4f(SkColor4f* color) {
155    if (!this->readPad32(color, sizeof(SkColor4f))) {
156        *color = {0, 0, 0, 0};
157    }
158}
159
160void SkReadBuffer::readPoint(SkPoint* point) {
161    point->fX = this->readScalar();
162    point->fY = this->readScalar();
163}
164
165void SkReadBuffer::readPoint3(SkPoint3* point) {
166    this->readPad32(point, sizeof(SkPoint3));
167}
168
169void 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
180void 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
192void SkReadBuffer::readIRect(SkIRect* rect) {
193    if (!this->readPad32(rect, sizeof(SkIRect))) {
194        rect->setEmpty();
195    }
196}
197
198void SkReadBuffer::readRect(SkRect* rect) {
199    if (!this->readPad32(rect, sizeof(SkRect))) {
200        rect->setEmpty();
201    }
202}
203
204SkRect SkReadBuffer::readRect() {
205    SkRect r;
206    if (!this->readPad32(&r, sizeof(SkRect))) {
207        r.setEmpty();
208    }
209    return r;
210}
211
212SkSamplingOptions 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
224void 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
235void 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
246void 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
257bool 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
263bool SkReadBuffer::readByteArray(void* value, size_t size) {
264    return this->readArray(value, size, sizeof(uint8_t));
265}
266
267bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
268    return this->readArray(colors, size, sizeof(SkColor));
269}
270
271bool SkReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
272    return this->readArray(colors, size, sizeof(SkColor4f));
273}
274
275bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
276    return this->readArray(values, size, sizeof(int32_t));
277}
278
279bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) {
280    return this->readArray(points, size, sizeof(SkPoint));
281}
282
283bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
284    return this->readArray(values, size, sizeof(SkScalar));
285}
286
287const 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
296sk_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
309uint32_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.
321sk_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
368sk_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
392SkFlattenable* 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
461int32_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
471SkLegacyFQ SkReadBuffer::checkFilterQuality() {
472    return this->checkRange<SkLegacyFQ>(kNone_SkLegacyFQ, kLast_SkLegacyFQ);
473}
474