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