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     }
    120 }
    121 
    122 void SkValidatingReadBuffer::readPoint(SkPoint* point) {
    123     point->fX = this->readScalar();
    124     point->fY = this->readScalar();
    125 }
    126 
    127 void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) {
    128     size_t size = 0;
    129     if (!fError) {
    130         size = matrix->readFromMemory(fReader.peek(), fReader.available());
    131         this->validate((SkAlign4(size) == size) && (0 != size));
    132     }
    133     if (!fError) {
    134         (void)this->skip(size);
    135     }
    136 }
    137 
    138 void SkValidatingReadBuffer::readIRect(SkIRect* rect) {
    139     const void* ptr = this->skip(sizeof(SkIRect));
    140     if (!fError) {
    141         memcpy(rect, ptr, sizeof(SkIRect));
    142     }
    143 }
    144 
    145 void SkValidatingReadBuffer::readRect(SkRect* rect) {
    146     const void* ptr = this->skip(sizeof(SkRect));
    147     if (!fError) {
    148         memcpy(rect, ptr, sizeof(SkRect));
    149     }
    150 }
    151 
    152 void SkValidatingReadBuffer::readRRect(SkRRect* rrect) {
    153     const void* ptr = this->skip(sizeof(SkRRect));
    154     if (!fError) {
    155         memcpy(rrect, ptr, sizeof(SkRRect));
    156         this->validate(rrect->isValid());
    157     }
    158 
    159     if (fError) {
    160         rrect->setEmpty();
    161     }
    162 }
    163 
    164 void SkValidatingReadBuffer::readRegion(SkRegion* region) {
    165     size_t size = 0;
    166     if (!fError) {
    167         size = region->readFromMemory(fReader.peek(), fReader.available());
    168         this->validate((SkAlign4(size) == size) && (0 != size));
    169     }
    170     if (!fError) {
    171         (void)this->skip(size);
    172     }
    173 }
    174 
    175 void SkValidatingReadBuffer::readPath(SkPath* path) {
    176     size_t size = 0;
    177     if (!fError) {
    178         size = path->readFromMemory(fReader.peek(), fReader.available());
    179         this->validate((SkAlign4(size) == size) && (0 != size));
    180     }
    181     if (!fError) {
    182         (void)this->skip(size);
    183     }
    184 }
    185 
    186 bool SkValidatingReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
    187     const uint32_t count = this->getArrayCount();
    188     this->validate(size == count);
    189     (void)this->skip(sizeof(uint32_t)); // Skip array count
    190     const uint64_t byteLength64 = sk_64_mul(count, elementSize);
    191     const size_t byteLength = count * elementSize;
    192     this->validate(byteLength == byteLength64);
    193     const void* ptr = this->skip(SkAlign4(byteLength));
    194     if (!fError) {
    195         memcpy(value, ptr, byteLength);
    196         return true;
    197     }
    198     return false;
    199 }
    200 
    201 bool SkValidatingReadBuffer::readByteArray(void* value, size_t size) {
    202     return this->readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
    203 }
    204 
    205 bool SkValidatingReadBuffer::readColorArray(SkColor* colors, size_t size) {
    206     return this->readArray(colors, size, sizeof(SkColor));
    207 }
    208 
    209 bool SkValidatingReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
    210     return this->readArray(colors, size, sizeof(SkColor4f));
    211 }
    212 
    213 bool SkValidatingReadBuffer::readIntArray(int32_t* values, size_t size) {
    214     return this->readArray(values, size, sizeof(int32_t));
    215 }
    216 
    217 bool SkValidatingReadBuffer::readPointArray(SkPoint* points, size_t size) {
    218     return this->readArray(points, size, sizeof(SkPoint));
    219 }
    220 
    221 bool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) {
    222     return this->readArray(values, size, sizeof(SkScalar));
    223 }
    224 
    225 uint32_t SkValidatingReadBuffer::getArrayCount() {
    226     const size_t inc = sizeof(uint32_t);
    227     fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
    228     return fError ? 0 : *(uint32_t*)fReader.peek();
    229 }
    230 
    231 bool SkValidatingReadBuffer::validateAvailable(size_t size) {
    232     return this->validate((size <= SK_MaxU32) && fReader.isAvailable(static_cast<uint32_t>(size)));
    233 }
    234 
    235 SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) {
    236     // The validating read buffer always uses strings and string-indices for unflattening.
    237     SkASSERT(0 == this->factoryCount());
    238 
    239     uint8_t firstByte = this->peekByte();
    240     if (fError) {
    241         return nullptr;
    242     }
    243 
    244     SkString name;
    245     if (firstByte) {
    246         // If the first byte is non-zero, the flattenable is specified by a string.
    247         this->readString(&name);
    248         if (fError) {
    249             return nullptr;
    250         }
    251 
    252         // Add the string to the dictionary.
    253         fFlattenableDict.set(fFlattenableDict.count() + 1, name);
    254     } else {
    255         // Read the index.  We are guaranteed that the first byte
    256         // is zeroed, so we must shift down a byte.
    257         uint32_t index = this->readUInt() >> 8;
    258         if (0 == index) {
    259             return nullptr; // writer failed to give us the flattenable
    260         }
    261 
    262         SkString* namePtr = fFlattenableDict.find(index);
    263         if (!namePtr) {
    264             return nullptr;
    265         }
    266         name = *namePtr;
    267     }
    268 
    269     // Is this the type we wanted ?
    270     const char* cname = name.c_str();
    271     SkFlattenable::Type baseType;
    272     if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) {
    273         return nullptr;
    274     }
    275 
    276     // Get the factory for this flattenable.
    277     SkFlattenable::Factory factory = this->getCustomFactory(name);
    278     if (!factory) {
    279         factory = SkFlattenable::NameToFactory(cname);
    280         if (!factory) {
    281             return nullptr; // writer failed to give us the flattenable
    282         }
    283     }
    284 
    285     // If we get here, the factory is non-null.
    286     sk_sp<SkFlattenable> obj;
    287     uint32_t sizeRecorded = this->readUInt();
    288     size_t offset = fReader.offset();
    289     obj = (*factory)(*this);
    290     // check that we read the amount we expected
    291     size_t sizeRead = fReader.offset() - offset;
    292     this->validate(sizeRecorded == sizeRead);
    293     if (fError) {
    294         obj = nullptr;
    295     }
    296     return obj.release();
    297 }
    298