Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2013 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 "SkValidatingReadBuffer.h"
     10 #include "SkStream.h"
     11 #include "SkTypeface.h"
     12 
     13 SkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) :
     14     fError(false) {
     15     this->setMemory(data, size);
     16     this->setFlags(SkReadBuffer::kValidation_Flag);
     17 }
     18 
     19 SkValidatingReadBuffer::~SkValidatingReadBuffer() {
     20 }
     21 
     22 bool SkValidatingReadBuffer::validate(bool isValid) {
     23     if (!fError && !isValid) {
     24         // When an error is found, send the read cursor to the end of the stream
     25         fReader.skip(fReader.available());
     26         fError = true;
     27     }
     28     return !fError;
     29 }
     30 
     31 bool SkValidatingReadBuffer::isValid() const {
     32     return !fError;
     33 }
     34 
     35 void SkValidatingReadBuffer::setMemory(const void* data, size_t size) {
     36     this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
     37     if (!fError) {
     38         fReader.setMemory(data, size);
     39     }
     40 }
     41 
     42 const void* SkValidatingReadBuffer::skip(size_t size) {
     43     size_t inc = SkAlign4(size);
     44     this->validate(inc >= size);
     45     const void* addr = fReader.peek();
     46     this->validate(IsPtrAlign4(addr) && fReader.isAvailable(inc));
     47     if (fError) {
     48         return nullptr;
     49     }
     50 
     51     fReader.skip(size);
     52     return addr;
     53 }
     54 
     55 // All the methods in this file funnel down into either readInt(), readScalar() or skip(),
     56 // followed by a memcpy. So we've got all our validation in readInt(), readScalar() and skip();
     57 // if they fail they'll return a zero value or skip nothing, respectively, and set fError to
     58 // true, which the caller should check to see if an error occurred during the read operation.
     59 
     60 bool SkValidatingReadBuffer::readBool() {
     61     uint32_t value = this->readInt();
     62     // Boolean value should be either 0 or 1
     63     this->validate(!(value & ~1));
     64     return value != 0;
     65 }
     66 
     67 SkColor SkValidatingReadBuffer::readColor() {
     68     return this->readInt();
     69 }
     70 
     71 int32_t SkValidatingReadBuffer::readInt() {
     72     const size_t inc = sizeof(int32_t);
     73     this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
     74     return fError ? 0 : fReader.readInt();
     75 }
     76 
     77 SkScalar SkValidatingReadBuffer::readScalar() {
     78     const size_t inc = sizeof(SkScalar);
     79     this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
     80     return fError ? 0 : fReader.readScalar();
     81 }
     82 
     83 uint32_t SkValidatingReadBuffer::readUInt() {
     84     return this->readInt();
     85 }
     86 
     87 int32_t SkValidatingReadBuffer::read32() {
     88     return this->readInt();
     89 }
     90 
     91 uint8_t SkValidatingReadBuffer::peekByte() {
     92     if (fReader.available() <= 0) {
     93         fError = true;
     94         return 0;
     95     }
     96     return *((uint8_t*) fReader.peek());
     97 }
     98 
     99 void SkValidatingReadBuffer::readString(SkString* string) {
    100     const size_t len = this->readUInt();
    101     const void* ptr = fReader.peek();
    102     const char* cptr = (const char*)ptr;
    103 
    104     // skip over the string + '\0' and then pad to a multiple of 4
    105     const size_t alignedSize = SkAlign4(len + 1);
    106     this->skip(alignedSize);
    107     if (!fError) {
    108         this->validate(cptr[len] == '\0');
    109     }
    110     if (!fError) {
    111         string->set(cptr, len);
    112     }
    113 }
    114 
    115 void SkValidatingReadBuffer::readColor4f(SkColor4f* color) {
    116     const void* ptr = this->skip(sizeof(SkColor4f));
    117     if (!fError) {
    118         memcpy(color, ptr, sizeof(SkColor4f));
    119     } else {
    120         *color = SkColor4f::FromColor(SK_ColorBLACK);
    121     }
    122 }
    123 
    124 void SkValidatingReadBuffer::readPoint(SkPoint* point) {
    125     point->fX = this->readScalar();
    126     point->fY = this->readScalar();
    127 }
    128 
    129 void SkValidatingReadBuffer::readPoint3(SkPoint3* point) {
    130     point->fX = this->readScalar();
    131     point->fY = this->readScalar();
    132     point->fZ = this->readScalar();
    133 }
    134 
    135 void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) {
    136     size_t size = 0;
    137     if (!fError) {
    138         size = matrix->readFromMemory(fReader.peek(), fReader.available());
    139         this->validate((SkAlign4(size) == size) && (0 != size));
    140     }
    141     if (!fError) {
    142         (void)this->skip(size);
    143     }
    144 }
    145 
    146 void SkValidatingReadBuffer::readIRect(SkIRect* rect) {
    147     const void* ptr = this->skip(sizeof(SkIRect));
    148     if (!fError) {
    149         memcpy(rect, ptr, sizeof(SkIRect));
    150     } else {
    151         rect->setEmpty();
    152     }
    153 }
    154 
    155 void SkValidatingReadBuffer::readRect(SkRect* rect) {
    156     const void* ptr = this->skip(sizeof(SkRect));
    157     if (!fError) {
    158         memcpy(rect, ptr, sizeof(SkRect));
    159     } else {
    160         rect->setEmpty();
    161     }
    162 }
    163 
    164 void SkValidatingReadBuffer::readRRect(SkRRect* rrect) {
    165     const void* ptr = this->skip(sizeof(SkRRect));
    166     if (!fError) {
    167         memcpy(rrect, ptr, sizeof(SkRRect));
    168         this->validate(rrect->isValid());
    169     }
    170 
    171     if (fError) {
    172         rrect->setEmpty();
    173     }
    174 }
    175 
    176 void SkValidatingReadBuffer::readRegion(SkRegion* region) {
    177     size_t size = 0;
    178     if (!fError) {
    179         size = region->readFromMemory(fReader.peek(), fReader.available());
    180         this->validate((SkAlign4(size) == size) && (0 != size));
    181     }
    182     if (!fError) {
    183         (void)this->skip(size);
    184     }
    185 }
    186 
    187 void SkValidatingReadBuffer::readPath(SkPath* path) {
    188     size_t size = 0;
    189     if (!fError) {
    190         size = path->readFromMemory(fReader.peek(), fReader.available());
    191         this->validate((SkAlign4(size) == size) && (0 != size));
    192     }
    193     if (!fError) {
    194         (void)this->skip(size);
    195     }
    196 }
    197 
    198 bool SkValidatingReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
    199     const uint32_t count = this->getArrayCount();
    200     this->validate(size == count);
    201     (void)this->skip(sizeof(uint32_t)); // Skip array count
    202     const uint64_t byteLength64 = sk_64_mul(count, elementSize);
    203     const size_t byteLength = count * elementSize;
    204     this->validate(byteLength == byteLength64);
    205     const void* ptr = this->skip(SkAlign4(byteLength));
    206     if (!fError) {
    207         memcpy(value, ptr, byteLength);
    208         return true;
    209     }
    210     return false;
    211 }
    212 
    213 bool SkValidatingReadBuffer::readByteArray(void* value, size_t size) {
    214     return this->readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
    215 }
    216 
    217 bool SkValidatingReadBuffer::readColorArray(SkColor* colors, size_t size) {
    218     return this->readArray(colors, size, sizeof(SkColor));
    219 }
    220 
    221 bool SkValidatingReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
    222     return this->readArray(colors, size, sizeof(SkColor4f));
    223 }
    224 
    225 bool SkValidatingReadBuffer::readIntArray(int32_t* values, size_t size) {
    226     return this->readArray(values, size, sizeof(int32_t));
    227 }
    228 
    229 bool SkValidatingReadBuffer::readPointArray(SkPoint* points, size_t size) {
    230     return this->readArray(points, size, sizeof(SkPoint));
    231 }
    232 
    233 bool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) {
    234     return this->readArray(values, size, sizeof(SkScalar));
    235 }
    236 
    237 uint32_t SkValidatingReadBuffer::getArrayCount() {
    238     const size_t inc = sizeof(uint32_t);
    239     fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
    240     return fError ? 0 : *(uint32_t*)fReader.peek();
    241 }
    242 
    243 bool SkValidatingReadBuffer::validateAvailable(size_t size) {
    244     return this->validate((size <= SK_MaxU32) && fReader.isAvailable(static_cast<uint32_t>(size)));
    245 }
    246 
    247 SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) {
    248     // The validating read buffer always uses strings and string-indices for unflattening.
    249     SkASSERT(0 == this->factoryCount());
    250 
    251     uint8_t firstByte = this->peekByte();
    252     if (fError) {
    253         return nullptr;
    254     }
    255 
    256     SkString name;
    257     if (firstByte) {
    258         // If the first byte is non-zero, the flattenable is specified by a string.
    259         this->readString(&name);
    260         if (fError) {
    261             return nullptr;
    262         }
    263 
    264         // Add the string to the dictionary.
    265         fFlattenableDict.set(fFlattenableDict.count() + 1, name);
    266     } else {
    267         // Read the index.  We are guaranteed that the first byte
    268         // is zeroed, so we must shift down a byte.
    269         uint32_t index = this->readUInt() >> 8;
    270         if (0 == index) {
    271             return nullptr; // writer failed to give us the flattenable
    272         }
    273 
    274         SkString* namePtr = fFlattenableDict.find(index);
    275         if (!namePtr) {
    276             return nullptr;
    277         }
    278         name = *namePtr;
    279     }
    280 
    281     // Is this the type we wanted ?
    282     const char* cname = name.c_str();
    283     SkFlattenable::Type baseType;
    284     if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) {
    285         return nullptr;
    286     }
    287 
    288     // Get the factory for this flattenable.
    289     SkFlattenable::Factory factory = this->getCustomFactory(name);
    290     if (!factory) {
    291         factory = SkFlattenable::NameToFactory(cname);
    292         if (!factory) {
    293             return nullptr; // writer failed to give us the flattenable
    294         }
    295     }
    296 
    297     // If we get here, the factory is non-null.
    298     sk_sp<SkFlattenable> obj;
    299     uint32_t sizeRecorded = this->readUInt();
    300     size_t offset = fReader.offset();
    301     obj = (*factory)(*this);
    302     // check that we read the amount we expected
    303     size_t sizeRead = fReader.offset() - offset;
    304     this->validate(sizeRecorded == sizeRead);
    305     if (fError) {
    306         obj = nullptr;
    307     }
    308     return obj.release();
    309 }
    310