aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/core/SkPathRef.cpp5
-rw-r--r--tests/PathTest.cpp57
2 files changed, 62 insertions, 0 deletions
diff --git a/src/core/SkPathRef.cpp b/src/core/SkPathRef.cpp
index 3338225391..71d7f206c9 100644
--- a/src/core/SkPathRef.cpp
+++ b/src/core/SkPathRef.cpp
@@ -258,6 +258,11 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
return nullptr;
}
+ // If the buffer can't plausibly contain this many objects, abort.
+ size_t requiredBufferSize = verbCount * sizeof(uint8_t) + pointCount * sizeof(SkPoint) +
+ conicCount * sizeof(SkScalar) + sizeof(SkRect);
+ if (buffer->available() < requiredBufferSize) return nullptr;
+
ref->resetToSize(verbCount, pointCount, conicCount);
SkASSERT(verbCount == ref->countVerbs());
SkASSERT(pointCount == ref->countPoints());
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index 117da5bdeb..e4edb76627 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -4775,3 +4775,60 @@ DEF_TEST(skbug_6450, r) {
orr.setRectRadii(ro, rdo);
SkMakeNullCanvas()->drawDRRect(orr, irr, SkPaint());
}
+
+DEF_TEST(PathRefSerialization, reporter) {
+ SkPath path;
+ const size_t numMoves = 5;
+ const size_t numConics = 7;
+ const size_t numPoints = numMoves + 2 * numConics;
+ const size_t numVerbs = numMoves + numConics;
+ for (size_t i = 0; i < numMoves; ++i) path.moveTo(1, 2);
+ for (size_t i = 0; i < numConics; ++i) path.conicTo(1, 2, 3, 4, 5);
+ REPORTER_ASSERT(reporter, path.countPoints() == numPoints);
+ REPORTER_ASSERT(reporter, path.countVerbs() == numVerbs);
+
+ // Verify that path serializes/deserializes properly.
+ SkWriter32 writer;
+ writer.writePath(path);
+ size_t bytesWritten = writer.bytesWritten();
+ SkAutoMalloc storage(bytesWritten);
+ writer.flatten(storage.get());
+ {
+ SkPath readBack;
+ REPORTER_ASSERT(reporter, readBack != path);
+ size_t bytesRead = readBack.readFromMemory(storage.get(), bytesWritten);
+ REPORTER_ASSERT(reporter, bytesRead == bytesWritten);
+ REPORTER_ASSERT(reporter, readBack == path);
+ }
+
+ // uint32_t[] offset into serialized path.
+ const size_t verbCountOffset = 4;
+ const size_t pointCountOffset = 5;
+ const size_t conicCountOffset = 6;
+
+ // Verify that this test is changing the right values.
+ int* writtenValues = static_cast<int*>(storage.get());
+ REPORTER_ASSERT(reporter, writtenValues[verbCountOffset] == numVerbs);
+ REPORTER_ASSERT(reporter, writtenValues[pointCountOffset] == numPoints);
+ REPORTER_ASSERT(reporter, writtenValues[conicCountOffset] == numConics);
+
+ // Too many verbs, points, or conics fails to deserialize silently.
+ const int tooManyObjects = INT_MAX;
+ size_t offsets[] = {verbCountOffset, pointCountOffset, conicCountOffset};
+ for (size_t i = 0; i < 3; ++i) {
+ SkAutoMalloc storage_copy(bytesWritten);
+ memcpy(storage_copy.get(), storage.get(), bytesWritten);
+ static_cast<int*>(storage_copy.get())[offsets[i]] = tooManyObjects;
+ SkPath readBack;
+ size_t bytesRead = readBack.readFromMemory(storage_copy.get(), bytesWritten);
+ REPORTER_ASSERT(reporter, !bytesRead);
+ }
+
+ // One less byte (rounded down to alignment) than was written will also
+ // fail to be deserialized.
+ {
+ SkPath readBack;
+ size_t bytesRead = readBack.readFromMemory(storage.get(), bytesWritten - 4);
+ REPORTER_ASSERT(reporter, !bytesRead);
+ }
+}