1/* 2 * Copyright 2012 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 "include/core/SkBitmap.h" 9#include "include/core/SkData.h" 10#include "include/core/SkImage.h" 11#include "include/core/SkImageGenerator.h" 12#include "include/core/SkStream.h" 13#include "include/core/SkTypeface.h" 14#include "src/core/SkAutoMalloc.h" 15#include "src/core/SkMathPriv.h" 16#include "src/core/SkMatrixPriv.h" 17#include "src/core/SkMipmapBuilder.h" 18#include "src/core/SkReadBuffer.h" 19#include "src/core/SkSafeMath.h" 20 21namespace { 22 // This generator intentionally should always fail on all attempts to get its pixels, 23 // simulating a bad or empty codec stream. 24 class EmptyImageGenerator final : public SkImageGenerator { 25 public: 26 EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { } 27 28 private: 29 using INHERITED = SkImageGenerator; 30 }; 31 32 static sk_sp<SkImage> MakeEmptyImage(int width, int height) { 33 return SkImage::MakeFromGenerator( 34 std::make_unique<EmptyImageGenerator>(SkImageInfo::MakeN32Premul(width, height))); 35 } 36 37} // anonymous namespace 38 39void SkReadBuffer::setMemory(const void* data, size_t size) { 40 this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size)); 41 if (!fError) { 42 fBase = fCurr = (const char*)data; 43 fStop = fBase + size; 44 } 45} 46 47void SkReadBuffer::setInvalid() { 48 if (!fError) { 49 // When an error is found, send the read cursor to the end of the stream 50 fCurr = fStop; 51 fError = true; 52 } 53} 54 55const void* SkReadBuffer::skip(size_t size) { 56 size_t inc = SkAlign4(size); 57 this->validate(inc >= size); 58 const void* addr = fCurr; 59 this->validate(IsPtrAlign4(addr) && this->isAvailable(inc)); 60 if (fError) { 61 return nullptr; 62 } 63 64 fCurr += inc; 65 return addr; 66} 67 68const void* SkReadBuffer::skip(size_t count, size_t size) { 69 return this->skip(SkSafeMath::Mul(count, size)); 70} 71 72void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) { 73 fProcs = procs; 74} 75 76bool SkReadBuffer::readBool() { 77 uint32_t value = this->readUInt(); 78 // Boolean value should be either 0 or 1 79 this->validate(!(value & ~1)); 80 return value != 0; 81} 82 83SkColor SkReadBuffer::readColor() { 84 return this->readUInt(); 85} 86 87int32_t SkReadBuffer::readInt() { 88 const size_t inc = sizeof(int32_t); 89 if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) { 90 return 0; 91 } 92 int32_t value = *((const int32_t*)fCurr); 93 fCurr += inc; 94 return value; 95} 96 97SkScalar SkReadBuffer::readScalar() { 98 const size_t inc = sizeof(SkScalar); 99 if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) { 100 return 0; 101 } 102 SkScalar value = *((const SkScalar*)fCurr); 103 fCurr += inc; 104 return value; 105} 106 107uint32_t SkReadBuffer::readUInt() { 108 return this->readInt(); 109} 110 111int32_t SkReadBuffer::read32() { 112 return this->readInt(); 113} 114 115uint8_t SkReadBuffer::peekByte() { 116 if (this->available() <= 0) { 117 fError = true; 118 return 0; 119 } 120 return *((uint8_t*)fCurr); 121} 122 123bool SkReadBuffer::readPad32(void* buffer, size_t bytes) { 124 if (const void* src = this->skip(bytes)) { 125 // buffer might be null if bytes is zero (see SkAutoMalloc), hence we call 126 // the careful version of memcpy. 127 sk_careful_memcpy(buffer, src, bytes); 128 return true; 129 } 130 return false; 131} 132 133const char* SkReadBuffer::readString(size_t* len) { 134 *len = this->readUInt(); 135 136 // The string is len characters and a terminating \0. 137 const char* c_str = this->skipT<char>(*len+1); 138 139 if (this->validate(c_str && c_str[*len] == '\0')) { 140 return c_str; 141 } 142 return nullptr; 143} 144 145void SkReadBuffer::readString(SkString* string) { 146 size_t len; 147 if (const char* c_str = this->readString(&len)) { 148 string->set(c_str, len); 149 return; 150 } 151 string->reset(); 152} 153 154void SkReadBuffer::readColor4f(SkColor4f* color) { 155 if (!this->readPad32(color, sizeof(SkColor4f))) { 156 *color = {0, 0, 0, 0}; 157 } 158} 159 160void SkReadBuffer::readPoint(SkPoint* point) { 161 point->fX = this->readScalar(); 162 point->fY = this->readScalar(); 163} 164 165void SkReadBuffer::readPoint3(SkPoint3* point) { 166 this->readPad32(point, sizeof(SkPoint3)); 167} 168 169void SkReadBuffer::read(SkM44* matrix) { 170 if (this->isValid()) { 171 if (const float* m = (const float*)this->skip(sizeof(float) * 16)) { 172 *matrix = SkM44::ColMajor(m); 173 } 174 } 175 if (!this->isValid()) { 176 *matrix = SkM44(); 177 } 178} 179 180void SkReadBuffer::readMatrix(SkMatrix* matrix) { 181 size_t size = 0; 182 if (this->isValid()) { 183 size = SkMatrixPriv::ReadFromMemory(matrix, fCurr, this->available()); 184 (void)this->validate((SkAlign4(size) == size) && (0 != size)); 185 } 186 if (!this->isValid()) { 187 matrix->reset(); 188 } 189 (void)this->skip(size); 190} 191 192void SkReadBuffer::readIRect(SkIRect* rect) { 193 if (!this->readPad32(rect, sizeof(SkIRect))) { 194 rect->setEmpty(); 195 } 196} 197 198void SkReadBuffer::readRect(SkRect* rect) { 199 if (!this->readPad32(rect, sizeof(SkRect))) { 200 rect->setEmpty(); 201 } 202} 203 204SkRect SkReadBuffer::readRect() { 205 SkRect r; 206 if (!this->readPad32(&r, sizeof(SkRect))) { 207 r.setEmpty(); 208 } 209 return r; 210} 211 212SkSamplingOptions SkReadBuffer::readSampling() { 213 if (this->readBool()) { 214 float B = this->readScalar(); 215 float C = this->readScalar(); 216 return SkSamplingOptions({B, C}); 217 } else { 218 SkFilterMode filter = this->read32LE(SkFilterMode::kLinear); 219 SkMipmapMode mipmap = this->read32LE(SkMipmapMode::kLinear); 220 return SkSamplingOptions(filter, mipmap); 221 } 222} 223 224void SkReadBuffer::readRRect(SkRRect* rrect) { 225 size_t size = 0; 226 if (!fError) { 227 size = rrect->readFromMemory(fCurr, this->available()); 228 if (!this->validate((SkAlign4(size) == size) && (0 != size))) { 229 rrect->setEmpty(); 230 } 231 } 232 (void)this->skip(size); 233} 234 235void SkReadBuffer::readRegion(SkRegion* region) { 236 size_t size = 0; 237 if (!fError) { 238 size = region->readFromMemory(fCurr, this->available()); 239 if (!this->validate((SkAlign4(size) == size) && (0 != size))) { 240 region->setEmpty(); 241 } 242 } 243 (void)this->skip(size); 244} 245 246void SkReadBuffer::readPath(SkPath* path) { 247 size_t size = 0; 248 if (!fError) { 249 size = path->readFromMemory(fCurr, this->available()); 250 if (!this->validate((SkAlign4(size) == size) && (0 != size))) { 251 path->reset(); 252 } 253 } 254 (void)this->skip(size); 255} 256 257bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) { 258 const uint32_t count = this->readUInt(); 259 return this->validate(size == count) && 260 this->readPad32(value, SkSafeMath::Mul(size, elementSize)); 261} 262 263bool SkReadBuffer::readByteArray(void* value, size_t size) { 264 return this->readArray(value, size, sizeof(uint8_t)); 265} 266 267bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) { 268 return this->readArray(colors, size, sizeof(SkColor)); 269} 270 271bool SkReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) { 272 return this->readArray(colors, size, sizeof(SkColor4f)); 273} 274 275bool SkReadBuffer::readIntArray(int32_t* values, size_t size) { 276 return this->readArray(values, size, sizeof(int32_t)); 277} 278 279bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) { 280 return this->readArray(points, size, sizeof(SkPoint)); 281} 282 283bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) { 284 return this->readArray(values, size, sizeof(SkScalar)); 285} 286 287const void* SkReadBuffer::skipByteArray(size_t* size) { 288 const uint32_t count = this->readUInt(); 289 const void* buf = this->skip(count); 290 if (size) { 291 *size = this->isValid() ? count : 0; 292 } 293 return buf; 294} 295 296sk_sp<SkData> SkReadBuffer::readByteArrayAsData() { 297 size_t numBytes = this->getArrayCount(); 298 if (!this->validate(this->isAvailable(numBytes))) { 299 return nullptr; 300 } 301 302 SkAutoMalloc buffer(numBytes); 303 if (!this->readByteArray(buffer.get(), numBytes)) { 304 return nullptr; 305 } 306 return SkData::MakeFromMalloc(buffer.release(), numBytes); 307} 308 309uint32_t SkReadBuffer::getArrayCount() { 310 const size_t inc = sizeof(uint32_t); 311 if (!this->validate(IsPtrAlign4(fCurr) && this->isAvailable(inc))) { 312 return 0; 313 } 314 return *((uint32_t*)fCurr); 315} 316 317#include "src/core/SkMipmap.h" 318 319// If we see a corrupt stream, we return null (fail). If we just fail trying to decode 320// the image, we don't fail, but return a 1x1 empty image. 321sk_sp<SkImage> SkReadBuffer::readImage() { 322 uint32_t flags = this->read32(); 323 324 sk_sp<SkImage> image; 325 { 326 sk_sp<SkData> data = this->readByteArrayAsData(); 327 if (!data) { 328 this->validate(false); 329 return nullptr; 330 } 331 if (fProcs.fImageProc) { 332 image = fProcs.fImageProc(data->data(), data->size(), fProcs.fImageCtx); 333 } 334 if (!image) { 335 image = SkImage::MakeFromEncoded(std::move(data)); 336 } 337 } 338 339 if (flags & SkWriteBufferImageFlags::kHasSubsetRect) { 340 SkIRect subset; 341 this->readIRect(&subset); 342 if (image) { 343 image = image->makeSubset(subset); 344 } 345 } 346 347 if (flags & SkWriteBufferImageFlags::kHasMipmap) { 348 sk_sp<SkData> data = this->readByteArrayAsData(); 349 if (!data) { 350 this->validate(false); 351 return nullptr; 352 } 353 if (image) { 354 SkMipmapBuilder builder(image->imageInfo()); 355 if (SkMipmap::Deserialize(&builder, data->data(), data->size())) { 356 // TODO: need to make lazy images support mips 357 if (auto ri = image->makeRasterImage()) { 358 image = ri; 359 } 360 image = builder.attachTo(image); 361 SkASSERT(image); // withMipmaps should never return null 362 } 363 } 364 } 365 return image ? image : MakeEmptyImage(1, 1); 366} 367 368sk_sp<SkTypeface> SkReadBuffer::readTypeface() { 369 // Read 32 bits (signed) 370 // 0 -- return null (default font) 371 // >0 -- index 372 // <0 -- custom (serial procs) : negative size in bytes 373 374 int32_t index = this->read32(); 375 if (index == 0) { 376 return nullptr; 377 } else if (index > 0) { 378 if (!this->validate(index <= fTFCount)) { 379 return nullptr; 380 } 381 return fTFArray[index - 1]; 382 } else { // custom 383 size_t size = sk_negate_to_size_t(index); 384 const void* data = this->skip(size); 385 if (!this->validate(data != nullptr && fProcs.fTypefaceProc)) { 386 return nullptr; 387 } 388 return fProcs.fTypefaceProc(data, size, fProcs.fTypefaceCtx); 389 } 390} 391 392SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) { 393 SkFlattenable::Factory factory = nullptr; 394 395 if (fFactoryCount > 0) { 396 int32_t index = this->read32(); 397 if (0 == index || !this->isValid()) { 398 return nullptr; // writer failed to give us the flattenable 399 } 400 index -= 1; // we stored the index-base-1 401 if ((unsigned)index >= (unsigned)fFactoryCount) { 402 this->validate(false); 403 return nullptr; 404 } 405 factory = fFactoryArray[index]; 406 } else { 407 if (this->peekByte() != 0) { 408 // If the first byte is non-zero, the flattenable is specified by a string. 409 size_t ignored_length; 410 if (const char* name = this->readString(&ignored_length)) { 411 factory = SkFlattenable::NameToFactory(name); 412 fFlattenableDict.set(fFlattenableDict.count() + 1, factory); 413 } 414 } else { 415 // Read the index. We are guaranteed that the first byte 416 // is zeroed, so we must shift down a byte. 417 uint32_t index = this->readUInt() >> 8; 418 if (index == 0) { 419 return nullptr; // writer failed to give us the flattenable 420 } 421 422 if (SkFlattenable::Factory* found = fFlattenableDict.find(index)) { 423 factory = *found; 424 } 425 } 426 427 if (!this->validate(factory != nullptr)) { 428 return nullptr; 429 } 430 } 431 432 // if we get here, factory may still be null, but if that is the case, the 433 // failure was ours, not the writer. 434 sk_sp<SkFlattenable> obj; 435 uint32_t sizeRecorded = this->read32(); 436 if (factory) { 437 size_t offset = this->offset(); 438 obj = (*factory)(*this); 439 // check that we read the amount we expected 440 size_t sizeRead = this->offset() - offset; 441 if (sizeRecorded != sizeRead) { 442 this->validate(false); 443 return nullptr; 444 } 445 if (obj && obj->getFlattenableType() != ft) { 446 this->validate(false); 447 return nullptr; 448 } 449 } else { 450 // we must skip the remaining data 451 this->skip(sizeRecorded); 452 } 453 if (!this->isValid()) { 454 return nullptr; 455 } 456 return obj.release(); 457} 458 459/////////////////////////////////////////////////////////////////////////////////////////////////// 460 461int32_t SkReadBuffer::checkInt(int32_t min, int32_t max) { 462 SkASSERT(min <= max); 463 int32_t value = this->read32(); 464 if (value < min || value > max) { 465 this->validate(false); 466 value = min; 467 } 468 return value; 469} 470 471SkLegacyFQ SkReadBuffer::checkFilterQuality() { 472 return this->checkRange<SkLegacyFQ>(kNone_SkLegacyFQ, kLast_SkLegacyFQ); 473} 474