Ensure that SkMemoryStream does not crash dereferencing fData.
SkMemoryStream attempts to dereference fData in multiple places.
Instead of allowing it to be NULL, resulting in a crash, set it
to SkData::NewEmpty().
Add a test for SkStream that will crash when its SkData is set to NULL.
Review URL: https://codereview.appspot.com/7061059
git-svn-id: http://skia.googlecode.com/svn/trunk@7111 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
index 8f0548e..7ec3117 100644
--- a/include/core/SkStream.h
+++ b/include/core/SkStream.h
@@ -188,7 +188,13 @@
/** if copyData is true, the stream makes a private copy of the data
*/
SkMemoryStream(const void* data, size_t length, bool copyData = false);
- SkMemoryStream(SkData *data);
+
+ /**
+ * Use the specified data as the memory for this stream. The stream will
+ * call ref() on the data (assuming it is not null).
+ */
+ SkMemoryStream(SkData*);
+
virtual ~SkMemoryStream();
/** Resets the stream to the specified data and length,
diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp
index 2851e5f..f173b9e 100644
--- a/src/core/SkStream.cpp
+++ b/src/core/SkStream.cpp
@@ -299,9 +299,13 @@
fOffset = 0;
}
-SkMemoryStream::SkMemoryStream(SkData *data) {
- fData = SkSafeRef(data);
- fOffset = 0;
+SkMemoryStream::SkMemoryStream(SkData* data) {
+ if (NULL == data) {
+ fData = SkData::NewEmpty();
+ } else {
+ fData = data;
+ fData->ref();
+ }
}
SkMemoryStream::~SkMemoryStream() {
@@ -326,7 +330,13 @@
}
SkData* SkMemoryStream::setData(SkData* data) {
- SkRefCnt_SafeAssign(fData, data);
+ fData->unref();
+ if (NULL == data) {
+ fData = SkData::NewEmpty();
+ } else {
+ fData = data;
+ fData->ref();
+ }
return data;
}
diff --git a/tests/StreamTest.cpp b/tests/StreamTest.cpp
index b5e3cd9..ed51aa7 100644
--- a/tests/StreamTest.cpp
+++ b/tests/StreamTest.cpp
@@ -130,10 +130,29 @@
}
}
+// Test that setting an SkMemoryStream to a NULL data does not result in a crash when calling
+// methods that access fData.
+static void TestDereferencingData(SkMemoryStream* memStream) {
+ memStream->read(NULL, 0);
+ memStream->getMemoryBase();
+ SkAutoDataUnref data(memStream->copyToData());
+}
+
+static void TestNullData() {
+ SkData* nullData = NULL;
+ SkMemoryStream memStream(nullData);
+ TestDereferencingData(&memStream);
+
+ memStream.setData(nullData);
+ TestDereferencingData(&memStream);
+
+}
+
static void TestStreams(skiatest::Reporter* reporter) {
TestRStream(reporter);
TestWStream(reporter);
TestPackedUInt(reporter);
+ TestNullData();
}
#include "TestClassDef.h"