1c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org/*
2c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org * Copyright 2013 Google Inc.
3c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org *
4c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
5c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org * found in the LICENSE file.
6c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org */
7c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
8c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkBitmap.h"
9c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkErrorInternals.h"
10c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkValidatingReadBuffer.h"
11c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkStream.h"
12c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org#include "SkTypeface.h"
13c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
1477e079af1a909ee9d14306db48561d77e2f9fcabcommit-bot@chromium.orgSkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) :
1577e079af1a909ee9d14306db48561d77e2f9fcabcommit-bot@chromium.org    fError(false) {
16c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    this->setMemory(data, size);
178b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org    this->setFlags(SkReadBuffer::kValidation_Flag);
18c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
19c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
20c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgSkValidatingReadBuffer::~SkValidatingReadBuffer() {
21c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
22c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
238f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.orgbool SkValidatingReadBuffer::validate(bool isValid) {
24025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    if (!fError && !isValid) {
25025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        // When an error is found, send the read cursor to the end of the stream
26025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        fReader.skip(fReader.available());
27025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        fError = true;
28025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    }
298f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org    return !fError;
30025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org}
31025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org
32c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.orgbool SkValidatingReadBuffer::isValid() const {
33c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org    return !fError;
34c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org}
35c2e9db30d393862bd3485cfe57b4ac06433f2f32commit-bot@chromium.org
36c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::setMemory(const void* data, size_t size) {
37025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
38c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
39c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        fReader.setMemory(data, size);
40c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
41c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
42c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
43c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgconst void* SkValidatingReadBuffer::skip(size_t size) {
44c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    size_t inc = SkAlign4(size);
45c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const void* addr = fReader.peek();
46025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(IsPtrAlign4(addr) && fReader.isAvailable(inc));
47c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
48c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        fReader.skip(size);
49c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
50c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return addr;
51c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
52c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
53c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org// All the methods in this file funnel down into either readInt(), readScalar() or skip(),
54c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org// followed by a memcpy. So we've got all our validation in readInt(), readScalar() and skip();
55c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org// if they fail they'll return a zero value or skip nothing, respectively, and set fError to
56c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org// true, which the caller should check to see if an error occurred during the read operation.
57c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
58c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgbool SkValidatingReadBuffer::readBool() {
59d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    uint32_t value = this->readInt();
60d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    // Boolean value should be either 0 or 1
61025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(!(value & ~1));
62d594dbec0407343b7ac13af9c4580ec5933ab060commit-bot@chromium.org    return value != 0;
63c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
64c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
65c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgSkColor SkValidatingReadBuffer::readColor() {
66c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return this->readInt();
67c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
68c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
69c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgSkFixed SkValidatingReadBuffer::readFixed() {
70c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return this->readInt();
71c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
72c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
73c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgint32_t SkValidatingReadBuffer::readInt() {
74c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const size_t inc = sizeof(int32_t);
75025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
76c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return fError ? 0 : fReader.readInt();
77c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
78c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
79c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgSkScalar SkValidatingReadBuffer::readScalar() {
80c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const size_t inc = sizeof(SkScalar);
81025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
82c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return fError ? 0 : fReader.readScalar();
83c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
84c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
85c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orguint32_t SkValidatingReadBuffer::readUInt() {
86c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return this->readInt();
87c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
88c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
89c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgint32_t SkValidatingReadBuffer::read32() {
90c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return this->readInt();
91c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
92c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
93c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readString(SkString* string) {
941ac99c890b8afe957385a7625fd3b759f31be249commit-bot@chromium.org    const size_t len = this->readUInt();
95c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const void* ptr = fReader.peek();
96c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const char* cptr = (const char*)ptr;
97c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
98c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    // skip over the string + '\0' and then pad to a multiple of 4
99c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const size_t alignedSize = SkAlign4(len + 1);
100c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    this->skip(alignedSize);
10146a9bb8d71529e4a8c2ca9c68e280ea989d5bececommit-bot@chromium.org    if (!fError) {
10246a9bb8d71529e4a8c2ca9c68e280ea989d5bececommit-bot@chromium.org        this->validate(cptr[len] == '\0');
10346a9bb8d71529e4a8c2ca9c68e280ea989d5bececommit-bot@chromium.org    }
104c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
105c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        string->set(cptr, len);
106c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
107c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
108c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
109c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid* SkValidatingReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
11046a9bb8d71529e4a8c2ca9c68e280ea989d5bececommit-bot@chromium.org    const int32_t encodingType = this->readInt();
111025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(encodingType == encoding);
112c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    *length = this->readInt();
113c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const void* ptr = this->skip(SkAlign4(*length));
114c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    void* data = NULL;
115c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
116c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        data = sk_malloc_throw(*length);
117c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        memcpy(data, ptr, *length);
118c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
119c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return data;
120c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
121c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
122c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readPoint(SkPoint* point) {
12346a9bb8d71529e4a8c2ca9c68e280ea989d5bececommit-bot@chromium.org    point->fX = this->readScalar();
12446a9bb8d71529e4a8c2ca9c68e280ea989d5bececommit-bot@chromium.org    point->fY = this->readScalar();
125c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
126c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
127c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) {
1284faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t size = 0;
1294faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    if (!fError) {
1304faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        size = matrix->readFromMemory(fReader.peek(), fReader.available());
1318f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        this->validate((SkAlign4(size) == size) && (0 != size));
1324faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    }
133c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
134c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        (void)this->skip(size);
135c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
136c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
137c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
138c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readIRect(SkIRect* rect) {
139c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const void* ptr = this->skip(sizeof(SkIRect));
140c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
141c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        memcpy(rect, ptr, sizeof(SkIRect));
142c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
143c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
144c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
145c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readRect(SkRect* rect) {
146c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const void* ptr = this->skip(sizeof(SkRect));
147c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
148c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        memcpy(rect, ptr, sizeof(SkRect));
149c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
150c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
151c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
152c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readRegion(SkRegion* region) {
1534faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t size = 0;
1544faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    if (!fError) {
1554faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        size = region->readFromMemory(fReader.peek(), fReader.available());
1568f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        this->validate((SkAlign4(size) == size) && (0 != size));
1574faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    }
158c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
159c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        (void)this->skip(size);
160c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
161c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
162c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
163c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgvoid SkValidatingReadBuffer::readPath(SkPath* path) {
1644faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    size_t size = 0;
1654faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    if (!fError) {
1664faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org        size = path->readFromMemory(fReader.peek(), fReader.available());
1678f457e3230f1a4ce737f512ffbb5c919b8d02407commit-bot@chromium.org        this->validate((SkAlign4(size) == size) && (0 != size));
1684faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    }
169c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
170c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        (void)this->skip(size);
171c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
172c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
173c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
174025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
175025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    const uint32_t count = this->getArrayCount();
176025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    this->validate(size == count);
177025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    (void)this->skip(sizeof(uint32_t)); // Skip array count
178025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    const size_t byteLength = count * elementSize;
179025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    const void* ptr = this->skip(SkAlign4(byteLength));
180c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!fError) {
181025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        memcpy(value, ptr, byteLength);
182025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        return true;
183c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
184025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return false;
185c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
186c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
187025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readByteArray(void* value, size_t size) {
188025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
189c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
190c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
191025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readColorArray(SkColor* colors, size_t size) {
192025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return readArray(colors, size, sizeof(SkColor));
193c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
194c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
195025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readIntArray(int32_t* values, size_t size) {
196025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return readArray(values, size, sizeof(int32_t));
197c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
198c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
199025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readPointArray(SkPoint* points, size_t size) {
200025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return readArray(points, size, sizeof(SkPoint));
201025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org}
202025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org
203025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) {
204025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return readArray(values, size, sizeof(SkScalar));
205c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
206c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
207c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orguint32_t SkValidatingReadBuffer::getArrayCount() {
2084faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    const size_t inc = sizeof(uint32_t);
2094faa869cdabbdcf4867118b4a1272296baaeeb52commit-bot@chromium.org    fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
210d6bab0238655dbab24dfe92bd0b16b464310a8c7rmistry@google.com    return fError ? 0 : *(uint32_t*)fReader.peek();
211c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
212c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
213025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.orgSkTypeface* SkValidatingReadBuffer::readTypeface() {
214025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    // TODO: Implement this (securely) when needed
215025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org    return NULL;
216c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
217c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
218ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.orgbool SkValidatingReadBuffer::validateAvailable(size_t size) {
219ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org    return this->validate((size <= SK_MaxU32) && fReader.isAvailable(static_cast<uint32_t>(size)));
220ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org}
221ef74fa189b738e13295d6a96f86a6e10223505a8commit-bot@chromium.org
222c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.orgSkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) {
223c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    SkString name;
224c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    this->readString(&name);
225c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (fError) {
226c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        return NULL;
227c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
228c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
229c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    // Is this the type we wanted ?
230c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    const char* cname = name.c_str();
231c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    SkFlattenable::Type baseType;
232c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) {
233c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        return NULL;
234c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
235c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
236c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname);
237c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (NULL == factory) {
238c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        return NULL; // writer failed to give us the flattenable
239c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
240c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org
241c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    // if we get here, factory may still be null, but if that is the case, the
242c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    // failure was ours, not the writer.
243c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    SkFlattenable* obj = NULL;
244c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    uint32_t sizeRecorded = this->readUInt();
245c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    if (factory) {
246f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org        size_t offset = fReader.offset();
247c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        obj = (*factory)(*this);
248c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        // check that we read the amount we expected
249f117781362ecf673f43f93918781853690f0e145commit-bot@chromium.org        size_t sizeRead = fReader.offset() - offset;
250025128811219dc45fd99b6c4d1d14f833cf7a26ecommit-bot@chromium.org        this->validate(sizeRecorded == sizeRead);
251c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        if (fError) {
252c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org            // we could try to fix up the offset...
253c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org            delete obj;
254c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org            obj = NULL;
255c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        }
256c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    } else {
257c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        // we must skip the remaining data
258c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        this->skip(sizeRecorded);
259c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org        SkASSERT(false);
260c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    }
261c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org    return obj;
262c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cfcommit-bot@chromium.org}
26383f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org
26483f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.orgvoid SkValidatingReadBuffer::skipFlattenable() {
26583f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    SkString name;
26683f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    this->readString(&name);
26783f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    if (fError) {
26883f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org        return;
26983f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    }
27083f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    uint32_t sizeRecorded = this->readUInt();
27183f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org    this->skip(sizeRecorded);
27283f23d87f1d67e6e73873e1ef7cda621c43703a0commit-bot@chromium.org}
273