diff options
-rw-r--r-- | include/core/SkMatrix.h | 13 | ||||
-rw-r--r-- | include/core/SkPath.h | 15 | ||||
-rw-r--r-- | include/core/SkRRect.h | 16 | ||||
-rw-r--r-- | include/core/SkReader32.h | 32 | ||||
-rw-r--r-- | include/core/SkRegion.h | 13 | ||||
-rw-r--r-- | samplecode/SampleRegion.cpp | 2 | ||||
-rw-r--r-- | src/core/SkBuffer.cpp | 7 | ||||
-rw-r--r-- | src/core/SkBuffer.h | 26 | ||||
-rw-r--r-- | src/core/SkMatrix.cpp | 17 | ||||
-rw-r--r-- | src/core/SkPath.cpp | 14 | ||||
-rw-r--r-- | src/core/SkPicturePlayback.cpp | 3 | ||||
-rw-r--r-- | src/core/SkRRect.cpp | 8 | ||||
-rw-r--r-- | src/core/SkRegion.cpp | 22 | ||||
-rw-r--r-- | src/core/SkValidatingReadBuffer.cpp | 14 | ||||
-rw-r--r-- | tests/MatrixTest.cpp | 11 | ||||
-rw-r--r-- | tests/PathTest.cpp | 6 | ||||
-rw-r--r-- | tests/SerializationTest.cpp | 281 |
17 files changed, 314 insertions, 186 deletions
diff --git a/include/core/SkMatrix.h b/include/core/SkMatrix.h index b6856d103c..dad5ff92f5 100644 --- a/include/core/SkMatrix.h +++ b/include/core/SkMatrix.h @@ -559,9 +559,16 @@ public: kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t) }; // return the number of bytes written, whether or not buffer is null - uint32_t writeToMemory(void* buffer) const; - // return the number of bytes read - uint32_t readFromMemory(const void* buffer); + size_t writeToMemory(void* buffer) const; + /** + * Reads data from the buffer parameter + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available + */ + size_t readFromMemory(const void* buffer, size_t length); SkDEVCODE(void dump() const;) SkDEVCODE(void toString(SkString*) const;) diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 785eb7793f..2b111fe505 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -899,16 +899,19 @@ public: void dump() const; /** - * Write the region to the buffer, and return the number of bytes written. + * Write the path to the buffer, and return the number of bytes written. * If buffer is NULL, it still returns the number of bytes. */ - uint32_t writeToMemory(void* buffer) const; - + size_t writeToMemory(void* buffer) const; /** - * Initialized the region from the buffer, returning the number - * of bytes actually read. + * Initializes the path from the buffer + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available */ - uint32_t readFromMemory(const void* buffer); + size_t readFromMemory(const void* buffer, size_t length); /** Returns a non-zero, globally unique value corresponding to the set of verbs and points in the path (but not the fill type [except on Android skbug.com/1762]). diff --git a/include/core/SkRRect.h b/include/core/SkRRect.h index 402e6c6c4b..3c6386f1c6 100644 --- a/include/core/SkRRect.h +++ b/include/core/SkRRect.h @@ -244,14 +244,20 @@ public: * write kSizeInMemory bytes, and that value is guaranteed to always be * a multiple of 4. Return kSizeInMemory. */ - uint32_t writeToMemory(void* buffer) const; + size_t writeToMemory(void* buffer) const; /** - * Read the rrect from the specified buffer. This is guaranteed to always - * read kSizeInMemory bytes, and that value is guaranteed to always be - * a multiple of 4. Return kSizeInMemory. + * Reads the rrect from the specified buffer + * + * If the specified buffer is large enough, this will read kSizeInMemory bytes, + * and that value is guaranteed to always be a multiple of 4. + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available */ - uint32_t readFromMemory(const void* buffer); + size_t readFromMemory(const void* buffer, size_t length); private: SkRect fRect; diff --git a/include/core/SkReader32.h b/include/core/SkReader32.h index 7a8d22a80c..40ae12ce23 100644 --- a/include/core/SkReader32.h +++ b/include/core/SkReader32.h @@ -106,27 +106,20 @@ public: int32_t readS32() { return this->readInt(); } uint32_t readU32() { return this->readInt(); } - void readPath(SkPath* path) { - size_t size = path->readFromMemory(this->peek()); - SkASSERT(SkAlign4(size) == size); - (void)this->skip(size); + bool readPath(SkPath* path) { + return readObjectFromMemory(path); } - void readMatrix(SkMatrix* matrix) { - size_t size = matrix->readFromMemory(this->peek()); - SkASSERT(SkAlign4(size) == size); - (void)this->skip(size); + bool readMatrix(SkMatrix* matrix) { + return readObjectFromMemory(matrix); } - SkRRect* readRRect(SkRRect* rrect) { - rrect->readFromMemory(this->skip(SkRRect::kSizeInMemory)); - return rrect; + bool readRRect(SkRRect* rrect) { + return readObjectFromMemory(rrect); } - void readRegion(SkRegion* rgn) { - size_t size = rgn->readFromMemory(this->peek()); - SkASSERT(SkAlign4(size) == size); - (void)this->skip(size); + bool readRegion(SkRegion* rgn) { + return readObjectFromMemory(rgn); } /** @@ -143,6 +136,15 @@ public: size_t readIntoString(SkString* copy); private: + template <typename T> bool readObjectFromMemory(T* obj) { + size_t size = obj->readFromMemory(this->peek(), this->available()); + // If readFromMemory() fails (which means that available() was too small), it returns 0 + bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size); + // In case of failure, we want to skip to the end + (void)this->skip(success ? size : this->available()); + return success; + } + // these are always 4-byte aligned const char* fCurr; // current position within buffer const char* fStop; // end of buffer diff --git a/include/core/SkRegion.h b/include/core/SkRegion.h index a088d54620..c9aa8daf88 100644 --- a/include/core/SkRegion.h +++ b/include/core/SkRegion.h @@ -361,13 +361,16 @@ public: * Write the region to the buffer, and return the number of bytes written. * If buffer is NULL, it still returns the number of bytes. */ - uint32_t writeToMemory(void* buffer) const; - + size_t writeToMemory(void* buffer) const; /** - * Initialized the region from the buffer, returning the number - * of bytes actually read. + * Initializes the region from the buffer + * + * @param buffer Memory to read from + * @param length Amount of memory available in the buffer + * @return number of bytes read (must be a multiple of 4) or + * 0 if there was not enough memory available */ - uint32_t readFromMemory(const void* buffer); + size_t readFromMemory(const void* buffer, size_t length); /** * Returns a reference to a global empty region. Just a convenience for diff --git a/samplecode/SampleRegion.cpp b/samplecode/SampleRegion.cpp index 1bd316233f..39c27a8928 100644 --- a/samplecode/SampleRegion.cpp +++ b/samplecode/SampleRegion.cpp @@ -280,7 +280,7 @@ protected: SkASSERT(size == size2); SkRegion tmp3; - SkDEBUGCODE(size2 = ) tmp3.readFromMemory(buffer); + SkDEBUGCODE(size2 = ) tmp3.readFromMemory(buffer, 1000); SkASSERT(size == size2); SkASSERT(tmp3 == tmp); diff --git a/src/core/SkBuffer.cpp b/src/core/SkBuffer.cpp index 915264d957..32a8011ac7 100644 --- a/src/core/SkBuffer.cpp +++ b/src/core/SkBuffer.cpp @@ -34,6 +34,13 @@ size_t SkRBuffer::skipToAlign4() return n; } +void SkRBufferWithSizeCheck::read(void* buffer, size_t size) { + fError = fError || (fPos + size > fStop); + if (!fError && (size > 0)) { + readNoSizeCheck(buffer, size); + } +} + void* SkWBuffer::skip(size_t size) { void* result = fPos; diff --git a/src/core/SkBuffer.h b/src/core/SkBuffer.h index 9633389907..1a4c6c281c 100644 --- a/src/core/SkBuffer.h +++ b/src/core/SkBuffer.h @@ -56,7 +56,7 @@ public: /** Read the specified number of bytes from the data pointer. If buffer is not null, copy those bytes into buffer. */ - void read(void* buffer, size_t size) { + virtual void read(void* buffer, size_t size) { if (size) { this->readNoSizeCheck(buffer, size); } @@ -74,7 +74,7 @@ public: uint8_t readU8() { uint8_t x; read(&x, 1); return x; } bool readBool() { return this->readU8() != 0; } -private: +protected: void readNoSizeCheck(void* buffer, size_t size); const char* fData; @@ -82,6 +82,28 @@ private: const char* fStop; }; +/** \class SkRBufferWithSizeCheck + + Same as SkRBuffer, except that a size check is performed before the read operation and an + error is set if the read operation is attempting to read past the end of the data. +*/ +class SkRBufferWithSizeCheck : public SkRBuffer { +public: + SkRBufferWithSizeCheck(const void* data, size_t size) : SkRBuffer(data, size), fError(false) {} + + /** Read the specified number of bytes from the data pointer. If buffer is not + null and the number of bytes to read does not overflow this object's data, + copy those bytes into buffer. + */ + virtual void read(void* buffer, size_t size) SK_OVERRIDE; + + /** Returns whether or not a read operation attempted to read past the end of the data. + */ + bool isValid() const { return !fError; } +private: + bool fError; +}; + /** \class SkWBuffer Light weight class for writing data to a memory block. diff --git a/src/core/SkMatrix.cpp b/src/core/SkMatrix.cpp index 5bcb35b298..cd7bcea176 100644 --- a/src/core/SkMatrix.cpp +++ b/src/core/SkMatrix.cpp @@ -1921,20 +1921,25 @@ const SkMatrix& SkMatrix::InvalidMatrix() { /////////////////////////////////////////////////////////////////////////////// -uint32_t SkMatrix::writeToMemory(void* buffer) const { +size_t SkMatrix::writeToMemory(void* buffer) const { // TODO write less for simple matrices + static const size_t sizeInMemory = 9 * sizeof(SkScalar); if (buffer) { - memcpy(buffer, fMat, 9 * sizeof(SkScalar)); + memcpy(buffer, fMat, sizeInMemory); } - return 9 * sizeof(SkScalar); + return sizeInMemory; } -uint32_t SkMatrix::readFromMemory(const void* buffer) { +size_t SkMatrix::readFromMemory(const void* buffer, size_t length) { + static const size_t sizeInMemory = 9 * sizeof(SkScalar); + if (length < sizeInMemory) { + return 0; + } if (buffer) { - memcpy(fMat, buffer, 9 * sizeof(SkScalar)); + memcpy(fMat, buffer, sizeInMemory); this->setTypeMask(kUnknown_Mask); } - return 9 * sizeof(SkScalar); + return sizeInMemory; } #ifdef SK_DEVELOPER diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp index 60cfe0373c..982d6ad936 100644 --- a/src/core/SkPath.cpp +++ b/src/core/SkPath.cpp @@ -2066,7 +2066,7 @@ SkPath::Verb SkPath::RawIter::next(SkPoint pts[4]) { Format in compressed buffer: [ptCount, verbCount, pts[], verbs[]] */ -uint32_t SkPath::writeToMemory(void* storage) const { +size_t SkPath::writeToMemory(void* storage) const { SkDEBUGCODE(this->validate();) if (NULL == storage) { @@ -2090,11 +2090,11 @@ uint32_t SkPath::writeToMemory(void* storage) const { fPathRef->writeToBuffer(&buffer); buffer.padToAlign4(); - return SkToU32(buffer.pos()); + return buffer.pos(); } -uint32_t SkPath::readFromMemory(const void* storage) { - SkRBuffer buffer(storage); +size_t SkPath::readFromMemory(const void* storage, size_t length) { + SkRBufferWithSizeCheck buffer(storage, length); uint32_t packed = buffer.readS32(); fIsOval = (packed >> kIsOval_SerializationShift) & 1; @@ -2108,14 +2108,14 @@ uint32_t SkPath::readFromMemory(const void* storage) { fPathRef.reset(SkPathRef::CreateFromBuffer(&buffer #ifndef DELETE_THIS_CODE_WHEN_SKPS_ARE_REBUILT_AT_V14_AND_ALL_OTHER_INSTANCES_TOO - , newFormat, packed) + , newFormat, packed #endif - ); + )); buffer.skipToAlign4(); SkDEBUGCODE(this->validate();) - return SkToU32(buffer.pos()); + return buffer.isValid() ? buffer.pos() : 0; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp index f2d959d3d6..5a016d48d6 100644 --- a/src/core/SkPicturePlayback.cpp +++ b/src/core/SkPicturePlayback.cpp @@ -997,7 +997,8 @@ void SkPicturePlayback::draw(SkCanvas& canvas, SkDrawPictureCallback* callback) case DRAW_RRECT: { const SkPaint& paint = *getPaint(reader); SkRRect rrect; - canvas.drawRRect(*reader.readRRect(&rrect), paint); + reader.readRRect(&rrect); + canvas.drawRRect(rrect, paint); } break; case DRAW_SPRITE: { const SkPaint* paint = getPaint(reader); diff --git a/src/core/SkRRect.cpp b/src/core/SkRRect.cpp index e3d11cb01e..bcbf37ec59 100644 --- a/src/core/SkRRect.cpp +++ b/src/core/SkRRect.cpp @@ -259,7 +259,7 @@ void SkRRect::inset(SkScalar dx, SkScalar dy, SkRRect* dst) const { /////////////////////////////////////////////////////////////////////////////// -uint32_t SkRRect::writeToMemory(void* buffer) const { +size_t SkRRect::writeToMemory(void* buffer) const { SkASSERT(kSizeInMemory == sizeof(SkRect) + sizeof(fRadii)); memcpy(buffer, &fRect, sizeof(SkRect)); @@ -267,7 +267,11 @@ uint32_t SkRRect::writeToMemory(void* buffer) const { return kSizeInMemory; } -uint32_t SkRRect::readFromMemory(const void* buffer) { +size_t SkRRect::readFromMemory(const void* buffer, size_t length) { + if (length < kSizeInMemory) { + return 0; + } + SkScalar storage[12]; SkASSERT(sizeof(storage) == kSizeInMemory); diff --git a/src/core/SkRegion.cpp b/src/core/SkRegion.cpp index 02994bffb0..468be67154 100644 --- a/src/core/SkRegion.cpp +++ b/src/core/SkRegion.cpp @@ -1100,9 +1100,9 @@ bool SkRegion::op(const SkRegion& rgna, const SkRegion& rgnb, Op op) { #include "SkBuffer.h" -uint32_t SkRegion::writeToMemory(void* storage) const { +size_t SkRegion::writeToMemory(void* storage) const { if (NULL == storage) { - uint32_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount + size_t size = sizeof(int32_t); // -1 (empty), 0 (rect), runCount if (!this->isEmpty()) { size += sizeof(fBounds); if (this->isComplex()) { @@ -1133,11 +1133,11 @@ uint32_t SkRegion::writeToMemory(void* storage) const { return buffer.pos(); } -uint32_t SkRegion::readFromMemory(const void* storage) { - SkRBuffer buffer(storage); - SkRegion tmp; - int32_t count; - +size_t SkRegion::readFromMemory(const void* storage, size_t length) { + SkRBufferWithSizeCheck buffer(storage, length); + SkRegion tmp; + int32_t count; + count = buffer.readS32(); if (count >= 0) { buffer.read(&tmp.fBounds, sizeof(tmp.fBounds)); @@ -1150,8 +1150,12 @@ uint32_t SkRegion::readFromMemory(const void* storage) { buffer.read(tmp.fRunHead->writable_runs(), count * sizeof(RunType)); } } - this->swap(tmp); - return buffer.pos(); + size_t sizeRead = 0; + if (buffer.isValid()) { + this->swap(tmp); + sizeRead = buffer.pos(); + } + return sizeRead; } /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkValidatingReadBuffer.cpp b/src/core/SkValidatingReadBuffer.cpp index 9f094f9617..384dd10b30 100644 --- a/src/core/SkValidatingReadBuffer.cpp +++ b/src/core/SkValidatingReadBuffer.cpp @@ -118,8 +118,8 @@ void SkValidatingReadBuffer::readPoint(SkPoint* point) { } void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) { - const size_t size = matrix->readFromMemory(fReader.peek()); - this->validate(SkAlign4(size) == size); + const size_t size = matrix->readFromMemory(fReader.peek(), fReader.available()); + this->validate((SkAlign4(size) != size) || (0 == size)); if (!fError) { (void)this->skip(size); } @@ -140,16 +140,16 @@ void SkValidatingReadBuffer::readRect(SkRect* rect) { } void SkValidatingReadBuffer::readRegion(SkRegion* region) { - const size_t size = region->readFromMemory(fReader.peek()); - this->validate(SkAlign4(size) == size); + const size_t size = region->readFromMemory(fReader.peek(), fReader.available()); + this->validate((SkAlign4(size) != size) || (0 == size)); if (!fError) { (void)this->skip(size); } } void SkValidatingReadBuffer::readPath(SkPath* path) { - const size_t size = path->readFromMemory(fReader.peek()); - this->validate(SkAlign4(size) == size); + const size_t size = path->readFromMemory(fReader.peek(), fReader.available()); + this->validate((SkAlign4(size) != size) || (0 == size)); if (!fError) { (void)this->skip(size); } @@ -189,6 +189,8 @@ bool SkValidatingReadBuffer::readScalarArray(SkScalar* values, size_t size) { } uint32_t SkValidatingReadBuffer::getArrayCount() { + const size_t inc = sizeof(uint32_t); + fError = fError || !IsPtrAlign4(fReader.peek()) || !fReader.isAvailable(inc); return *(uint32_t*)fReader.peek(); } diff --git a/tests/MatrixTest.cpp b/tests/MatrixTest.cpp index 07eacb6f44..e9886941eb 100644 --- a/tests/MatrixTest.cpp +++ b/tests/MatrixTest.cpp @@ -112,18 +112,19 @@ static void test_matrix_recttorect(skiatest::Reporter* reporter) { static void test_flatten(skiatest::Reporter* reporter, const SkMatrix& m) { // add 100 in case we have a bug, I don't want to kill my stack in the test - char buffer[SkMatrix::kMaxFlattenSize + 100]; - uint32_t size1 = m.writeToMemory(NULL); - uint32_t size2 = m.writeToMemory(buffer); + static const size_t kBufferSize = SkMatrix::kMaxFlattenSize + 100; + char buffer[kBufferSize]; + size_t size1 = m.writeToMemory(NULL); + size_t size2 = m.writeToMemory(buffer); REPORTER_ASSERT(reporter, size1 == size2); REPORTER_ASSERT(reporter, size1 <= SkMatrix::kMaxFlattenSize); SkMatrix m2; - uint32_t size3 = m2.readFromMemory(buffer); + size_t size3 = m2.readFromMemory(buffer, kBufferSize); REPORTER_ASSERT(reporter, size1 == size3); REPORTER_ASSERT(reporter, are_equal(reporter, m, m2)); - char buffer2[SkMatrix::kMaxFlattenSize + 100]; + char buffer2[kBufferSize]; size3 = m2.writeToMemory(buffer2); REPORTER_ASSERT(reporter, size1 == size3); REPORTER_ASSERT(reporter, memcmp(buffer, buffer2, size1) == 0); diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp index d879ea6e33..f6c2a7ae6e 100644 --- a/tests/PathTest.cpp +++ b/tests/PathTest.cpp @@ -1808,12 +1808,12 @@ static void test_flattening(skiatest::Reporter* reporter) { // create a buffer that should be much larger than the path so we don't // kill our stack if writer goes too far. char buffer[1024]; - uint32_t size1 = p.writeToMemory(NULL); - uint32_t size2 = p.writeToMemory(buffer); + size_t size1 = p.writeToMemory(NULL); + size_t size2 = p.writeToMemory(buffer); REPORTER_ASSERT(reporter, size1 == size2); SkPath p2; - uint32_t size3 = p2.readFromMemory(buffer); + size_t size3 = p2.readFromMemory(buffer, 1024); REPORTER_ASSERT(reporter, size1 == size3); REPORTER_ASSERT(reporter, p == p2); diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp index d2c692526f..88b9fbbc2e 100644 --- a/tests/SerializationTest.cpp +++ b/tests/SerializationTest.cpp @@ -9,140 +9,201 @@ #include "SkValidatingReadBuffer.h" #include "Test.h" -static void Tests(skiatest::Reporter* reporter) { - { - static const uint32_t arraySize = 512; - unsigned char data[arraySize] = {0}; - SkOrderedWriteBuffer writer(1024); - writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); - writer.writeByteArray(data, arraySize); - uint32_t bytesWritten = writer.bytesWritten(); - // This should write the length (in 4 bytes) and the array - REPORTER_ASSERT(reporter, (4 + arraySize) == bytesWritten); +static const uint32_t kArraySize = 64; + +template<typename T> +static void TestAlignment(T* testObj, skiatest::Reporter* reporter) { + // Test memory read/write functions directly + unsigned char dataWritten[1024]; + size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten); + REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory); + size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory); + REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory); +} - unsigned char dataWritten[1024]; - writer.writeToMemory(dataWritten); +template<typename T> struct SerializationUtils { +}; - // Make sure this fails when it should - SkValidatingReadBuffer buffer(dataWritten, bytesWritten); - unsigned char dataRead[arraySize]; - bool success = buffer.readByteArray(dataRead, 256); - // This should have failed, since 256 < sizeInBytes - REPORTER_ASSERT(reporter, !success); +template<> struct SerializationUtils<SkMatrix> { + static void Write(SkOrderedWriteBuffer& writer, const SkMatrix* matrix) { + writer.writeMatrix(*matrix); + } + static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) { + reader.readMatrix(matrix); + } +}; - // Make sure this succeeds when it should - SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); - success = buffer2.readByteArray(dataRead, arraySize); - // This should have succeeded, since there are enough bytes to read this - REPORTER_ASSERT(reporter, success); +template<> struct SerializationUtils<SkPath> { + static void Write(SkOrderedWriteBuffer& writer, const SkPath* path) { + writer.writePath(*path); } + static void Read(SkValidatingReadBuffer& reader, SkPath* path) { + reader.readPath(path); + } +}; - { - static const uint32_t arraySize = 64; - SkColor data[arraySize]; - SkOrderedWriteBuffer writer(1024); - writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); +template<> struct SerializationUtils<SkRegion> { + static void Write(SkOrderedWriteBuffer& writer, const SkRegion* region) { + writer.writeRegion(*region); + } + static void Read(SkValidatingReadBuffer& reader, SkRegion* region) { + reader.readRegion(region); + } +}; + +template<> struct SerializationUtils<unsigned char> { + static void Write(SkOrderedWriteBuffer& writer, unsigned char* data, uint32_t arraySize) { + writer.writeByteArray(data, arraySize); + } + static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) { + return reader.readByteArray(data, arraySize); + } +}; + +template<> struct SerializationUtils<SkColor> { + static void Write(SkOrderedWriteBuffer& writer, SkColor* data, uint32_t arraySize) { writer.writeColorArray(data, arraySize); - uint32_t bytesWritten = writer.bytesWritten(); - // This should write the length (in 4 bytes) and the array - REPORTER_ASSERT(reporter, (4 + arraySize * sizeof(SkColor)) == bytesWritten); + } + static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) { + return reader.readColorArray(data, arraySize); + } +}; - unsigned char dataWritten[1024]; - writer.writeToMemory(dataWritten); +template<> struct SerializationUtils<int32_t> { + static void Write(SkOrderedWriteBuffer& writer, int32_t* data, uint32_t arraySize) { + writer.writeIntArray(data, arraySize); + } + static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) { + return reader.readIntArray(data, arraySize); + } +}; - // Make sure this fails when it should - SkValidatingReadBuffer buffer(dataWritten, bytesWritten); - SkColor dataRead[arraySize]; - bool success = buffer.readColorArray(dataRead, 32); - // This should have failed, since 256 < sizeInBytes - REPORTER_ASSERT(reporter, !success); +template<> struct SerializationUtils<SkPoint> { + static void Write(SkOrderedWriteBuffer& writer, SkPoint* data, uint32_t arraySize) { + writer.writePointArray(data, arraySize); + } + static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) { + return reader.readPointArray(data, arraySize); + } +}; - // Make sure this succeeds when it should - SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); - success = buffer2.readColorArray(dataRead, arraySize); - // This should have succeeded, since there are enough bytes to read this - REPORTER_ASSERT(reporter, success); +template<> struct SerializationUtils<SkScalar> { + static void Write(SkOrderedWriteBuffer& writer, SkScalar* data, uint32_t arraySize) { + writer.writeScalarArray(data, arraySize); + } + static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) { + return reader.readScalarArray(data, arraySize); } +}; + +template<typename T> +static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) { + SkOrderedWriteBuffer writer(1024); + writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); + SerializationUtils<T>::Write(writer, testObj); + size_t bytesWritten = writer.bytesWritten(); + + unsigned char dataWritten[1024]; + writer.writeToMemory(dataWritten); + + // Make sure this fails when it should + SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 1); + const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer.skip(0)); + SerializationUtils<T>::Read(buffer, testObj); + const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer.skip(0)); + // This should have failed, since the buffer is too small to read a matrix from it + REPORTER_ASSERT(reporter, peekBefore == peekAfter); + + // Make sure this succeeds when it should + SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); + peekBefore = static_cast<const unsigned char*>(buffer2.skip(0)); + SerializationUtils<T>::Read(buffer2, testObj); + peekAfter = static_cast<const unsigned char*>(buffer2.skip(0)); + // This should have succeeded, since there are enough bytes to read this + REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten); + + TestAlignment(testObj, reporter); +} + +template<typename T> +static void TestArraySerialization(T* data, skiatest::Reporter* reporter) { + SkOrderedWriteBuffer writer(1024); + writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); + SerializationUtils<T>::Write(writer, data, kArraySize); + size_t bytesWritten = writer.bytesWritten(); + // This should write the length (in 4 bytes) and the array + REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten); + + unsigned char dataWritten[1024]; + writer.writeToMemory(dataWritten); + + // Make sure this fails when it should + SkValidatingReadBuffer buffer(dataWritten, bytesWritten); + T dataRead[kArraySize]; + bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2); + // This should have failed, since the provided size was too small + REPORTER_ASSERT(reporter, !success); + + // Make sure this succeeds when it should + SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); + success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize); + // This should have succeeded, since there are enough bytes to read this + REPORTER_ASSERT(reporter, success); +} +static void Tests(skiatest::Reporter* reporter) { + // Test matrix serialization { - static const uint32_t arraySize = 64; - int32_t data[arraySize]; - SkOrderedWriteBuffer writer(1024); - writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); - writer.writeIntArray(data, arraySize); - uint32_t bytesWritten = writer.bytesWritten(); - // This should write the length (in 4 bytes) and the array - REPORTER_ASSERT(reporter, (4 + arraySize * sizeof(int32_t)) == bytesWritten); + SkMatrix matrix = SkMatrix::I(); + TestObjectSerialization(&matrix, reporter); + } - unsigned char dataWritten[1024]; - writer.writeToMemory(dataWritten); + // Test path serialization + { + SkPath path; + TestObjectSerialization(&path, reporter); + } - // Make sure this fails when it should - SkValidatingReadBuffer buffer(dataWritten, bytesWritten); - int32_t dataRead[arraySize]; - bool success = buffer.readIntArray(dataRead, 32); - // This should have failed, since 256 < sizeInBytes - REPORTER_ASSERT(reporter, !success); + // Test region serialization + { + SkRegion region; + TestObjectSerialization(®ion, reporter); + } - // Make sure this succeeds when it should - SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); - success = buffer2.readIntArray(dataRead, arraySize); - // This should have succeeded, since there are enough bytes to read this - REPORTER_ASSERT(reporter, success); + // Test rrect serialization + { + SkRRect rrect; + TestAlignment(&rrect, reporter); } + // Test readByteArray { - static const uint32_t arraySize = 64; - SkPoint data[arraySize]; - SkOrderedWriteBuffer writer(1024); - writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); - writer.writePointArray(data, arraySize); - uint32_t bytesWritten = writer.bytesWritten(); - // This should write the length (in 4 bytes) and the array - REPORTER_ASSERT(reporter, (4 + arraySize * sizeof(SkPoint)) == bytesWritten); + unsigned char data[kArraySize] = {0}; + TestArraySerialization(data, reporter); + } - unsigned char dataWritten[1024]; - writer.writeToMemory(dataWritten); + // Test readColorArray + { + SkColor data[kArraySize]; + TestArraySerialization(data, reporter); + } - // Make sure this fails when it should - SkValidatingReadBuffer buffer(dataWritten, bytesWritten); - SkPoint dataRead[arraySize]; - bool success = buffer.readPointArray(dataRead, 32); - // This should have failed, since 256 < sizeInBytes - REPORTER_ASSERT(reporter, !success); + // Test readIntArray + { + int32_t data[kArraySize]; + TestArraySerialization(data, reporter); + } - // Make sure this succeeds when it should - SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); - success = buffer2.readPointArray(dataRead, arraySize); - // This should have succeeded, since there are enough bytes to read this - REPORTER_ASSERT(reporter, success); + // Test readPointArray + { + SkPoint data[kArraySize]; + TestArraySerialization(data, reporter); } + // Test readScalarArray { - static const uint32_t arraySize = 64; - SkScalar data[arraySize]; - SkOrderedWriteBuffer writer(1024); - writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag); - writer.writeScalarArray(data, arraySize); - uint32_t bytesWritten = writer.bytesWritten(); - // This should write the length (in 4 bytes) and the array - REPORTER_ASSERT(reporter, (4 + arraySize * sizeof(SkScalar)) == bytesWritten); - - unsigned char dataWritten[1024]; - writer.writeToMemory(dataWritten); - - // Make sure this fails when it should - SkValidatingReadBuffer buffer(dataWritten, bytesWritten); - SkScalar dataRead[arraySize]; - bool success = buffer.readScalarArray(dataRead, 32); - // This should have failed, since 256 < sizeInBytes - REPORTER_ASSERT(reporter, !success); - - // Make sure this succeeds when it should - SkValidatingReadBuffer buffer2(dataWritten, bytesWritten); - success = buffer2.readScalarArray(dataRead, arraySize); - // This should have succeeded, since there are enough bytes to read this - REPORTER_ASSERT(reporter, success); + SkScalar data[kArraySize]; + TestArraySerialization(data, reporter); } } |