diff --git a/src/core/SkPath_serial.cpp b/src/core/SkPath_serial.cpp index d4983fc8a7..636775538b 100644 --- a/src/core/SkPath_serial.cpp +++ b/src/core/SkPath_serial.cpp @@ -222,21 +222,56 @@ size_t SkPath::readFromMemory_EQ4(const void* storage, size_t length) { } SkASSERT(buffer.pos() <= length); +#define CHECK_POINTS_CONICS(p, c) \ + do { \ + if (p && ((pts -= p) < 0)) { \ + return 0; \ + } \ + if (c && ((cnx -= c) < 0)) { \ + return 0; \ + } \ + } while (0) + SkPath tmp; tmp.setFillType(extract_filltype(packed)); tmp.incReserve(pts); for (int i = vbs - 1; i >= 0; --i) { switch (verbs[i]) { - case kMove_Verb: tmp.moveTo(*points++); break; - case kLine_Verb: tmp.lineTo(*points++); break; - case kQuad_Verb: tmp.quadTo(points[0], points[1]); points += 2; break; - case kConic_Verb: tmp.conicTo(points[0], points[1], *conics++); points += 2; break; - case kCubic_Verb: tmp.cubicTo(points[0], points[1], points[2]); points += 3; break; - case kClose_Verb: tmp.close(); break; + case kMove_Verb: + CHECK_POINTS_CONICS(1, 0); + tmp.moveTo(*points++); + break; + case kLine_Verb: + CHECK_POINTS_CONICS(1, 0); + tmp.lineTo(*points++); + break; + case kQuad_Verb: + CHECK_POINTS_CONICS(2, 0); + tmp.quadTo(points[0], points[1]); + points += 2; + break; + case kConic_Verb: + CHECK_POINTS_CONICS(2, 1); + tmp.conicTo(points[0], points[1], *conics++); + points += 2; + break; + case kCubic_Verb: + CHECK_POINTS_CONICS(3, 0); + tmp.cubicTo(points[0], points[1], points[2]); + points += 3; + break; + case kClose_Verb: + tmp.close(); + break; default: return 0; // bad verb } } +#undef CHECK_POINTS_CONICS + if (pts || cnx) { + return 0; // leftover points and/or conics + } + *this = std::move(tmp); return buffer.pos(); }