SkValidatingReadBuffer.cpp revision d594dbec0407343b7ac13af9c4580ec5933ab060
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 "SkErrorInternals.h" 10#include "SkValidatingReadBuffer.h" 11#include "SkStream.h" 12#include "SkTypeface.h" 13 14SkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) { 15 this->setMemory(data, size); 16 fError = false; 17 18 this->setFlags(SkFlattenableReadBuffer::kValidation_Flag); 19} 20 21SkValidatingReadBuffer::~SkValidatingReadBuffer() { 22} 23 24void SkValidatingReadBuffer::setMemory(const void* data, size_t size) { 25 fError = fError || !IsPtrAlign4(data) || (SkAlign4(size) != size); 26 if (!fError) { 27 fReader.setMemory(data, size); 28 } 29} 30 31const void* SkValidatingReadBuffer::skip(size_t size) { 32 size_t inc = SkAlign4(size); 33 const void* addr = fReader.peek(); 34 fError = fError || !IsPtrAlign4(addr) || !fReader.isAvailable(inc); 35 if (!fError) { 36 fReader.skip(size); 37 } 38 return addr; 39} 40 41// All the methods in this file funnel down into either readInt(), readScalar() or skip(), 42// followed by a memcpy. So we've got all our validation in readInt(), readScalar() and skip(); 43// if they fail they'll return a zero value or skip nothing, respectively, and set fError to 44// true, which the caller should check to see if an error occurred during the read operation. 45 46bool SkValidatingReadBuffer::readBool() { 47 uint32_t value = this->readInt(); 48 // Boolean value should be either 0 or 1 49 if (value & ~1) { 50 fError = true; 51 } 52 return value != 0; 53} 54 55SkColor SkValidatingReadBuffer::readColor() { 56 return this->readInt(); 57} 58 59SkFixed SkValidatingReadBuffer::readFixed() { 60 return this->readInt(); 61} 62 63int32_t SkValidatingReadBuffer::readInt() { 64 const size_t inc = sizeof(int32_t); 65 fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); 66 return fError ? 0 : fReader.readInt(); 67} 68 69SkScalar SkValidatingReadBuffer::readScalar() { 70 const size_t inc = sizeof(SkScalar); 71 fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); 72 return fError ? 0 : fReader.readScalar(); 73} 74 75uint32_t SkValidatingReadBuffer::readUInt() { 76 return this->readInt(); 77} 78 79int32_t SkValidatingReadBuffer::read32() { 80 return this->readInt(); 81} 82 83void SkValidatingReadBuffer::readString(SkString* string) { 84 const size_t len = this->readInt(); 85 const void* ptr = fReader.peek(); 86 const char* cptr = (const char*)ptr; 87 88 // skip over the string + '\0' and then pad to a multiple of 4 89 const size_t alignedSize = SkAlign4(len + 1); 90 this->skip(alignedSize); 91 fError = fError || (cptr[len] != '\0'); 92 if (!fError) { 93 string->set(cptr, len); 94 } 95} 96 97void* SkValidatingReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) { 98 const int32_t encodingType = fReader.readInt(); 99 fError = fError || (encodingType != encoding); 100 *length = this->readInt(); 101 const void* ptr = this->skip(SkAlign4(*length)); 102 void* data = NULL; 103 if (!fError) { 104 data = sk_malloc_throw(*length); 105 memcpy(data, ptr, *length); 106 } 107 return data; 108} 109 110void SkValidatingReadBuffer::readPoint(SkPoint* point) { 111 point->fX = fReader.readScalar(); 112 point->fY = fReader.readScalar(); 113} 114 115void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) { 116 const size_t size = matrix->readFromMemory(fReader.peek()); 117 fError = fError || (SkAlign4(size) != size); 118 if (!fError) { 119 (void)this->skip(size); 120 } 121} 122 123void SkValidatingReadBuffer::readIRect(SkIRect* rect) { 124 const void* ptr = this->skip(sizeof(SkIRect)); 125 if (!fError) { 126 memcpy(rect, ptr, sizeof(SkIRect)); 127 } 128} 129 130void SkValidatingReadBuffer::readRect(SkRect* rect) { 131 const void* ptr = this->skip(sizeof(SkRect)); 132 if (!fError) { 133 memcpy(rect, ptr, sizeof(SkRect)); 134 } 135} 136 137void SkValidatingReadBuffer::readRegion(SkRegion* region) { 138 const size_t size = region->readFromMemory(fReader.peek()); 139 fError = fError || (SkAlign4(size) != size); 140 if (!fError) { 141 (void)this->skip(size); 142 } 143} 144 145void SkValidatingReadBuffer::readPath(SkPath* path) { 146 const size_t size = path->readFromMemory(fReader.peek()); 147 fError = fError || (SkAlign4(size) != size); 148 if (!fError) { 149 (void)this->skip(size); 150 } 151} 152 153uint32_t SkValidatingReadBuffer::readByteArray(void* value) { 154 const uint32_t length = this->readUInt(); 155 const void* ptr = this->skip(SkAlign4(length)); 156 if (!fError) { 157 memcpy(value, ptr, length); 158 return length; 159 } 160 return 0; 161} 162 163uint32_t SkValidatingReadBuffer::readColorArray(SkColor* colors) { 164 const uint32_t count = this->readUInt(); 165 const uint32_t byteLength = count * sizeof(SkColor); 166 const void* ptr = this->skip(SkAlign4(byteLength)); 167 if (!fError) { 168 memcpy(colors, ptr, byteLength); 169 return count; 170 } 171 return 0; 172} 173 174uint32_t SkValidatingReadBuffer::readIntArray(int32_t* values) { 175 const uint32_t count = this->readUInt(); 176 const uint32_t byteLength = count * sizeof(int32_t); 177 const void* ptr = this->skip(SkAlign4(byteLength)); 178 if (!fError) { 179 memcpy(values, ptr, byteLength); 180 return count; 181 } 182 return 0; 183} 184 185uint32_t SkValidatingReadBuffer::readPointArray(SkPoint* points) { 186 const uint32_t count = this->readUInt(); 187 const uint32_t byteLength = count * sizeof(SkPoint); 188 const void* ptr = this->skip(SkAlign4(byteLength)); 189 if (!fError) { 190 memcpy(points, ptr, byteLength); 191 return count; 192 } 193 return 0; 194} 195 196uint32_t SkValidatingReadBuffer::readScalarArray(SkScalar* values) { 197 const uint32_t count = this->readUInt(); 198 const uint32_t byteLength = count * sizeof(SkScalar); 199 const void* ptr = this->skip(SkAlign4(byteLength)); 200 if (!fError) { 201 memcpy(values, ptr, byteLength); 202 return count; 203 } 204 return 0; 205} 206 207uint32_t SkValidatingReadBuffer::getArrayCount() { 208 return *(uint32_t*)fReader.peek(); 209} 210 211void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) { 212 const int width = this->readInt(); 213 const int height = this->readInt(); 214 const size_t length = this->readUInt(); 215 // A size of zero means the SkBitmap was simply flattened. 216 fError = fError || (length != 0); 217 if (fError) { 218 return; 219 } 220 bitmap->unflatten(*this); 221 fError = fError || (bitmap->width() != width) || (bitmap->height() != height); 222} 223 224SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) { 225 SkString name; 226 this->readString(&name); 227 if (fError) { 228 return NULL; 229 } 230 231 // Is this the type we wanted ? 232 const char* cname = name.c_str(); 233 SkFlattenable::Type baseType; 234 if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) { 235 return NULL; 236 } 237 238 SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname); 239 if (NULL == factory) { 240 return NULL; // writer failed to give us the flattenable 241 } 242 243 // if we get here, factory may still be null, but if that is the case, the 244 // failure was ours, not the writer. 245 SkFlattenable* obj = NULL; 246 uint32_t sizeRecorded = this->readUInt(); 247 if (factory) { 248 uint32_t offset = fReader.offset(); 249 obj = (*factory)(*this); 250 // check that we read the amount we expected 251 uint32_t sizeRead = fReader.offset() - offset; 252 fError = fError || (sizeRecorded != sizeRead); 253 if (fError) { 254 // we could try to fix up the offset... 255 delete obj; 256 obj = NULL; 257 } 258 } else { 259 // we must skip the remaining data 260 this->skip(sizeRecorded); 261 SkASSERT(false); 262 } 263 return obj; 264} 265