Checking structure sizes before reading them from memory to avoid overflowing the buffer's stream.
BUG= R=reed@google.com Committed: https://code.google.com/p/skia/source/detail?r=12114 Review URL: https://codereview.chromium.org/41253002 git-svn-id: http://skia.googlecode.com/svn/trunk@12119 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
ac9d306a92
commit
b48a59ae81
@ -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;)
|
||||
|
@ -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]).
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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,18 @@ 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());
|
||||
size_t sizeRead = 0;
|
||||
if (buffer.isValid()) {
|
||||
SkDEBUGCODE(this->validate();)
|
||||
sizeRead = buffer.pos();
|
||||
}
|
||||
return sizeRead;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -118,8 +118,11 @@ void SkValidatingReadBuffer::readPoint(SkPoint* point) {
|
||||
}
|
||||
|
||||
void SkValidatingReadBuffer::readMatrix(SkMatrix* matrix) {
|
||||
const size_t size = matrix->readFromMemory(fReader.peek());
|
||||
this->validate(SkAlign4(size) == size);
|
||||
size_t size = 0;
|
||||
if (!fError) {
|
||||
size = matrix->readFromMemory(fReader.peek(), fReader.available());
|
||||
this->validate((SkAlign4(size) != size) || (0 == size));
|
||||
}
|
||||
if (!fError) {
|
||||
(void)this->skip(size);
|
||||
}
|
||||
@ -140,16 +143,22 @@ void SkValidatingReadBuffer::readRect(SkRect* rect) {
|
||||
}
|
||||
|
||||
void SkValidatingReadBuffer::readRegion(SkRegion* region) {
|
||||
const size_t size = region->readFromMemory(fReader.peek());
|
||||
this->validate(SkAlign4(size) == size);
|
||||
size_t size = 0;
|
||||
if (!fError) {
|
||||
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);
|
||||
size_t size = 0;
|
||||
if (!fError) {
|
||||
size = path->readFromMemory(fReader.peek(), fReader.available());
|
||||
this->validate((SkAlign4(size) != size) || (0 == size));
|
||||
}
|
||||
if (!fError) {
|
||||
(void)this->skip(size);
|
||||
}
|
||||
@ -189,6 +198,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();
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -9,140 +9,202 @@
|
||||
#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);
|
||||
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);
|
||||
}
|
||||
|
||||
template<typename T> struct SerializationUtils {
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
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);
|
||||
uint32_t bytesWritten = writer.bytesWritten();
|
||||
// This should write the length (in 4 bytes) and the array
|
||||
REPORTER_ASSERT(reporter, (4 + arraySize) == bytesWritten);
|
||||
|
||||
unsigned char dataWritten[1024];
|
||||
writer.writeToMemory(dataWritten);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) {
|
||||
return reader.readByteArray(data, arraySize);
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
static const uint32_t arraySize = 64;
|
||||
SkColor data[arraySize];
|
||||
SkOrderedWriteBuffer writer(1024);
|
||||
writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag);
|
||||
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);
|
||||
|
||||
unsigned char dataWritten[1024];
|
||||
writer.writeToMemory(dataWritten);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) {
|
||||
return reader.readColorArray(data, arraySize);
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
static const uint32_t arraySize = 64;
|
||||
int32_t data[arraySize];
|
||||
SkOrderedWriteBuffer writer(1024);
|
||||
writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag);
|
||||
template<> struct SerializationUtils<int32_t> {
|
||||
static void Write(SkOrderedWriteBuffer& writer, int32_t* data, uint32_t arraySize) {
|
||||
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);
|
||||
|
||||
unsigned char dataWritten[1024];
|
||||
writer.writeToMemory(dataWritten);
|
||||
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
}
|
||||
static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) {
|
||||
return reader.readIntArray(data, arraySize);
|
||||
}
|
||||
};
|
||||
|
||||
{
|
||||
static const uint32_t arraySize = 64;
|
||||
SkPoint data[arraySize];
|
||||
SkOrderedWriteBuffer writer(1024);
|
||||
writer.setFlags(SkOrderedWriteBuffer::kValidation_Flag);
|
||||
template<> struct SerializationUtils<SkPoint> {
|
||||
static void Write(SkOrderedWriteBuffer& writer, SkPoint* data, uint32_t arraySize) {
|
||||
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);
|
||||
}
|
||||
static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) {
|
||||
return reader.readPointArray(data, arraySize);
|
||||
}
|
||||
};
|
||||
|
||||
unsigned char dataWritten[1024];
|
||||
writer.writeToMemory(dataWritten);
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
// 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);
|
||||
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();
|
||||
REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
|
||||
|
||||
// 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);
|
||||
unsigned char dataWritten[1024];
|
||||
writer.writeToMemory(dataWritten);
|
||||
|
||||
// Make sure this fails when it should (test with smaller size, but still multiple of 4)
|
||||
SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4);
|
||||
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
|
||||
{
|
||||
SkMatrix matrix = SkMatrix::I();
|
||||
TestObjectSerialization(&matrix, reporter);
|
||||
}
|
||||
|
||||
// Test path serialization
|
||||
{
|
||||
SkPath path;
|
||||
TestObjectSerialization(&path, reporter);
|
||||
}
|
||||
|
||||
// Test region serialization
|
||||
{
|
||||
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);
|
||||
SkRegion region;
|
||||
TestObjectSerialization(®ion, reporter);
|
||||
}
|
||||
|
||||
unsigned char dataWritten[1024];
|
||||
writer.writeToMemory(dataWritten);
|
||||
// Test rrect serialization
|
||||
{
|
||||
SkRRect rrect;
|
||||
TestAlignment(&rrect, reporter);
|
||||
}
|
||||
|
||||
// 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);
|
||||
// Test readByteArray
|
||||
{
|
||||
unsigned char data[kArraySize] = {0};
|
||||
TestArraySerialization(data, reporter);
|
||||
}
|
||||
|
||||
// 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);
|
||||
// Test readColorArray
|
||||
{
|
||||
SkColor data[kArraySize];
|
||||
TestArraySerialization(data, reporter);
|
||||
}
|
||||
|
||||
// Test readIntArray
|
||||
{
|
||||
int32_t data[kArraySize];
|
||||
TestArraySerialization(data, reporter);
|
||||
}
|
||||
|
||||
// Test readPointArray
|
||||
{
|
||||
SkPoint data[kArraySize];
|
||||
TestArraySerialization(data, reporter);
|
||||
}
|
||||
|
||||
// Test readScalarArray
|
||||
{
|
||||
SkScalar data[kArraySize];
|
||||
TestArraySerialization(data, reporter);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user