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
21 namespace {
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:
EmptyImageGenerator(const SkImageInfo & info)26 EmptyImageGenerator(const SkImageInfo& info) : INHERITED(info) { }
27
28 private:
29 using INHERITED = SkImageGenerator;
30 };
31
MakeEmptyImage(int width,int height)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
setMemory(const void * data,size_t size)39 void 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
setInvalid()47 void 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
skip(size_t size)55 const 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
skip(size_t count,size_t size)68 const void* SkReadBuffer::skip(size_t count, size_t size) {
69 return this->skip(SkSafeMath::Mul(count, size));
70 }
71
setDeserialProcs(const SkDeserialProcs & procs)72 void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
73 fProcs = procs;
74 }
75
readBool()76 bool 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
readColor()83 SkColor SkReadBuffer::readColor() {
84 return this->readUInt();
85 }
86
readInt()87 int32_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
readScalar()97 SkScalar 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
readUInt()107 uint32_t SkReadBuffer::readUInt() {
108 return this->readInt();
109 }
110
read32()111 int32_t SkReadBuffer::read32() {
112 return this->readInt();
113 }
114
peekByte()115 uint8_t SkReadBuffer::peekByte() {
116 if (this->available() <= 0) {
117 fError = true;
118 return 0;
119 }
120 return *((uint8_t*)fCurr);
121 }
122
readPad32(void * buffer,size_t bytes)123 bool 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
readString(size_t * len)133 const 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
readString(SkString * string)145 void 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
readColor4f(SkColor4f * color)154 void SkReadBuffer::readColor4f(SkColor4f* color) {
155 if (!this->readPad32(color, sizeof(SkColor4f))) {
156 *color = {0, 0, 0, 0};
157 }
158 }
159
readPoint(SkPoint * point)160 void SkReadBuffer::readPoint(SkPoint* point) {
161 point->fX = this->readScalar();
162 point->fY = this->readScalar();
163 }
164
readPoint3(SkPoint3 * point)165 void SkReadBuffer::readPoint3(SkPoint3* point) {
166 this->readPad32(point, sizeof(SkPoint3));
167 }
168
read(SkM44 * matrix)169 void 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
readMatrix(SkMatrix * matrix)180 void 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
readIRect(SkIRect * rect)192 void SkReadBuffer::readIRect(SkIRect* rect) {
193 if (!this->readPad32(rect, sizeof(SkIRect))) {
194 rect->setEmpty();
195 }
196 }
197
readRect(SkRect * rect)198 void SkReadBuffer::readRect(SkRect* rect) {
199 if (!this->readPad32(rect, sizeof(SkRect))) {
200 rect->setEmpty();
201 }
202 }
203
readRect()204 SkRect SkReadBuffer::readRect() {
205 SkRect r;
206 if (!this->readPad32(&r, sizeof(SkRect))) {
207 r.setEmpty();
208 }
209 return r;
210 }
211
readSampling()212 SkSamplingOptions 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
readRRect(SkRRect * rrect)224 void 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
readRegion(SkRegion * region)235 void 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
readPath(SkPath * path)246 void 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
readArray(void * value,size_t size,size_t elementSize)257 bool 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
readByteArray(void * value,size_t size)263 bool SkReadBuffer::readByteArray(void* value, size_t size) {
264 return this->readArray(value, size, sizeof(uint8_t));
265 }
266
readColorArray(SkColor * colors,size_t size)267 bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
268 return this->readArray(colors, size, sizeof(SkColor));
269 }
270
readColor4fArray(SkColor4f * colors,size_t size)271 bool SkReadBuffer::readColor4fArray(SkColor4f* colors, size_t size) {
272 return this->readArray(colors, size, sizeof(SkColor4f));
273 }
274
readIntArray(int32_t * values,size_t size)275 bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
276 return this->readArray(values, size, sizeof(int32_t));
277 }
278
readPointArray(SkPoint * points,size_t size)279 bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) {
280 return this->readArray(points, size, sizeof(SkPoint));
281 }
282
readScalarArray(SkScalar * values,size_t size)283 bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
284 return this->readArray(values, size, sizeof(SkScalar));
285 }
286
skipByteArray(size_t * size)287 const 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
readByteArrayAsData()296 sk_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
getArrayCount()309 uint32_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.
readImage()321 sk_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
readTypeface()368 sk_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
readFlattenable(SkFlattenable::Type ft)392 SkFlattenable* 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
checkInt(int32_t min,int32_t max)461 int32_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
checkFilterQuality()471 SkLegacyFQ SkReadBuffer::checkFilterQuality() {
472 return this->checkRange<SkLegacyFQ>(kNone_SkLegacyFQ, kLast_SkLegacyFQ);
473 }
474