Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 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 | |
| 14 SkValidatingReadBuffer::SkValidatingReadBuffer() : INHERITED() { | |
|
mtklein
2013/10/07 19:29:56
Are all these constructors in use? Let's cut out
mtklein
2013/10/07 19:29:56
I think you can get away without calling INHERITED
sugoi1
2013/10/08 20:23:10
Done.
sugoi1
2013/10/08 20:23:10
Done.
| |
| 15 fMemoryPtr = NULL; | |
| 16 | |
| 17 setFlags(SkFlattenableReadBuffer::kValidation_Flag); | |
| 18 } | |
| 19 | |
| 20 SkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) : INHERITED() { | |
| 21 this->setMemory(data, size); | |
| 22 fMemoryPtr = NULL; | |
|
mtklein
2013/10/07 19:29:56
This is, um, confusing? We're going to need names
sugoi1
2013/10/08 20:23:10
I removed fMemoryPtr for now.
| |
| 23 | |
| 24 setFlags(SkFlattenableReadBuffer::kValidation_Flag); | |
|
mtklein
2013/10/07 19:29:56
this->, and in a few other places
sugoi1
2013/10/08 20:23:10
Done.
| |
| 25 } | |
| 26 | |
| 27 SkValidatingReadBuffer::SkValidatingReadBuffer(SkStream* stream) { | |
|
mtklein
2013/10/07 19:29:56
We've got to be careful here. Not every SkStream
sugoi1
2013/10/08 20:23:10
I removed the stream constructor for now, as it is
| |
| 28 const size_t length = stream->getLength(); | |
| 29 fMemoryPtr = sk_malloc_throw(length); | |
| 30 stream->read(fMemoryPtr, length); | |
| 31 this->setMemory(fMemoryPtr, length); | |
| 32 | |
| 33 setFlags(SkFlattenableReadBuffer::kValidation_Flag); | |
| 34 } | |
| 35 | |
| 36 SkValidatingReadBuffer::~SkValidatingReadBuffer() { | |
| 37 sk_free(fMemoryPtr); | |
|
mtklein
2013/10/07 19:29:56
Would prefer it if you made fMemoryPtr an SkAutoFr
sugoi1
2013/10/08 20:23:10
fMemoryPtr is gone
| |
| 38 } | |
| 39 | |
| 40 void SkValidatingReadBuffer::setMemory(const void* data, size_t size) { | |
| 41 fError |= (!IsPtrAlign4(data) || (SkAlign4(size) != size)); | |
|
mtklein
2013/10/07 19:29:56
This is a nit, but it'd be nice to consistently pa
mtklein
2013/10/07 19:29:56
Yeah, I think I would also prefer to work on boole
sugoi1
2013/10/08 20:23:10
Done.
| |
| 42 if (!fError) { | |
| 43 fReader.setMemory(data, size); | |
| 44 } | |
| 45 } | |
| 46 | |
| 47 const void* SkValidatingReadBuffer::skip(size_t size) { | |
| 48 size_t inc = SkAlign4(size); | |
|
mtklein
2013/10/07 19:29:56
const size_t inc, and below
sugoi1
2013/10/08 20:23:10
Done.
| |
| 49 const void* addr = fReader.peek(); | |
| 50 fError |= !IsPtrAlign4(addr) || !fReader.isAvailable(inc); | |
| 51 if (!fError) { | |
| 52 fReader.skip(size); | |
| 53 } | |
| 54 return addr; | |
| 55 } | |
| 56 | |
| 57 // All the methods in this file funnel down into either readInt() or skip() foll owed by a memcpy. | |
| 58 // So we've got all our validation in readInt() and skip(); if they fail they'll return a zero | |
| 59 // value or skip nothing, respectively. | |
|
mtklein
2013/10/07 19:29:56
And I guess ReadScalar? Add a note about how they
sugoi1
2013/10/08 20:23:10
Done.
| |
| 60 | |
| 61 bool SkValidatingReadBuffer::readBool() { | |
| 62 return this->readInt() != 0; | |
| 63 } | |
| 64 | |
| 65 SkColor SkValidatingReadBuffer::readColor() { | |
| 66 return this->readInt(); | |
| 67 } | |
| 68 | |
| 69 SkFixed SkValidatingReadBuffer::readFixed() { | |
| 70 return this->readInt(); | |
| 71 } | |
| 72 | |
| 73 int32_t SkValidatingReadBuffer::readInt() { | |
| 74 size_t inc = sizeof(int32_t); | |
| 75 fError |= !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); | |
| 76 return fError ? 0 : fReader.readInt(); | |
| 77 } | |
| 78 | |
| 79 SkScalar SkValidatingReadBuffer::readScalar() { | |
| 80 size_t inc = sizeof(SkScalar); | |
| 81 fError |= !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); | |
| 82 return fError ? 0 : fReader.readScalar(); | |
| 83 } | |
| 84 | |
| 85 uint32_t SkValidatingReadBuffer::readUInt() { | |
| 86 return this->readInt(); | |
| 87 } | |
| 88 | |
| 89 int32_t SkValidatingReadBuffer::read32() { | |
| 90 return this->readInt(); | |
| 91 } | |
| 92 | |
| 93 void SkValidatingReadBuffer::readString(SkString* string) { | |
| 94 size_t len = this->readInt(); | |
| 95 const void* ptr = fReader.peek(); | |
| 96 | |
| 97 // skip over the string + '\0' and then pad to a multiple of 4 | |
| 98 size_t alignedSize = SkAlign4(len + 1); | |
| 99 this->skip(alignedSize); | |
| 100 if (!fError) { | |
| 101 string->set((const char*)ptr, len); | |
| 102 } | |
|
mtklein
2013/10/07 19:29:56
Shouldn't we be checking that there is indeed an \
sugoi1
2013/10/08 20:23:10
I added a check. Doesn't hurt to be extra careful.
| |
| 103 } | |
| 104 | |
| 105 void* SkValidatingReadBuffer::readEncodedString(size_t* length, SkPaint::TextEnc oding encoding) { | |
| 106 int32_t encodingType = fReader.readInt(); | |
| 107 if (encodingType == encoding) { | |
| 108 fError = true; | |
|
mtklein
2013/10/07 19:29:56
for consistency, fError ||= (encodingType == encod
sugoi1
2013/10/08 20:23:10
That was a mistake. Fixed it by writing :
fError =
| |
| 109 } | |
| 110 *length = this->readInt(); | |
| 111 const void* ptr = this->skip(SkAlign4(*length)); | |
| 112 void* data = NULL; | |
| 113 if (!fError) { | |
| 114 data = sk_malloc_throw(*length); | |
| 115 memcpy(data, ptr, *length); | |
| 116 } | |
| 117 return data; | |
| 118 } | |
| 119 | |
| 120 void SkValidatingReadBuffer::readPoint(SkPoint* point) { | |
| 121 point->fX = fReader.readScalar(); | |
| 122 point->fY = fReader.readScalar(); | |
| 123 } | |
| 124 | |
| 125 void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) { | |
| 126 size_t size = matrix->readFromMemory(fReader.peek()); | |
|
mtklein
2013/10/07 19:29:56
Don't we need to skip this memory first to make su
sugoi1
2013/10/08 20:23:10
Chicken and egg problem. Right now, we don't know
| |
| 127 fError |= (SkAlign4(size) != size); | |
| 128 if (!fError) { | |
| 129 (void)this->skip(size); | |
| 130 } | |
| 131 } | |
| 132 | |
| 133 void SkValidatingReadBuffer::readIRect(SkIRect* rect) { | |
| 134 memcpy(rect, this->skip(sizeof(SkIRect)), sizeof(SkIRect)); | |
|
mtklein
2013/10/07 19:29:56
I'm not sure I understand the failure strategy of
sugoi1
2013/10/08 20:23:10
Right, fixed.
| |
| 135 } | |
| 136 | |
| 137 void SkValidatingReadBuffer::readRect(SkRect* rect) { | |
| 138 memcpy(rect, this->skip(sizeof(SkRect)), sizeof(SkRect)); | |
| 139 } | |
| 140 | |
| 141 void SkValidatingReadBuffer::readRegion(SkRegion* region) { | |
| 142 size_t size = region->readFromMemory(fReader.peek()); | |
| 143 fError |= (SkAlign4(size) != size); | |
| 144 if (!fError) { | |
| 145 (void)this->skip(size); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 void SkValidatingReadBuffer::readPath(SkPath* path) { | |
| 150 size_t size = path->readFromMemory(fReader.peek()); | |
| 151 fError |= (SkAlign4(size) != size); | |
| 152 if (!fError) { | |
| 153 (void)this->skip(size); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 uint32_t SkValidatingReadBuffer::readByteArray(void* value) { | |
| 158 const uint32_t length = this->readUInt(); | |
| 159 memcpy(value, this->skip(SkAlign4(length)), length); | |
| 160 return fError ? 0 : length; | |
| 161 } | |
| 162 | |
| 163 uint32_t SkValidatingReadBuffer::readColorArray(SkColor* colors) { | |
| 164 const uint32_t count = this->readUInt(); | |
| 165 const uint32_t byteLength = count * sizeof(SkColor); | |
| 166 memcpy(colors, this->skip(SkAlign4(byteLength)), byteLength); | |
| 167 return fError ? 0 : count; | |
| 168 } | |
| 169 | |
| 170 uint32_t SkValidatingReadBuffer::readIntArray(int32_t* values) { | |
| 171 const uint32_t count = this->readUInt(); | |
| 172 const uint32_t byteLength = count * sizeof(int32_t); | |
| 173 memcpy(values, this->skip(SkAlign4(byteLength)), byteLength); | |
| 174 return fError ? 0 : count; | |
| 175 } | |
| 176 | |
| 177 uint32_t SkValidatingReadBuffer::readPointArray(SkPoint* points) { | |
| 178 const uint32_t count = this->readUInt(); | |
| 179 const uint32_t byteLength = count * sizeof(SkPoint); | |
| 180 memcpy(points, this->skip(SkAlign4(byteLength)), byteLength); | |
| 181 return fError ? 0 : count; | |
| 182 } | |
| 183 | |
| 184 uint32_t SkValidatingReadBuffer::readScalarArray(SkScalar* values) { | |
| 185 const uint32_t count = this->readUInt(); | |
| 186 const uint32_t byteLength = count * sizeof(SkScalar); | |
| 187 memcpy(values, this->skip(SkAlign4(byteLength)), byteLength); | |
| 188 return fError ? 0 : count; | |
| 189 } | |
| 190 | |
| 191 uint32_t SkValidatingReadBuffer::getArrayCount() { | |
| 192 return *(uint32_t*)fReader.peek(); | |
| 193 } | |
| 194 | |
| 195 void SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) { | |
| 196 const int width = this->readInt(); | |
| 197 const int height = this->readInt(); | |
| 198 const size_t length = this->readUInt(); | |
| 199 // A size of zero means the SkBitmap was simply flattened. | |
| 200 if (length != 0) { | |
|
mtklein
2013/10/07 19:29:56
fError ||= (length != 0); ?
sugoi1
2013/10/08 20:23:10
Done.
| |
| 201 fError = true; | |
| 202 } | |
| 203 if (fError) { | |
| 204 return; | |
| 205 } | |
| 206 bitmap->unflatten(*this); | |
| 207 if ((bitmap->width() != width) || (bitmap->height() != height)) { | |
| 208 fError = true; | |
| 209 } | |
| 210 } | |
| 211 | |
| 212 SkFlattenable* SkValidatingReadBuffer::readFlattenable(const char* baseClassName ) { | |
| 213 SkString name; | |
| 214 this->readString(&name); | |
| 215 if (fError) { | |
| 216 return NULL; | |
| 217 } | |
| 218 | |
| 219 // Is this the type we wanted ? | |
| 220 const char* cname = name.c_str(); | |
| 221 if (fError || !SkFlattenable::TypeIsA(cname, baseClassName)) { | |
| 222 return NULL; | |
| 223 } | |
| 224 | |
| 225 SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname); | |
| 226 if (NULL == factory) { | |
| 227 return NULL; // writer failed to give us the flattenable | |
| 228 } | |
| 229 | |
| 230 // if we get here, factory may still be null, but if that is the case, the | |
| 231 // failure was ours, not the writer. | |
| 232 SkFlattenable* obj = NULL; | |
| 233 uint32_t sizeRecorded = this->readUInt(); | |
| 234 if (factory) { | |
| 235 uint32_t offset = fReader.offset(); | |
| 236 obj = (*factory)(*this); | |
| 237 // check that we read the amount we expected | |
| 238 uint32_t sizeRead = fReader.offset() - offset; | |
| 239 if (sizeRecorded != sizeRead) { | |
| 240 // we could try to fix up the offset... | |
| 241 fError = true; | |
| 242 delete obj; | |
| 243 obj = NULL; | |
| 244 } | |
| 245 } else { | |
| 246 // we must skip the remaining data | |
| 247 this->skip(sizeRecorded); | |
| 248 SkASSERT(false); | |
| 249 } | |
| 250 return obj; | |
| 251 } | |
| OLD | NEW |