Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
/*
|
|
|
|
* Copyright 2013 Google Inc.
|
|
|
|
*
|
|
|
|
* Use of this source code is governed by a BSD-style license that can be
|
|
|
|
* found in the LICENSE file.
|
|
|
|
*/
|
|
|
|
|
2016-06-15 21:28:17 +00:00
|
|
|
#include "Resources.h"
|
2016-06-16 19:39:25 +00:00
|
|
|
#include "SkAnnotationKeys.h"
|
2013-12-04 17:06:49 +00:00
|
|
|
#include "SkCanvas.h"
|
2018-04-04 00:51:40 +00:00
|
|
|
#include "SkDashPathEffect.h"
|
2015-05-20 16:21:04 +00:00
|
|
|
#include "SkFixed.h"
|
|
|
|
#include "SkFontDescriptor.h"
|
2015-09-15 18:26:13 +00:00
|
|
|
#include "SkImage.h"
|
|
|
|
#include "SkImageSource.h"
|
2016-09-16 13:24:20 +00:00
|
|
|
#include "SkMakeUnique.h"
|
2013-12-04 17:06:49 +00:00
|
|
|
#include "SkMallocPixelRef.h"
|
2017-10-20 16:14:33 +00:00
|
|
|
#include "SkMatrixPriv.h"
|
2014-06-30 19:14:52 +00:00
|
|
|
#include "SkOSFile.h"
|
2017-12-06 21:09:20 +00:00
|
|
|
#include "SkReadBuffer.h"
|
2014-04-18 18:04:41 +00:00
|
|
|
#include "SkPictureRecorder.h"
|
2017-05-25 14:38:07 +00:00
|
|
|
#include "SkShaderBase.h"
|
2014-09-25 22:51:35 +00:00
|
|
|
#include "SkTableColorFilter.h"
|
2014-03-14 21:22:22 +00:00
|
|
|
#include "SkTemplates.h"
|
2018-04-04 00:51:40 +00:00
|
|
|
#include "SkTextBlob.h"
|
2014-06-30 19:14:52 +00:00
|
|
|
#include "SkTypeface.h"
|
2014-01-30 18:58:24 +00:00
|
|
|
#include "SkWriteBuffer.h"
|
2013-12-04 17:06:49 +00:00
|
|
|
#include "SkXfermodeImageFilter.h"
|
2016-06-16 19:39:25 +00:00
|
|
|
#include "sk_tool_utils.h"
|
2014-01-24 20:56:26 +00:00
|
|
|
#include "Test.h"
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
static const uint32_t kArraySize = 64;
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
static const int kBitmapSize = 256;
|
2013-11-05 15:46:56 +00:00
|
|
|
|
2017-10-20 16:14:33 +00:00
|
|
|
class SerializationTest {
|
|
|
|
public:
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
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);
|
|
|
|
}
|
2017-10-20 16:14:33 +00:00
|
|
|
};
|
2013-11-04 16:18:15 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<typename T> struct SerializationUtils {
|
2013-12-04 17:06:49 +00:00
|
|
|
// Generic case for flattenables
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, const T* flattenable) {
|
2013-12-04 17:06:49 +00:00
|
|
|
writer.writeFlattenable(flattenable);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static void Read(SkReadBuffer& reader, T** flattenable) {
|
2016-04-04 21:57:19 +00:00
|
|
|
*flattenable = (T*)reader.readFlattenable(T::GetFlattenableType());
|
2013-12-04 17:06:49 +00:00
|
|
|
}
|
2013-11-05 15:46:56 +00:00
|
|
|
};
|
2013-11-04 16:18:15 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<SkMatrix> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writeMatrix(*matrix);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static void Read(SkReadBuffer& reader, SkMatrix* matrix) {
|
2013-11-05 15:46:56 +00:00
|
|
|
reader.readMatrix(matrix);
|
|
|
|
}
|
|
|
|
};
|
2013-11-04 20:28:23 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<SkPath> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, const SkPath* path) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writePath(*path);
|
2013-11-04 20:28:23 +00:00
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static void Read(SkReadBuffer& reader, SkPath* path) {
|
2013-11-05 15:46:56 +00:00
|
|
|
reader.readPath(path);
|
|
|
|
}
|
|
|
|
};
|
2013-11-04 20:28:23 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<SkRegion> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, const SkRegion* region) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writeRegion(*region);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static void Read(SkReadBuffer& reader, SkRegion* region) {
|
2013-11-05 15:46:56 +00:00
|
|
|
reader.readRegion(region);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2014-04-29 15:35:23 +00:00
|
|
|
template<> struct SerializationUtils<SkString> {
|
|
|
|
static void Write(SkWriteBuffer& writer, const SkString* string) {
|
|
|
|
writer.writeString(string->c_str());
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static void Read(SkReadBuffer& reader, SkString* string) {
|
2014-04-29 15:35:23 +00:00
|
|
|
reader.readString(string);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<unsigned char> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writeByteArray(data, arraySize);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static bool Read(SkReadBuffer& reader, unsigned char* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
return reader.readByteArray(data, arraySize);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct SerializationUtils<SkColor> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) {
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
writer.writeColorArray(data, arraySize);
|
2013-11-05 15:46:56 +00:00
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static bool Read(SkReadBuffer& reader, SkColor* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
return reader.readColorArray(data, arraySize);
|
|
|
|
}
|
|
|
|
};
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2016-09-25 20:15:58 +00:00
|
|
|
template<> struct SerializationUtils<SkColor4f> {
|
|
|
|
static void Write(SkWriteBuffer& writer, SkColor4f* data, uint32_t arraySize) {
|
|
|
|
writer.writeColor4fArray(data, arraySize);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static bool Read(SkReadBuffer& reader, SkColor4f* data, uint32_t arraySize) {
|
2016-09-25 20:15:58 +00:00
|
|
|
return reader.readColor4fArray(data, arraySize);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<int32_t> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writeIntArray(data, arraySize);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static bool Read(SkReadBuffer& reader, int32_t* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
return reader.readIntArray(data, arraySize);
|
|
|
|
}
|
|
|
|
};
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<SkPoint> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writePointArray(data, arraySize);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static bool Read(SkReadBuffer& reader, SkPoint* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
return reader.readPointArray(data, arraySize);
|
|
|
|
}
|
|
|
|
};
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<> struct SerializationUtils<SkScalar> {
|
2014-01-30 18:58:24 +00:00
|
|
|
static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writeScalarArray(data, arraySize);
|
|
|
|
}
|
2017-12-06 21:09:20 +00:00
|
|
|
static bool Read(SkReadBuffer& reader, SkScalar* data, uint32_t arraySize) {
|
2013-11-05 15:46:56 +00:00
|
|
|
return reader.readScalarArray(data, arraySize);
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
}
|
2013-11-05 15:46:56 +00:00
|
|
|
};
|
|
|
|
|
2014-04-29 15:35:23 +00:00
|
|
|
template<typename T, bool testInvalid> struct SerializationTestUtils {
|
|
|
|
static void InvalidateData(unsigned char* data) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<> struct SerializationTestUtils<SkString, true> {
|
|
|
|
static void InvalidateData(unsigned char* data) {
|
|
|
|
data[3] |= 0x80; // Reverse sign of 1st integer
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename T, bool testInvalid>
|
|
|
|
static void TestObjectSerializationNoAlign(T* testObj, skiatest::Reporter* reporter) {
|
2016-05-04 18:06:28 +00:00
|
|
|
SkBinaryWriteBuffer writer;
|
2013-11-05 15:46:56 +00:00
|
|
|
SerializationUtils<T>::Write(writer, testObj);
|
|
|
|
size_t bytesWritten = writer.bytesWritten();
|
|
|
|
REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
|
|
|
|
|
|
|
|
unsigned char dataWritten[1024];
|
|
|
|
writer.writeToMemory(dataWritten);
|
|
|
|
|
2014-04-29 15:35:23 +00:00
|
|
|
SerializationTestUtils<T, testInvalid>::InvalidateData(dataWritten);
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Make sure this fails when it should (test with smaller size, but still multiple of 4)
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer buffer(dataWritten, bytesWritten - 4);
|
2013-11-08 19:22:57 +00:00
|
|
|
T obj;
|
|
|
|
SerializationUtils<T>::Read(buffer, &obj);
|
2013-12-06 20:14:46 +00:00
|
|
|
REPORTER_ASSERT(reporter, !buffer.isValid());
|
2013-11-05 15:46:56 +00:00
|
|
|
|
|
|
|
// Make sure this succeeds when it should
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer buffer2(dataWritten, bytesWritten);
|
2016-09-26 13:00:36 +00:00
|
|
|
size_t offsetBefore = buffer2.offset();
|
2013-11-08 19:22:57 +00:00
|
|
|
T obj2;
|
|
|
|
SerializationUtils<T>::Read(buffer2, &obj2);
|
2016-09-26 13:00:36 +00:00
|
|
|
size_t offsetAfter = buffer2.offset();
|
2013-11-05 15:46:56 +00:00
|
|
|
// This should have succeeded, since there are enough bytes to read this
|
2014-04-29 15:35:23 +00:00
|
|
|
REPORTER_ASSERT(reporter, buffer2.isValid() == !testInvalid);
|
|
|
|
// Note: This following test should always succeed, regardless of whether the buffer is valid,
|
|
|
|
// since if it is invalid, it will simply skip to the end, as if it had read the whole buffer.
|
2016-09-26 13:00:36 +00:00
|
|
|
REPORTER_ASSERT(reporter, offsetAfter - offsetBefore == bytesWritten);
|
2014-04-29 15:35:23 +00:00
|
|
|
}
|
2013-11-05 15:46:56 +00:00
|
|
|
|
2014-04-29 15:35:23 +00:00
|
|
|
template<typename T>
|
|
|
|
static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) {
|
|
|
|
TestObjectSerializationNoAlign<T, false>(testObj, reporter);
|
2017-10-20 16:14:33 +00:00
|
|
|
SerializationTest::TestAlignment(testObj, reporter);
|
2013-11-05 15:46:56 +00:00
|
|
|
}
|
|
|
|
|
2013-12-04 17:06:49 +00:00
|
|
|
template<typename T>
|
|
|
|
static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed,
|
|
|
|
skiatest::Reporter* reporter) {
|
2016-05-04 18:06:28 +00:00
|
|
|
SkBinaryWriteBuffer writer;
|
2013-12-04 17:06:49 +00:00
|
|
|
SerializationUtils<T>::Write(writer, testObj);
|
|
|
|
size_t bytesWritten = writer.bytesWritten();
|
|
|
|
REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
|
|
|
|
|
2016-06-16 19:39:25 +00:00
|
|
|
SkASSERT(bytesWritten <= 4096);
|
2014-09-25 22:51:35 +00:00
|
|
|
unsigned char dataWritten[4096];
|
2013-12-04 17:06:49 +00:00
|
|
|
writer.writeToMemory(dataWritten);
|
|
|
|
|
|
|
|
// Make sure this fails when it should (test with smaller size, but still multiple of 4)
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer buffer(dataWritten, bytesWritten - 4);
|
2015-08-27 14:41:13 +00:00
|
|
|
T* obj = nullptr;
|
2013-12-04 17:06:49 +00:00
|
|
|
SerializationUtils<T>::Read(buffer, &obj);
|
2013-12-06 20:14:46 +00:00
|
|
|
REPORTER_ASSERT(reporter, !buffer.isValid());
|
2015-08-27 14:41:13 +00:00
|
|
|
REPORTER_ASSERT(reporter, nullptr == obj);
|
2013-12-04 17:06:49 +00:00
|
|
|
|
|
|
|
// Make sure this succeeds when it should
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer buffer2(dataWritten, bytesWritten);
|
2013-12-04 17:06:49 +00:00
|
|
|
const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0));
|
2015-08-27 14:41:13 +00:00
|
|
|
T* obj2 = nullptr;
|
2013-12-04 17:06:49 +00:00
|
|
|
SerializationUtils<T>::Read(buffer2, &obj2);
|
|
|
|
const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0));
|
|
|
|
if (shouldSucceed) {
|
|
|
|
// This should have succeeded, since there are enough bytes to read this
|
2013-12-06 20:14:46 +00:00
|
|
|
REPORTER_ASSERT(reporter, buffer2.isValid());
|
2013-12-04 17:06:49 +00:00
|
|
|
REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten);
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, obj2);
|
2013-12-04 17:06:49 +00:00
|
|
|
} else {
|
|
|
|
// If the deserialization was supposed to fail, make sure it did
|
2013-12-06 20:14:46 +00:00
|
|
|
REPORTER_ASSERT(reporter, !buffer.isValid());
|
2015-08-27 14:41:13 +00:00
|
|
|
REPORTER_ASSERT(reporter, nullptr == obj2);
|
2013-12-04 17:06:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return obj2; // Return object to perform further validity tests on it
|
|
|
|
}
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
template<typename T>
|
|
|
|
static void TestArraySerialization(T* data, skiatest::Reporter* reporter) {
|
2016-05-04 18:06:28 +00:00
|
|
|
SkBinaryWriteBuffer writer;
|
2013-11-05 15:46:56 +00:00
|
|
|
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);
|
|
|
|
|
2016-09-25 20:15:58 +00:00
|
|
|
unsigned char dataWritten[2048];
|
2013-11-05 15:46:56 +00:00
|
|
|
writer.writeToMemory(dataWritten);
|
|
|
|
|
|
|
|
// Make sure this fails when it should
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer buffer(dataWritten, bytesWritten);
|
2013-11-05 15:46:56 +00:00
|
|
|
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
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer buffer2(dataWritten, bytesWritten);
|
2013-11-05 15:46:56 +00:00
|
|
|
success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize);
|
|
|
|
// This should have succeeded, since there are enough bytes to read this
|
|
|
|
REPORTER_ASSERT(reporter, success);
|
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-12-04 17:06:49 +00:00
|
|
|
static void TestBitmapSerialization(const SkBitmap& validBitmap,
|
|
|
|
const SkBitmap& invalidBitmap,
|
|
|
|
bool shouldSucceed,
|
|
|
|
skiatest::Reporter* reporter) {
|
2016-03-17 17:51:11 +00:00
|
|
|
sk_sp<SkImage> validImage(SkImage::MakeFromBitmap(validBitmap));
|
2016-04-01 16:28:51 +00:00
|
|
|
sk_sp<SkImageFilter> validBitmapSource(SkImageSource::Make(std::move(validImage)));
|
2016-03-17 17:51:11 +00:00
|
|
|
sk_sp<SkImage> invalidImage(SkImage::MakeFromBitmap(invalidBitmap));
|
2016-04-01 16:28:51 +00:00
|
|
|
sk_sp<SkImageFilter> invalidBitmapSource(SkImageSource::Make(std::move(invalidImage)));
|
2016-03-29 18:32:50 +00:00
|
|
|
sk_sp<SkImageFilter> xfermodeImageFilter(
|
2016-10-06 00:33:02 +00:00
|
|
|
SkXfermodeImageFilter::Make(SkBlendMode::kSrcOver,
|
2016-04-05 19:48:34 +00:00
|
|
|
std::move(invalidBitmapSource),
|
|
|
|
std::move(validBitmapSource), nullptr));
|
2013-12-04 17:06:49 +00:00
|
|
|
|
2016-11-01 15:22:05 +00:00
|
|
|
sk_sp<SkImageFilter> deserializedFilter(
|
2013-12-04 17:06:49 +00:00
|
|
|
TestFlattenableSerialization<SkImageFilter>(
|
2016-03-29 18:32:50 +00:00
|
|
|
xfermodeImageFilter.get(), shouldSucceed, reporter));
|
2013-12-04 17:06:49 +00:00
|
|
|
|
|
|
|
// Try to render a small bitmap using the invalid deserialized filter
|
|
|
|
// to make sure we don't crash while trying to render it
|
|
|
|
if (shouldSucceed) {
|
|
|
|
SkBitmap bitmap;
|
2014-02-13 14:41:43 +00:00
|
|
|
bitmap.allocN32Pixels(24, 24);
|
|
|
|
SkCanvas canvas(bitmap);
|
2013-12-04 17:06:49 +00:00
|
|
|
canvas.clear(0x00000000);
|
|
|
|
SkPaint paint;
|
|
|
|
paint.setImageFilter(deserializedFilter);
|
|
|
|
canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24)));
|
|
|
|
canvas.drawBitmap(bitmap, 0, 0, &paint);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-25 22:51:35 +00:00
|
|
|
static void TestColorFilterSerialization(skiatest::Reporter* reporter) {
|
|
|
|
uint8_t table[256];
|
|
|
|
for (int i = 0; i < 256; ++i) {
|
|
|
|
table[i] = (i * 41) % 256;
|
|
|
|
}
|
2016-03-22 17:17:23 +00:00
|
|
|
auto colorFilter(SkTableColorFilter::Make(table));
|
2016-11-04 15:49:42 +00:00
|
|
|
sk_sp<SkColorFilter> copy(
|
2014-09-25 22:51:35 +00:00
|
|
|
TestFlattenableSerialization<SkColorFilter>(colorFilter.get(), true, reporter));
|
|
|
|
}
|
|
|
|
|
2014-06-30 19:14:52 +00:00
|
|
|
static SkBitmap draw_picture(SkPicture& picture) {
|
|
|
|
SkBitmap bitmap;
|
2016-03-29 16:03:52 +00:00
|
|
|
bitmap.allocN32Pixels(SkScalarCeilToInt(picture.cullRect().width()),
|
2014-08-29 15:03:56 +00:00
|
|
|
SkScalarCeilToInt(picture.cullRect().height()));
|
2014-06-30 19:14:52 +00:00
|
|
|
SkCanvas canvas(bitmap);
|
2014-09-04 15:42:50 +00:00
|
|
|
picture.playback(&canvas);
|
2014-06-30 19:14:52 +00:00
|
|
|
return bitmap;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void compare_bitmaps(skiatest::Reporter* reporter,
|
|
|
|
const SkBitmap& b1, const SkBitmap& b2) {
|
|
|
|
REPORTER_ASSERT(reporter, b1.width() == b2.width());
|
|
|
|
REPORTER_ASSERT(reporter, b1.height() == b2.height());
|
|
|
|
|
|
|
|
if ((b1.width() != b2.width()) ||
|
|
|
|
(b1.height() != b2.height())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
int pixelErrors = 0;
|
|
|
|
for (int y = 0; y < b2.height(); ++y) {
|
|
|
|
for (int x = 0; x < b2.width(); ++x) {
|
|
|
|
if (b1.getColor(x, y) != b2.getColor(x, y))
|
|
|
|
++pixelErrors;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
REPORTER_ASSERT(reporter, 0 == pixelErrors);
|
|
|
|
}
|
2016-05-12 17:09:30 +00:00
|
|
|
static void serialize_and_compare_typeface(sk_sp<SkTypeface> typeface, const char* text,
|
2015-05-20 16:21:04 +00:00
|
|
|
skiatest::Reporter* reporter)
|
|
|
|
{
|
|
|
|
// Create a paint with the typeface.
|
2014-06-30 19:14:52 +00:00
|
|
|
SkPaint paint;
|
|
|
|
paint.setColor(SK_ColorGRAY);
|
|
|
|
paint.setTextSize(SkIntToScalar(30));
|
2016-05-12 17:09:30 +00:00
|
|
|
paint.setTypeface(std::move(typeface));
|
2014-06-30 19:14:52 +00:00
|
|
|
|
|
|
|
// Paint some text.
|
|
|
|
SkPictureRecorder recorder;
|
|
|
|
SkIRect canvasRect = SkIRect::MakeWH(kBitmapSize, kBitmapSize);
|
2016-03-29 16:03:52 +00:00
|
|
|
SkCanvas* canvas = recorder.beginRecording(SkIntToScalar(canvasRect.width()),
|
|
|
|
SkIntToScalar(canvasRect.height()),
|
2015-08-27 14:41:13 +00:00
|
|
|
nullptr, 0);
|
2014-06-30 19:14:52 +00:00
|
|
|
canvas->drawColor(SK_ColorWHITE);
|
2015-05-20 16:21:04 +00:00
|
|
|
canvas->drawText(text, 2, 24, 32, paint);
|
2016-03-18 14:25:55 +00:00
|
|
|
sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture());
|
2014-06-30 19:14:52 +00:00
|
|
|
|
|
|
|
// Serlialize picture and create its clone from stream.
|
|
|
|
SkDynamicMemoryWStream stream;
|
|
|
|
picture->serialize(&stream);
|
2016-11-03 18:40:50 +00:00
|
|
|
std::unique_ptr<SkStream> inputStream(stream.detachAsStream());
|
2016-03-18 14:25:55 +00:00
|
|
|
sk_sp<SkPicture> loadedPicture(SkPicture::MakeFromStream(inputStream.get()));
|
2014-06-30 19:14:52 +00:00
|
|
|
|
|
|
|
// Draw both original and clone picture and compare bitmaps -- they should be identical.
|
|
|
|
SkBitmap origBitmap = draw_picture(*picture);
|
|
|
|
SkBitmap destBitmap = draw_picture(*loadedPicture);
|
|
|
|
compare_bitmaps(reporter, origBitmap, destBitmap);
|
|
|
|
}
|
|
|
|
|
2015-05-20 16:21:04 +00:00
|
|
|
static void TestPictureTypefaceSerialization(skiatest::Reporter* reporter) {
|
|
|
|
{
|
|
|
|
// Load typeface from file to test CreateFromFile with index.
|
2017-12-09 01:27:41 +00:00
|
|
|
auto data = GetResourceAsData("fonts/test.ttc");
|
|
|
|
auto typeface = SkTypeface::MakeFromStream(new SkMemoryStream(std::move(data)), 1);
|
2015-05-20 16:21:04 +00:00
|
|
|
if (!typeface) {
|
2016-02-25 01:59:16 +00:00
|
|
|
INFOF(reporter, "Could not run fontstream test because test.ttc not found.");
|
2015-05-20 16:21:04 +00:00
|
|
|
} else {
|
2016-05-12 17:09:30 +00:00
|
|
|
serialize_and_compare_typeface(std::move(typeface), "A!", reporter);
|
2015-05-20 16:21:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
// Load typeface as stream to create with axis settings.
|
2017-12-09 01:27:41 +00:00
|
|
|
std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("fonts/Distortable.ttf"));
|
2015-05-20 16:21:04 +00:00
|
|
|
if (!distortable) {
|
2016-02-25 01:59:16 +00:00
|
|
|
INFOF(reporter, "Could not run fontstream test because Distortable.ttf not found.");
|
2015-05-20 16:21:04 +00:00
|
|
|
} else {
|
|
|
|
SkFixed axis = SK_FixedSqrt2;
|
2016-05-12 17:09:30 +00:00
|
|
|
sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData(
|
2016-09-16 13:24:20 +00:00
|
|
|
skstd::make_unique<SkFontData>(std::move(distortable), 0, &axis, 1)));
|
2015-05-20 16:21:04 +00:00
|
|
|
if (!typeface) {
|
2016-02-25 01:59:16 +00:00
|
|
|
INFOF(reporter, "Could not run fontstream test because Distortable.ttf not created.");
|
2015-05-20 16:21:04 +00:00
|
|
|
} else {
|
2016-05-12 17:09:30 +00:00
|
|
|
serialize_and_compare_typeface(std::move(typeface), "abc", reporter);
|
2015-05-20 16:21:04 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-02 19:50:45 +00:00
|
|
|
static void setup_bitmap_for_canvas(SkBitmap* bitmap) {
|
|
|
|
bitmap->allocN32Pixels(kBitmapSize, kBitmapSize);
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
}
|
|
|
|
|
2014-09-02 19:50:45 +00:00
|
|
|
static void make_checkerboard_bitmap(SkBitmap& bitmap) {
|
|
|
|
setup_bitmap_for_canvas(&bitmap);
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
|
|
|
|
SkCanvas canvas(bitmap);
|
|
|
|
canvas.clear(0x00000000);
|
|
|
|
SkPaint darkPaint;
|
|
|
|
darkPaint.setColor(0xFF804020);
|
|
|
|
SkPaint lightPaint;
|
|
|
|
lightPaint.setColor(0xFF244484);
|
|
|
|
const int i = kBitmapSize / 8;
|
|
|
|
const SkScalar f = SkIntToScalar(i);
|
|
|
|
for (int y = 0; y < kBitmapSize; y += i) {
|
|
|
|
for (int x = 0; x < kBitmapSize; x += i) {
|
|
|
|
canvas.save();
|
|
|
|
canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
|
|
|
|
canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
|
|
|
|
canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
|
|
|
|
canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
|
|
|
|
canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
|
|
|
|
canvas.restore();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-09-02 19:50:45 +00:00
|
|
|
static void draw_something(SkCanvas* canvas) {
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
SkPaint paint;
|
|
|
|
SkBitmap bitmap;
|
2014-09-02 19:50:45 +00:00
|
|
|
make_checkerboard_bitmap(bitmap);
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
|
|
|
|
canvas->save();
|
|
|
|
canvas->scale(0.5f, 0.5f);
|
2015-08-27 14:41:13 +00:00
|
|
|
canvas->drawBitmap(bitmap, 0, 0, nullptr);
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
canvas->restore();
|
|
|
|
|
|
|
|
paint.setAntiAlias(true);
|
|
|
|
|
|
|
|
paint.setColor(SK_ColorRED);
|
|
|
|
canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint);
|
|
|
|
paint.setColor(SK_ColorBLACK);
|
|
|
|
paint.setTextSize(SkIntToScalar(kBitmapSize/3));
|
2017-04-28 19:35:12 +00:00
|
|
|
canvas->drawString("Picture", SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint);
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
}
|
|
|
|
|
2013-12-12 21:11:12 +00:00
|
|
|
DEF_TEST(Serialization, reporter) {
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test matrix serialization
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
{
|
2013-11-05 15:46:56 +00:00
|
|
|
SkMatrix matrix = SkMatrix::I();
|
|
|
|
TestObjectSerialization(&matrix, reporter);
|
2014-06-30 19:14:52 +00:00
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test path serialization
|
|
|
|
{
|
|
|
|
SkPath path;
|
|
|
|
TestObjectSerialization(&path, reporter);
|
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test region serialization
|
|
|
|
{
|
|
|
|
SkRegion region;
|
|
|
|
TestObjectSerialization(®ion, reporter);
|
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2014-09-25 22:51:35 +00:00
|
|
|
// Test color filter serialization
|
|
|
|
{
|
|
|
|
TestColorFilterSerialization(reporter);
|
|
|
|
}
|
|
|
|
|
2014-04-29 15:35:23 +00:00
|
|
|
// Test string serialization
|
|
|
|
{
|
|
|
|
SkString string("string");
|
|
|
|
TestObjectSerializationNoAlign<SkString, false>(&string, reporter);
|
|
|
|
TestObjectSerializationNoAlign<SkString, true>(&string, reporter);
|
|
|
|
}
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test rrect serialization
|
|
|
|
{
|
2013-12-02 13:50:38 +00:00
|
|
|
// SkRRect does not initialize anything.
|
|
|
|
// An uninitialized SkRRect can be serialized,
|
|
|
|
// but will branch on uninitialized data when deserialized.
|
2013-11-05 15:46:56 +00:00
|
|
|
SkRRect rrect;
|
2013-12-02 13:50:38 +00:00
|
|
|
SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30);
|
|
|
|
SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} };
|
|
|
|
rrect.setRectRadii(rect, corners);
|
2017-10-20 16:14:33 +00:00
|
|
|
SerializationTest::TestAlignment(&rrect, reporter);
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test readByteArray
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
{
|
2013-12-02 13:50:38 +00:00
|
|
|
unsigned char data[kArraySize] = { 1, 2, 3 };
|
2013-11-05 15:46:56 +00:00
|
|
|
TestArraySerialization(data, reporter);
|
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test readColorArray
|
|
|
|
{
|
2013-12-02 13:50:38 +00:00
|
|
|
SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED };
|
2013-11-05 15:46:56 +00:00
|
|
|
TestArraySerialization(data, reporter);
|
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2016-09-25 20:15:58 +00:00
|
|
|
// Test readColor4fArray
|
|
|
|
{
|
|
|
|
SkColor4f data[kArraySize] = {
|
|
|
|
SkColor4f::FromColor(SK_ColorBLACK),
|
|
|
|
SkColor4f::FromColor(SK_ColorWHITE),
|
|
|
|
SkColor4f::FromColor(SK_ColorRED),
|
|
|
|
{ 1.f, 2.f, 4.f, 8.f }
|
|
|
|
};
|
|
|
|
TestArraySerialization(data, reporter);
|
|
|
|
}
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test readIntArray
|
|
|
|
{
|
2013-12-02 13:50:38 +00:00
|
|
|
int32_t data[kArraySize] = { 1, 2, 4, 8 };
|
2013-11-05 15:46:56 +00:00
|
|
|
TestArraySerialization(data, reporter);
|
|
|
|
}
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test readPointArray
|
|
|
|
{
|
2013-12-02 13:50:38 +00:00
|
|
|
SkPoint data[kArraySize] = { {6, 7}, {42, 128} };
|
2013-11-05 15:46:56 +00:00
|
|
|
TestArraySerialization(data, reporter);
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
}
|
|
|
|
|
2013-11-05 15:46:56 +00:00
|
|
|
// Test readScalarArray
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
{
|
2013-12-02 13:50:38 +00:00
|
|
|
SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax };
|
2013-11-05 15:46:56 +00:00
|
|
|
TestArraySerialization(data, reporter);
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
}
|
2013-12-04 17:06:49 +00:00
|
|
|
|
|
|
|
// Test invalid deserializations
|
|
|
|
{
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
SkImageInfo info = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize);
|
2014-02-13 14:41:43 +00:00
|
|
|
|
2013-12-04 17:06:49 +00:00
|
|
|
SkBitmap validBitmap;
|
2014-05-30 13:26:10 +00:00
|
|
|
validBitmap.setInfo(info);
|
2013-12-04 17:06:49 +00:00
|
|
|
|
|
|
|
// Create a bitmap with a really large height
|
|
|
|
SkBitmap invalidBitmap;
|
2014-09-03 18:54:58 +00:00
|
|
|
invalidBitmap.setInfo(info.makeWH(info.width(), 1000000000));
|
2013-12-04 17:06:49 +00:00
|
|
|
|
|
|
|
// The deserialization should succeed, and the rendering shouldn't crash,
|
|
|
|
// even when the device fails to initialize, due to its size
|
|
|
|
TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter);
|
|
|
|
}
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
|
|
|
|
// Test simple SkPicture serialization
|
|
|
|
{
|
2014-04-13 19:09:42 +00:00
|
|
|
SkPictureRecorder recorder;
|
2014-09-02 19:50:45 +00:00
|
|
|
draw_something(recorder.beginRecording(SkIntToScalar(kBitmapSize),
|
|
|
|
SkIntToScalar(kBitmapSize),
|
2015-08-27 14:41:13 +00:00
|
|
|
nullptr, 0));
|
2016-03-18 14:25:55 +00:00
|
|
|
sk_sp<SkPicture> pict(recorder.finishRecordingAsPicture());
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
|
|
|
|
// Serialize picture
|
2016-05-04 18:06:28 +00:00
|
|
|
SkBinaryWriteBuffer writer;
|
2018-01-27 17:30:04 +00:00
|
|
|
pict->flatten(writer);
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
size_t size = writer.bytesWritten();
|
2014-03-14 21:22:22 +00:00
|
|
|
SkAutoTMalloc<unsigned char> data(size);
|
|
|
|
writer.writeToMemory(static_cast<void*>(data.get()));
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
|
|
|
|
// Deserialize picture
|
2017-12-06 21:09:20 +00:00
|
|
|
SkReadBuffer reader(static_cast<void*>(data.get()), size);
|
2016-03-18 14:25:55 +00:00
|
|
|
sk_sp<SkPicture> readPict(SkPicture::MakeFromBuffer(reader));
|
2016-09-30 16:27:20 +00:00
|
|
|
REPORTER_ASSERT(reporter, reader.isValid());
|
2014-09-05 20:34:00 +00:00
|
|
|
REPORTER_ASSERT(reporter, readPict.get());
|
Fixing SkPicture serialization
Fixed a few issues while attempting to use the new
serialization path for SkPicture inside a fuzzer:
- SkReadBuffer and SkValidatingReadBuffer both had a fReader
member instead of sharing the same member, which leads to
problems if a base class function is used
- In SkPicture, a header is now written as a single chunk of
data, so it also has to be read as a single chunk of data
- In the SkPicturePlayback destructor, a bad deserialization
would lead to a crash if we don't safely unref fOpData
- Also in SkPicturePlayback, if we only use a ReadBuffer for
the whole deserialization, additional tags must be added to
parseBufferTag()
- SkValidatingReadBuffer::readBitmap() was broken, but this
path wasn't usen't since the only use case for
SkValidatingReadBuffer is currently image filters and
bitmaps are unflattened as part of the deserialization of
SkBitmapSource
- SkPictureImageFilter was not deserializable. Added it to
SkGlobalInitialization*
- Added a test that exercises the SkPicture serialization /
deserialization code
BUG=skia:
R=senorblanco@google.com, senorblanco@chromium.org, reed@google.com, robertphillips@google.com
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/195223003
git-svn-id: http://skia.googlecode.com/svn/trunk@13764 2bbb7eff-a529-9590-31e7-b0007b416f81
2014-03-12 14:46:41 +00:00
|
|
|
}
|
2014-06-30 19:14:52 +00:00
|
|
|
|
|
|
|
TestPictureTypefaceSerialization(reporter);
|
Adding size parameter to read array functions
In some cases, the allocated array into which the data will be read is using getArrayCount() to allocate itself, which should be safe, but some cases use fixed length arrays or compute the array size before reading, which could overflow if the stream is compromised.
To prevent that from happening, I added a check that will verify that the number of bytes to read will not exceed the capacity of the input buffer argument passed to all the read...Array() functions.
I chose to use the byte array for this initial version, so that "size" represents the same value across all read...Array() functions, but I could also use the element count, if it is preferred.
Note : readPointArray and writePointArray are unused, so I could also remove them
BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org
Author: sugoi@chromium.org
Review URL: https://codereview.chromium.org/37803002
git-svn-id: http://skia.googlecode.com/svn/trunk@12058 2bbb7eff-a529-9590-31e7-b0007b416f81
2013-10-31 18:37:50 +00:00
|
|
|
}
|
2016-03-05 00:36:20 +00:00
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include "SkAnnotation.h"
|
|
|
|
|
2016-03-18 14:25:55 +00:00
|
|
|
static sk_sp<SkPicture> copy_picture_via_serialization(SkPicture* src) {
|
2016-03-05 00:36:20 +00:00
|
|
|
SkDynamicMemoryWStream wstream;
|
|
|
|
src->serialize(&wstream);
|
2016-11-03 18:40:50 +00:00
|
|
|
std::unique_ptr<SkStreamAsset> rstream(wstream.detachAsStream());
|
|
|
|
return SkPicture::MakeFromStream(rstream.get());
|
2016-03-05 00:36:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
struct AnnotationRec {
|
|
|
|
const SkRect fRect;
|
|
|
|
const char* fKey;
|
2016-08-02 21:40:46 +00:00
|
|
|
sk_sp<SkData> fValue;
|
2016-03-05 00:36:20 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
class TestAnnotationCanvas : public SkCanvas {
|
|
|
|
skiatest::Reporter* fReporter;
|
|
|
|
const AnnotationRec* fRec;
|
|
|
|
int fCount;
|
|
|
|
int fCurrIndex;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TestAnnotationCanvas(skiatest::Reporter* reporter, const AnnotationRec rec[], int count)
|
|
|
|
: SkCanvas(100, 100)
|
|
|
|
, fReporter(reporter)
|
|
|
|
, fRec(rec)
|
|
|
|
, fCount(count)
|
|
|
|
, fCurrIndex(0)
|
|
|
|
{}
|
|
|
|
|
|
|
|
~TestAnnotationCanvas() {
|
|
|
|
REPORTER_ASSERT(fReporter, fCount == fCurrIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
void onDrawAnnotation(const SkRect& rect, const char key[], SkData* value) {
|
|
|
|
REPORTER_ASSERT(fReporter, fCurrIndex < fCount);
|
|
|
|
REPORTER_ASSERT(fReporter, rect == fRec[fCurrIndex].fRect);
|
|
|
|
REPORTER_ASSERT(fReporter, !strcmp(key, fRec[fCurrIndex].fKey));
|
2016-08-02 21:40:46 +00:00
|
|
|
REPORTER_ASSERT(fReporter, value->equals(fRec[fCurrIndex].fValue.get()));
|
2016-03-05 00:36:20 +00:00
|
|
|
fCurrIndex += 1;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Test the 3 annotation types by recording them into a picture, serializing, and then playing
|
|
|
|
* them back into another canvas.
|
|
|
|
*/
|
|
|
|
DEF_TEST(Annotations, reporter) {
|
|
|
|
SkPictureRecorder recorder;
|
|
|
|
SkCanvas* recordingCanvas = recorder.beginRecording(SkRect::MakeWH(100, 100));
|
2016-03-29 16:03:52 +00:00
|
|
|
|
2016-03-05 00:36:20 +00:00
|
|
|
const char* str0 = "rect-with-url";
|
|
|
|
const SkRect r0 = SkRect::MakeWH(10, 10);
|
2016-08-02 21:40:46 +00:00
|
|
|
sk_sp<SkData> d0(SkData::MakeWithCString(str0));
|
|
|
|
SkAnnotateRectWithURL(recordingCanvas, r0, d0.get());
|
2016-03-29 16:03:52 +00:00
|
|
|
|
2016-03-05 00:36:20 +00:00
|
|
|
const char* str1 = "named-destination";
|
|
|
|
const SkRect r1 = SkRect::MakeXYWH(5, 5, 0, 0); // collapsed to a point
|
2016-08-02 21:40:46 +00:00
|
|
|
sk_sp<SkData> d1(SkData::MakeWithCString(str1));
|
|
|
|
SkAnnotateNamedDestination(recordingCanvas, {r1.x(), r1.y()}, d1.get());
|
2016-03-29 16:03:52 +00:00
|
|
|
|
2016-03-05 00:36:20 +00:00
|
|
|
const char* str2 = "link-to-destination";
|
|
|
|
const SkRect r2 = SkRect::MakeXYWH(20, 20, 5, 6);
|
2016-08-02 21:40:46 +00:00
|
|
|
sk_sp<SkData> d2(SkData::MakeWithCString(str2));
|
|
|
|
SkAnnotateLinkToDestination(recordingCanvas, r2, d2.get());
|
2016-03-05 00:36:20 +00:00
|
|
|
|
|
|
|
const AnnotationRec recs[] = {
|
2016-08-02 21:40:46 +00:00
|
|
|
{ r0, SkAnnotationKeys::URL_Key(), std::move(d0) },
|
|
|
|
{ r1, SkAnnotationKeys::Define_Named_Dest_Key(), std::move(d1) },
|
|
|
|
{ r2, SkAnnotationKeys::Link_Named_Dest_Key(), std::move(d2) },
|
2016-03-05 00:36:20 +00:00
|
|
|
};
|
|
|
|
|
2016-03-18 14:25:55 +00:00
|
|
|
sk_sp<SkPicture> pict0(recorder.finishRecordingAsPicture());
|
|
|
|
sk_sp<SkPicture> pict1(copy_picture_via_serialization(pict0.get()));
|
2016-03-05 00:36:20 +00:00
|
|
|
|
|
|
|
TestAnnotationCanvas canvas(reporter, recs, SK_ARRAY_COUNT(recs));
|
|
|
|
canvas.drawPicture(pict1);
|
|
|
|
}
|
2018-03-14 13:52:02 +00:00
|
|
|
|
|
|
|
DEF_TEST(WriteBuffer_storage, reporter) {
|
|
|
|
enum {
|
|
|
|
kSize = 32
|
|
|
|
};
|
|
|
|
int32_t storage[kSize/4];
|
|
|
|
char src[kSize];
|
|
|
|
sk_bzero(src, kSize);
|
|
|
|
|
|
|
|
SkBinaryWriteBuffer writer(storage, kSize);
|
|
|
|
REPORTER_ASSERT(reporter, writer.usingInitialStorage());
|
|
|
|
REPORTER_ASSERT(reporter, writer.bytesWritten() == 0);
|
|
|
|
writer.write(src, kSize - 4);
|
|
|
|
REPORTER_ASSERT(reporter, writer.usingInitialStorage());
|
|
|
|
REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize - 4);
|
|
|
|
writer.writeInt(0);
|
|
|
|
REPORTER_ASSERT(reporter, writer.usingInitialStorage());
|
|
|
|
REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize);
|
|
|
|
|
|
|
|
writer.reset(storage, kSize-4);
|
|
|
|
REPORTER_ASSERT(reporter, writer.usingInitialStorage());
|
|
|
|
REPORTER_ASSERT(reporter, writer.bytesWritten() == 0);
|
|
|
|
writer.write(src, kSize - 4);
|
|
|
|
REPORTER_ASSERT(reporter, writer.usingInitialStorage());
|
|
|
|
REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize - 4);
|
|
|
|
writer.writeInt(0);
|
|
|
|
REPORTER_ASSERT(reporter, !writer.usingInitialStorage()); // this is the change
|
|
|
|
REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize);
|
|
|
|
}
|
2018-04-04 00:51:40 +00:00
|
|
|
|
|
|
|
DEF_TEST(WriteBuffer_external_memory_textblob, reporter) {
|
|
|
|
SkPaint font;
|
|
|
|
font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
|
|
|
font.setTypeface(SkTypeface::MakeDefault());
|
|
|
|
|
|
|
|
SkTextBlobBuilder builder;
|
|
|
|
int glyph_count = 5;
|
|
|
|
const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f);
|
|
|
|
// allocRun() allocates only the glyph buffer.
|
|
|
|
std::fill(run.glyphs, run.glyphs + glyph_count, 0);
|
|
|
|
auto blob = builder.make();
|
|
|
|
SkSerialProcs procs;
|
|
|
|
SkAutoTMalloc<uint8_t> storage;
|
|
|
|
size_t blob_size = 0u;
|
|
|
|
size_t storage_size = 0u;
|
|
|
|
|
|
|
|
blob_size = SkAlign4(blob->serialize(procs)->size());
|
|
|
|
REPORTER_ASSERT(reporter, blob_size > 4u);
|
|
|
|
storage_size = blob_size - 4;
|
|
|
|
storage.realloc(storage_size);
|
|
|
|
REPORTER_ASSERT(reporter, blob->serialize(procs, storage.get(), storage_size) == 0u);
|
|
|
|
storage_size = blob_size;
|
|
|
|
storage.realloc(storage_size);
|
|
|
|
REPORTER_ASSERT(reporter, blob->serialize(procs, storage.get(), storage_size) != 0u);
|
|
|
|
}
|
|
|
|
|
|
|
|
DEF_TEST(WriteBuffer_external_memory_flattenable, reporter) {
|
|
|
|
SkScalar intervals[] = {1.f, 1.f};
|
|
|
|
auto path_effect = SkDashPathEffect::Make(intervals, 2, 0);
|
|
|
|
size_t path_size = SkAlign4(path_effect->serialize()->size());
|
|
|
|
REPORTER_ASSERT(reporter, path_size > 4u);
|
|
|
|
SkAutoTMalloc<uint8_t> storage;
|
|
|
|
|
|
|
|
size_t storage_size = path_size - 4;
|
|
|
|
storage.realloc(storage_size);
|
|
|
|
REPORTER_ASSERT(reporter, path_effect->serialize(storage.get(), storage_size) == 0u);
|
|
|
|
|
|
|
|
storage_size = path_size;
|
|
|
|
storage.realloc(storage_size);
|
|
|
|
REPORTER_ASSERT(reporter, path_effect->serialize(storage.get(), storage_size) != 0u);
|
|
|
|
}
|