13218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org/*
23218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org * Copyright 2013 Google Inc.
33218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org *
43218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org * Use of this source code is governed by a BSD-style license that can be
53218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org * found in the LICENSE file.
63218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org */
73218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
83218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org#include "SkBitmap.h"
93218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org#include "SkErrorInternals.h"
103218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org#include "SkValidatingReadBuffer.h"
113218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org#include "SkStream.h"
123218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org#include "SkTypeface.h"
133218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1424cb5def8c993a224c1d9af53e9cdbc28e3e5105commit-bot@chromium.orgSkValidatingReadBuffer::SkValidatingReadBuffer(const void* data, size_t size) :
1524cb5def8c993a224c1d9af53e9cdbc28e3e5105commit-bot@chromium.org    fError(false) {
163218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    this->setMemory(data, size);
173218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    this->setFlags(SkFlattenableReadBuffer::kValidation_Flag);
183218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
193218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
203218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgSkValidatingReadBuffer::~SkValidatingReadBuffer() {
213218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
223218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
23ae553db4c7e96b5de88a78c8d195f34f8ea94d8ecommit-bot@chromium.orgbool SkValidatingReadBuffer::validate(bool isValid) {
24863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    if (!fError && !isValid) {
25863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org        // When an error is found, send the read cursor to the end of the stream
26863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org        fReader.skip(fReader.available());
27863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org        fError = true;
28863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    }
29ae553db4c7e96b5de88a78c8d195f34f8ea94d8ecommit-bot@chromium.org    return !fError;
30863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org}
31863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org
32ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.orgbool SkValidatingReadBuffer::isValid() const {
33ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org    return !fError;
34ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org}
35ce9b6b24ac76aa0494ca27509a215d4abb5640e2commit-bot@chromium.org
363218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::setMemory(const void* data, size_t size) {
37863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(IsPtrAlign4(data) && (SkAlign4(size) == size));
383218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
393218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        fReader.setMemory(data, size);
403218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
413218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
423218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
433218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgconst void* SkValidatingReadBuffer::skip(size_t size) {
443218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    size_t inc = SkAlign4(size);
453218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const void* addr = fReader.peek();
46863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(IsPtrAlign4(addr) && fReader.isAvailable(inc));
473218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
483218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        fReader.skip(size);
493218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
503218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return addr;
513218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
523218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
533218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org// All the methods in this file funnel down into either readInt(), readScalar() or skip(),
543218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org// followed by a memcpy. So we've got all our validation in readInt(), readScalar() and skip();
553218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org// if they fail they'll return a zero value or skip nothing, respectively, and set fError to
563218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org// true, which the caller should check to see if an error occurred during the read operation.
573218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
583218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgbool SkValidatingReadBuffer::readBool() {
59e58089fa3c17cad3d8836256218ccb1e6020cf54commit-bot@chromium.org    uint32_t value = this->readInt();
60e58089fa3c17cad3d8836256218ccb1e6020cf54commit-bot@chromium.org    // Boolean value should be either 0 or 1
61863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(!(value & ~1));
62e58089fa3c17cad3d8836256218ccb1e6020cf54commit-bot@chromium.org    return value != 0;
633218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
643218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
653218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgSkColor SkValidatingReadBuffer::readColor() {
663218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return this->readInt();
673218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
683218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
693218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgSkFixed SkValidatingReadBuffer::readFixed() {
703218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return this->readInt();
713218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
723218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
733218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgint32_t SkValidatingReadBuffer::readInt() {
743218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const size_t inc = sizeof(int32_t);
75863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
763218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return fError ? 0 : fReader.readInt();
773218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
783218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
793218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgSkScalar SkValidatingReadBuffer::readScalar() {
803218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const size_t inc = sizeof(SkScalar);
81863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(IsPtrAlign4(fReader.peek()) && fReader.isAvailable(inc));
823218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return fError ? 0 : fReader.readScalar();
833218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
843218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
853218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orguint32_t SkValidatingReadBuffer::readUInt() {
863218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return this->readInt();
873218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
883218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
893218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgint32_t SkValidatingReadBuffer::read32() {
903218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return this->readInt();
913218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
923218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
933218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readString(SkString* string) {
943218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const size_t len = this->readInt();
953218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const void* ptr = fReader.peek();
963218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const char* cptr = (const char*)ptr;
973218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
983218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    // skip over the string + '\0' and then pad to a multiple of 4
993218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const size_t alignedSize = SkAlign4(len + 1);
1003218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    this->skip(alignedSize);
101c700a801bd1e134ad713064bbcc6da9a074e5ebdcommit-bot@chromium.org    if (!fError) {
102c700a801bd1e134ad713064bbcc6da9a074e5ebdcommit-bot@chromium.org        this->validate(cptr[len] == '\0');
103c700a801bd1e134ad713064bbcc6da9a074e5ebdcommit-bot@chromium.org    }
1043218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1053218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        string->set(cptr, len);
1063218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1073218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1083218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1093218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid* SkValidatingReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
110c700a801bd1e134ad713064bbcc6da9a074e5ebdcommit-bot@chromium.org    const int32_t encodingType = this->readInt();
111863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(encodingType == encoding);
1123218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    *length = this->readInt();
1133218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const void* ptr = this->skip(SkAlign4(*length));
1143218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    void* data = NULL;
1153218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1163218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        data = sk_malloc_throw(*length);
1173218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        memcpy(data, ptr, *length);
1183218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1193218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return data;
1203218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1213218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1223218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readPoint(SkPoint* point) {
123c700a801bd1e134ad713064bbcc6da9a074e5ebdcommit-bot@chromium.org    point->fX = this->readScalar();
124c700a801bd1e134ad713064bbcc6da9a074e5ebdcommit-bot@chromium.org    point->fY = this->readScalar();
1253218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1263218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1273218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) {
1280c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    size_t size = 0;
1290c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    if (!fError) {
1300c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org        size = matrix->readFromMemory(fReader.peek(), fReader.available());
131ae553db4c7e96b5de88a78c8d195f34f8ea94d8ecommit-bot@chromium.org        this->validate((SkAlign4(size) == size) && (0 != size));
1320c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    }
1333218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1343218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        (void)this->skip(size);
1353218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1363218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1373218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1383218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readIRect(SkIRect* rect) {
1393218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const void* ptr = this->skip(sizeof(SkIRect));
1403218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1413218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        memcpy(rect, ptr, sizeof(SkIRect));
1423218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1433218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1443218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1453218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readRect(SkRect* rect) {
1463218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const void* ptr = this->skip(sizeof(SkRect));
1473218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1483218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        memcpy(rect, ptr, sizeof(SkRect));
1493218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1503218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1513218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1523218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readRegion(SkRegion* region) {
1530c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    size_t size = 0;
1540c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    if (!fError) {
1550c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org        size = region->readFromMemory(fReader.peek(), fReader.available());
156ae553db4c7e96b5de88a78c8d195f34f8ea94d8ecommit-bot@chromium.org        this->validate((SkAlign4(size) == size) && (0 != size));
1570c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    }
1583218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1593218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        (void)this->skip(size);
1603218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1613218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1623218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
1633218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readPath(SkPath* path) {
1640c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    size_t size = 0;
1650c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    if (!fError) {
1660c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org        size = path->readFromMemory(fReader.peek(), fReader.available());
167ae553db4c7e96b5de88a78c8d195f34f8ea94d8ecommit-bot@chromium.org        this->validate((SkAlign4(size) == size) && (0 != size));
1680c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    }
1693218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
1703218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        (void)this->skip(size);
1713218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
1723218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1733218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
174863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgbool SkValidatingReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
175863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    const uint32_t count = this->getArrayCount();
176863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(size == count);
177863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    (void)this->skip(sizeof(uint32_t)); // Skip array count
178863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    const size_t byteLength = count * elementSize;
179863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    const void* ptr = this->skip(SkAlign4(byteLength));
1803218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!fError) {
181863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org        memcpy(value, ptr, byteLength);
182863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org        return true;
1833218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
184863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return false;
1853218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1863218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
187863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgbool SkValidatingReadBuffer::readByteArray(void* value, size_t size) {
188863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
1893218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1903218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
191863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgbool SkValidatingReadBuffer::readColorArray(SkColor* colors, size_t size) {
192863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return readArray(colors, size, sizeof(SkColor));
1933218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1943218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
195863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgbool SkValidatingReadBuffer::readIntArray(int32_t* values, size_t size) {
196863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return readArray(values, size, sizeof(int32_t));
1973218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
1983218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
199863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgbool SkValidatingReadBuffer::readPointArray(SkPoint* points, size_t size) {
200863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return readArray(points, size, sizeof(SkPoint));
201863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org}
202863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org
203863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgbool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) {
204863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return readArray(values, size, sizeof(SkScalar));
2053218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
2063218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
2073218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orguint32_t SkValidatingReadBuffer::getArrayCount() {
2080c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    const size_t inc = sizeof(uint32_t);
2090c54a7b8945f1424f903279a94aef2280ec64aefcommit-bot@chromium.org    fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc);
2108793ad7e7045baaeed4c9bd6dde482961b527c47rmistry@google.com    return fError ? 0 : *(uint32_t*)fReader.peek();
2113218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
2123218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
2133218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgvoid SkValidatingReadBuffer::readBitmap(SkBitmap* bitmap) {
2143218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const int width = this->readInt();
2153218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const int height = this->readInt();
2163218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const size_t length = this->readUInt();
2173218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    // A size of zero means the SkBitmap was simply flattened.
218863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate(length == 0);
2193218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (fError) {
2203218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        return;
2213218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
2223218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    bitmap->unflatten(*this);
223863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    this->validate((bitmap->width() == width) && (bitmap->height() == height));
224863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org}
225863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org
226863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.orgSkTypeface* SkValidatingReadBuffer::readTypeface() {
227863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    // TODO: Implement this (securely) when needed
228863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org    return NULL;
2293218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
2303218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
2313218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.orgSkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type) {
2323218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    SkString name;
2333218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    this->readString(&name);
2343218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (fError) {
2353218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        return NULL;
2363218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
2373218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
2383218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    // Is this the type we wanted ?
2393218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    const char* cname = name.c_str();
2403218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    SkFlattenable::Type baseType;
2413218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (!SkFlattenable::NameToType(cname, &baseType) || (baseType != type)) {
2423218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        return NULL;
2433218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
2443218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
2453218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    SkFlattenable::Factory factory = SkFlattenable::NameToFactory(cname);
2463218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (NULL == factory) {
2473218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        return NULL; // writer failed to give us the flattenable
2483218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
2493218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org
2503218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    // if we get here, factory may still be null, but if that is the case, the
2513218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    // failure was ours, not the writer.
2523218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    SkFlattenable* obj = NULL;
2533218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    uint32_t sizeRecorded = this->readUInt();
2543218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    if (factory) {
2553218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        uint32_t offset = fReader.offset();
2563218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        obj = (*factory)(*this);
2573218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        // check that we read the amount we expected
2583218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        uint32_t sizeRead = fReader.offset() - offset;
259863cb3951e8da2d2eb8efd57c94d8f5ba069123ccommit-bot@chromium.org        this->validate(sizeRecorded == sizeRead);
2603218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        if (fError) {
2613218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org            // we could try to fix up the offset...
2623218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org            delete obj;
2633218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org            obj = NULL;
2643218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        }
2653218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    } else {
2663218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        // we must skip the remaining data
2673218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        this->skip(sizeRecorded);
2683218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org        SkASSERT(false);
2693218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    }
2703218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org    return obj;
2713218b023674b5d0bfc3eca0a6bd6800e24660b8ecommit-bot@chromium.org}
272