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