Home | History | Annotate | Download | only in core
      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:
     25         EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { }
     26 
     27     private:
     28         typedef SkImageGenerator INHERITED;
     29     };
     30 
     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 
     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 
     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 
     68 SkReadBuffer::~SkReadBuffer() {
     69     sk_free(fMemoryPtr);
     70 }
     71 
     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 }
     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 
     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 
     99 const void* SkReadBuffer::skip(size_t count, size_t size) {
    100     return this->skip(SkSafeMath::Mul(count, size));
    101 }
    102 
    103 void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
    104     fProcs = procs;
    105 }
    106 
    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 
    114 SkColor SkReadBuffer::readColor() {
    115     return this->readUInt();
    116 }
    117 
    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 
    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 
    130 uint32_t SkReadBuffer::readUInt() {
    131     return this->readInt();
    132 }
    133 
    134 int32_t SkReadBuffer::read32() {
    135     return this->readInt();
    136 }
    137 
    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 
    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 
    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 
    166 void SkReadBuffer::readColor4f(SkColor4f* color) {
    167     if (!this->readPad32(color, sizeof(SkColor4f))) {
    168         *color = {0, 0, 0, 0};
    169     }
    170 }
    171 
    172 void SkReadBuffer::readPoint(SkPoint* point) {
    173     point->fX = this->readScalar();
    174     point->fY = this->readScalar();
    175 }
    176 
    177 void SkReadBuffer::readPoint3(SkPoint3* point) {
    178     this->readPad32(point, sizeof(SkPoint3));
    179 }
    180 
    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 
    192 void SkReadBuffer::readIRect(SkIRect* rect) {
    193     if (!this->readPad32(rect, sizeof(SkIRect))) {
    194         rect->setEmpty();
    195     }
    196 }
    197 
    198 void SkReadBuffer::readRect(SkRect* rect) {
    199     if (!this->readPad32(rect, sizeof(SkRect))) {
    200         rect->setEmpty();
    201     }
    202 }
    203 
    204 void SkReadBuffer::readRRect(SkRRect* rrect) {
    205     if (!this->validate(fReader.readRRect(rrect))) {
    206         rrect->setEmpty();
    207     }
    208 }
    209 
    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 
    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 
    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 
    238 bool SkReadBuffer::readByteArray(void* value, size_t size) {
    239     return this->readArray(value, size, sizeof(uint8_t));
    240 }
    241 
    242 bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
    243     return this->readArray(colors, size, sizeof(SkColor));
    244 }
    245 
    246 bool SkReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
    247     return this->readArray(colors, size, sizeof(SkColor4f));
    248 }
    249 
    250 bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
    251     return this->readArray(values, size, sizeof(int32_t));
    252 }
    253 
    254 bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) {
    255     return this->readArray(points, size, sizeof(SkPoint));
    256 }
    257 
    258 bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
    259     return this->readArray(values, size, sizeof(SkScalar));
    260 }
    261 
    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 
    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 
    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 
    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 
    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 
    443 SkFilterQuality SkReadBuffer::checkFilterQuality() {
    444     return this->checkRange<SkFilterQuality>(kNone_SkFilterQuality, kLast_SkFilterQuality);
    445 }
    446