validate deserialized path verbs
BUG=676755 Change-Id: Ie9bd70d3a130c53737756587f73c9dce4a6bcb6d Reviewed-on: https://skia-review.googlesource.com/6529 Commit-Queue: Mike Reed <reed@google.com> Reviewed-by: Cary Clark <caryclark@google.com>
This commit is contained in:
parent
b0b625b796
commit
e3374d6893
@ -186,6 +186,38 @@ void SkPathRef::CreateTransformedCopy(sk_sp<SkPathRef>* dst,
|
||||
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;
|
||||
|
||||
@ -231,6 +263,17 @@ SkPathRef* SkPathRef::CreateFromBuffer(SkRBuffer* buffer) {
|
||||
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
|
||||
|
@ -2532,6 +2532,69 @@ static void write_and_read_back(skiatest::Reporter* reporter,
|
||||
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;
|
||||
|
||||
@ -2580,6 +2643,8 @@ static void test_flattening(skiatest::Reporter* reporter) {
|
||||
|
||||
write_and_read_back(reporter, oval);
|
||||
}
|
||||
|
||||
test_corrupt_flattening(reporter);
|
||||
}
|
||||
|
||||
static void test_transform(skiatest::Reporter* reporter) {
|
||||
|
Loading…
Reference in New Issue
Block a user