SkDEBUGCODE((*dst)->validate();)
}
+// Given the verb array, deduce the required number of pts and conics,
+// or if an invalid verb is encountered, return false.
+static bool deduce_pts_conics(const uint8_t verbs[], int vCount, int* ptCountPtr,
+ int* conicCountPtr) {
+ int ptCount = 0;
+ int conicCount = 0;
+ for (int i = 0; i < vCount; ++i) {
+ switch (verbs[i]) {
+ case SkPath::kMove_Verb:
+ case SkPath::kLine_Verb:
+ ptCount += 1;
+ break;
+ case SkPath::kConic_Verb:
+ conicCount += 1;
+ // fall-through
+ case SkPath::kQuad_Verb:
+ ptCount += 2;
+ break;
+ case SkPath::kCubic_Verb:
+ ptCount += 3;
+ break;
+ case SkPath::kClose_Verb:
+ break;
+ default:
+ return false;
+ }
+ }
+ *ptCountPtr = ptCount;
+ *conicCountPtr = conicCount;
+ return true;
+}
+
SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
SkPathRef* ref = new SkPathRef;
delete ref;
return nullptr;
}
+
+ // Check that the verbs are valid, and imply the correct number of pts and conics
+ {
+ int pCount, cCount;
+ if (!deduce_pts_conics(ref->verbsMemBegin(), ref->countVerbs(), &pCount, &cCount) ||
+ pCount != ref->countPoints() || cCount != ref->fConicWeights.count()) {
+ delete ref;
+ return nullptr;
+ }
+ }
+
ref->fBoundsIsDirty = false;
// resetToSize clears fSegmentMask and fIsOval
REPORTER_ASSERT(reporter, origBounds == readBackBounds);
}
+static void test_corrupt_flattening(skiatest::Reporter* reporter) {
+ SkPath path;
+ path.moveTo(1, 2);
+ path.lineTo(1, 2);
+ path.quadTo(1, 2, 3, 4);
+ path.conicTo(1, 2, 3, 4, 0.5f);
+ path.cubicTo(1, 2, 3, 4, 5, 6);
+ uint8_t buffer[1024];
+ SkDEBUGCODE(size_t size =) path.writeToMemory(buffer);
+ SkASSERT(size <= sizeof(buffer));
+
+ // find where the counts and verbs are stored : from the impl in SkPathRef.cpp
+ int32_t* vCount = (int32_t*)&buffer[16];
+ SkASSERT(*vCount == 5);
+ int32_t* pCount = (int32_t*)&buffer[20];
+ SkASSERT(*pCount == 9);
+ int32_t* cCount = (int32_t*)&buffer[24];
+ SkASSERT(*cCount == 1);
+ uint8_t* verbs = &buffer[28];
+
+ REPORTER_ASSERT(reporter, path.readFromMemory(buffer, sizeof(buffer)));
+
+ // check that we detect under/over-flow of counts
+
+ *vCount += 1;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ *vCount -= 1; // restore
+
+ *pCount += 1;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ *pCount -= 2;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ *pCount += 1; // restore
+
+ *cCount += 1;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ *cCount -= 2;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ *cCount += 1; // restore
+
+ // Check that we detect when the verbs indicate more or fewer pts/conics
+
+ uint8_t save = verbs[0];
+ SkASSERT(save == SkPath::kCubic_Verb);
+ verbs[0] = SkPath::kQuad_Verb;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ verbs[0] = save;
+
+ save = verbs[1];
+ SkASSERT(save == SkPath::kConic_Verb);
+ verbs[1] = SkPath::kQuad_Verb;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ verbs[1] = SkPath::kCubic_Verb;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ verbs[1] = save;
+
+ // Check that we detect invalid verbs
+ save = verbs[1];
+ verbs[1] = 17;
+ REPORTER_ASSERT(reporter, !path.readFromMemory(buffer, sizeof(buffer)));
+ verbs[1] = save;
+}
+
static void test_flattening(skiatest::Reporter* reporter) {
SkPath p;
write_and_read_back(reporter, oval);
}
+
+ test_corrupt_flattening(reporter);
}
static void test_transform(skiatest::Reporter* reporter) {