1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/src/core/SkValidatingReadBuffer.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,275 @@ 1.4 +/* 1.5 + * Copyright 2013 Google Inc. 1.6 + * 1.7 + * Use of this source code is governed by a BSD-style license that can be 1.8 + * found in the LICENSE file. 1.9 + */ 1.10 + 1.11 +#include "SkBitmap.h" 1.12 +#include "SkErrorInternals.h" 1.13 +#include "SkValidatingReadBuffer.h" 1.14 +#include "SkStream.h" 1.15 +#include "SkTypeface.h" 1.16 + 1.17 +SkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) : 1.18 + fError(false) { 1.19 + this->setMemory(data, size); 1.20 + this->setFlags(SkReadBuffer::kValidation_Flag); 1.21 +} 1.22 + 1.23 +SkValidatingReadBuffer::~SkValidatingReadBuffer() { 1.24 +} 1.25 + 1.26 +bool SkValidatingReadBuffer::validate(bool isValid) { 1.27 + if (!fError && !isValid) { 1.28 + // When an error is found, send the read cursor to the end of the stream 1.29 + fReader.skip(fReader.available()); 1.30 + fError = true; 1.31 + } 1.32 + return !fError; 1.33 +} 1.34 + 1.35 +bool SkValidatingReadBuffer::isValid() const { 1.36 + return !fError; 1.37 +} 1.38 + 1.39 +void SkValidatingReadBuffer::setMemory(const void* data, size_t size) { 1.40 + this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size)); 1.41 + if (!fError) { 1.42 + fReader.setMemory(data, size); 1.43 + } 1.44 +} 1.45 + 1.46 +const void* SkValidatingReadBuffer::skip(size_t size) { 1.47 + size_t inc = SkAlign4(size); 1.48 + const void* addr = fReader.peek(); 1.49 + this->validate(IsPtrAlign4(addr) && fReader.isAvailable(inc)); 1.50 + if (!fError) { 1.51 + fReader.skip(size); 1.52 + } 1.53 + return addr; 1.54 +} 1.55 + 1.56 +// All the methods in this file funnel down into either readInt(), readScalar() or skip(), 1.57 +// followed by a memcpy. So we've got all our validation in readInt(), readScalar() and skip(); 1.58 +// if they fail they'll return a zero value or skip nothing, respectively, and set fError to 1.59 +// true, which the caller should check to see if an error occurred during the read operation. 1.60 + 1.61 +bool SkValidatingReadBuffer::readBool() { 1.62 + uint32_t value = this->readInt(); 1.63 + // Boolean value should be either 0 or 1 1.64 + this->validate(!(value & ~1)); 1.65 + return value != 0; 1.66 +} 1.67 + 1.68 +SkColor SkValidatingReadBuffer::readColor() { 1.69 + return this->readInt(); 1.70 +} 1.71 + 1.72 +SkFixed SkValidatingReadBuffer::readFixed() { 1.73 + return this->readInt(); 1.74 +} 1.75 + 1.76 +int32_t SkValidatingReadBuffer::readInt() { 1.77 + const size_t inc = sizeof(int32_t); 1.78 + this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc)); 1.79 + return fError ? 0 : fReader.readInt(); 1.80 +} 1.81 + 1.82 +SkScalar SkValidatingReadBuffer::readScalar() { 1.83 + const size_t inc = sizeof(SkScalar); 1.84 + this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc)); 1.85 + return fError ? 0 : fReader.readScalar(); 1.86 +} 1.87 + 1.88 +uint32_t SkValidatingReadBuffer::readUInt() { 1.89 + return this->readInt(); 1.90 +} 1.91 + 1.92 +int32_t SkValidatingReadBuffer::read32() { 1.93 + return this->readInt(); 1.94 +} 1.95 + 1.96 +void SkValidatingReadBuffer::readString(SkString* string) { 1.97 + const size_t len = this->readInt(); 1.98 + const void* ptr = fReader.peek(); 1.99 + const char* cptr = (const char*)ptr; 1.100 + 1.101 + // skip over the string + '\0' and then pad to a multiple of 4 1.102 + const size_t alignedSize = SkAlign4(len + 1); 1.103 + this->skip(alignedSize); 1.104 + if (!fError) { 1.105 + this->validate(cptr[len] == '\0'); 1.106 + } 1.107 + if (!fError) { 1.108 + string->set(cptr, len); 1.109 + } 1.110 +} 1.111 + 1.112 +void* SkValidatingReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) { 1.113 + const int32_t encodingType = this->readInt(); 1.114 + this->validate(encodingType == encoding); 1.115 + *length = this->readInt(); 1.116 + const void* ptr = this->skip(SkAlign4(*length)); 1.117 + void* data = NULL; 1.118 + if (!fError) { 1.119 + data = sk_malloc_throw(*length); 1.120 + memcpy(data, ptr, *length); 1.121 + } 1.122 + return data; 1.123 +} 1.124 + 1.125 +void SkValidatingReadBuffer::readPoint(SkPoint* point) { 1.126 + point->fX = this->readScalar(); 1.127 + point->fY = this->readScalar(); 1.128 +} 1.129 + 1.130 +void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) { 1.131 + size_t size = 0; 1.132 + if (!fError) { 1.133 + size = matrix->readFromMemory(fReader.peek(), fReader.available()); 1.134 + this->validate((SkAlign4(size) == size) && (0 != size)); 1.135 + } 1.136 + if (!fError) { 1.137 + (void)this->skip(size); 1.138 + } 1.139 +} 1.140 + 1.141 +void SkValidatingReadBuffer::readIRect(SkIRect* rect) { 1.142 + const void* ptr = this->skip(sizeof(SkIRect)); 1.143 + if (!fError) { 1.144 + memcpy(rect, ptr, sizeof(SkIRect)); 1.145 + } 1.146 +} 1.147 + 1.148 +void SkValidatingReadBuffer::readRect(SkRect* rect) { 1.149 + const void* ptr = this->skip(sizeof(SkRect)); 1.150 + if (!fError) { 1.151 + memcpy(rect, ptr, sizeof(SkRect)); 1.152 + } 1.153 +} 1.154 + 1.155 +void SkValidatingReadBuffer::readRegion(SkRegion* region) { 1.156 + size_t size = 0; 1.157 + if (!fError) { 1.158 + size = region->readFromMemory(fReader.peek(), fReader.available()); 1.159 + this->validate((SkAlign4(size) == size) && (0 != size)); 1.160 + } 1.161 + if (!fError) { 1.162 + (void)this->skip(size); 1.163 + } 1.164 +} 1.165 + 1.166 +void SkValidatingReadBuffer::readPath(SkPath* path) { 1.167 + size_t size = 0; 1.168 + if (!fError) { 1.169 + size = path->readFromMemory(fReader.peek(), fReader.available()); 1.170 + this->validate((SkAlign4(size) == size) && (0 != size)); 1.171 + } 1.172 + if (!fError) { 1.173 + (void)this->skip(size); 1.174 + } 1.175 +} 1.176 + 1.177 +bool SkValidatingReadBuffer::readArray(void* value, size_t size, size_t elementSize) { 1.178 + const uint32_t count = this->getArrayCount(); 1.179 + this->validate(size == count); 1.180 + (void)this->skip(sizeof(uint32_t)); // Skip array count 1.181 + const size_t byteLength = count * elementSize; 1.182 + const void* ptr = this->skip(SkAlign4(byteLength)); 1.183 + if (!fError) { 1.184 + memcpy(value, ptr, byteLength); 1.185 + return true; 1.186 + } 1.187 + return false; 1.188 +} 1.189 + 1.190 +bool SkValidatingReadBuffer::readByteArray(void* value, size_t size) { 1.191 + return readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char)); 1.192 +} 1.193 + 1.194 +bool SkValidatingReadBuffer::readColorArray(SkColor* colors, size_t size) { 1.195 + return readArray(colors, size, sizeof(SkColor)); 1.196 +} 1.197 + 1.198 +bool SkValidatingReadBuffer::readIntArray(int32_t* values, size_t size) { 1.199 + return readArray(values, size, sizeof(int32_t)); 1.200 +} 1.201 + 1.202 +bool SkValidatingReadBuffer::readPointArray(SkPoint* points, size_t size) { 1.203 + return readArray(points, size, sizeof(SkPoint)); 1.204 +} 1.205 + 1.206 +bool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) { 1.207 + return readArray(values, size, sizeof(SkScalar)); 1.208 +} 1.209 + 1.210 +uint32_t SkValidatingReadBuffer::getArrayCount() { 1.211 + const size_t inc = sizeof(uint32_t); 1.212 + fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); 1.213 + return fError ? 0 : *(uint32_t*)fReader.peek(); 1.214 +} 1.215 + 1.216 +void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) { 1.217 + const int width = this->readInt(); 1.218 + const int height = this->readInt(); 1.219 + const bool useBitmapHeap = this->readBool(); 1.220 + const size_t length = this->readUInt(); 1.221 + // A size of zero means the SkBitmap was simply flattened. 1.222 + if (!this->validate(!useBitmapHeap && (0 == length))) { 1.223 + return; 1.224 + } 1.225 + bitmap->unflatten(*this); 1.226 + this->validate((bitmap->width() == width) && (bitmap->height() == height)); 1.227 +} 1.228 + 1.229 +SkTypeface* SkValidatingReadBuffer::readTypeface() { 1.230 + // TODO: Implement this (securely) when needed 1.231 + return NULL; 1.232 +} 1.233 + 1.234 +bool SkValidatingReadBuffer::validateAvailable(size_t size) { 1.235 + return this->validate((size <= SK_MaxU32) && fReader.isAvailable(static_cast<uint32_t>(size))); 1.236 +} 1.237 + 1.238 +SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) { 1.239 + SkString name; 1.240 + this->readString(&name); 1.241 + if (fError) { 1.242 + return NULL; 1.243 + } 1.244 + 1.245 + // Is this the type we wanted ? 1.246 + const char* cname = name.c_str(); 1.247 + SkFlattenable::Type baseType; 1.248 + if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) { 1.249 + return NULL; 1.250 + } 1.251 + 1.252 + SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname); 1.253 + if (NULL == factory) { 1.254 + return NULL; // writer failed to give us the flattenable 1.255 + } 1.256 + 1.257 + // if we get here, factory may still be null, but if that is the case, the 1.258 + // failure was ours, not the writer. 1.259 + SkFlattenable* obj = NULL; 1.260 + uint32_t sizeRecorded = this->readUInt(); 1.261 + if (factory) { 1.262 + uint32_t offset = fReader.offset(); 1.263 + obj = (*factory)(*this); 1.264 + // check that we read the amount we expected 1.265 + uint32_t sizeRead = fReader.offset() - offset; 1.266 + this->validate(sizeRecorded == sizeRead); 1.267 + if (fError) { 1.268 + // we could try to fix up the offset... 1.269 + delete obj; 1.270 + obj = NULL; 1.271 + } 1.272 + } else { 1.273 + // we must skip the remaining data 1.274 + this->skip(sizeRecorded); 1.275 + SkASSERT(false); 1.276 + } 1.277 + return obj; 1.278 +}