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