add safemath version of readbuffer->skip

Bug: skia:
Change-Id: I6a5d24569cc1bd93bd190d81e3375993da9c56f0
Reviewed-on: https://skia-review.googlesource.com/88581
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Herb Derby <herb@google.com>
Reviewed-by: Mike Klein <mtklein@chromium.org>
diff --git a/src/core/SkMath.cpp b/src/core/SkMath.cpp
index 6eff790..58645da 100644
--- a/src/core/SkMath.cpp
+++ b/src/core/SkMath.cpp
@@ -9,6 +9,7 @@
 #include "SkFixed.h"
 #include "SkFloatBits.h"
 #include "SkFloatingPoint.h"
+#include "SkSafeMath.h"
 #include "SkScalar.h"
 
 #define sub_shift(zeros, x, n)  \
@@ -67,8 +68,6 @@
     return root;
 }
 
-///////////////////////////////////////////////////////////////////////////////
-
 float SkScalarSinCos(float radians, float* cosValue) {
     float sinValue = sk_float_sin(radians);
 
@@ -84,3 +83,17 @@
     }
     return sinValue;
 }
+
+///////////////////////////////////////////////////////////////////////////////////////////////////
+
+size_t SkSafeMath::Add(size_t x, size_t y) {
+    SkSafeMath tmp;
+    size_t sum = tmp.add(x, y);
+    return tmp.ok() ? sum : SK_MaxSizeT;
+}
+
+size_t SkSafeMath::Mul(size_t x, size_t y) {
+    SkSafeMath tmp;
+    size_t prod = tmp.mul(x, y);
+    return tmp.ok() ? prod : SK_MaxSizeT;
+}
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index a226095..c5aebe3 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -14,6 +14,7 @@
 #include "SkPictureRecord.h"
 #include "SkReadBuffer.h"
 #include "SkRSXform.h"
+#include "SkSafeMath.h"
 #include "SkTextBlob.h"
 #include "SkTDArray.h"
 #include "SkTypes.h"
@@ -246,12 +247,12 @@
             const SkImage* atlas = fPictureData->getImage(reader);
             const uint32_t flags = reader->readUInt();
             const int count = reader->readUInt();
-            const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
-            const SkRect* tex = (const SkRect*)reader->skip(count * sizeof(SkRect));
+            const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
+            const SkRect* tex = (const SkRect*)reader->skip(count, sizeof(SkRect));
             const SkColor* colors = nullptr;
             SkBlendMode mode = SkBlendMode::kDst;
             if (flags & DRAW_ATLAS_HAS_COLORS) {
-                colors = (const SkColor*)reader->skip(count * sizeof(SkColor));
+                colors = (const SkColor*)reader->skip(count, sizeof(SkColor));
                 mode = (SkBlendMode)reader->readUInt();
             }
             const SkRect* cull = nullptr;
@@ -360,9 +361,9 @@
             const SkImage* image = fPictureData->getImage(reader);
             SkCanvas::Lattice lattice;
             lattice.fXCount = reader->readInt();
-            lattice.fXDivs = (const int*) reader->skip(lattice.fXCount * sizeof(int32_t));
+            lattice.fXDivs = (const int*) reader->skip(lattice.fXCount, sizeof(int32_t));
             lattice.fYCount = reader->readInt();
-            lattice.fYDivs = (const int*) reader->skip(lattice.fYCount * sizeof(int32_t));
+            lattice.fYDivs = (const int*) reader->skip(lattice.fYCount, sizeof(int32_t));
             int flagCount = reader->readInt();
             lattice.fRectTypes = (0 == flagCount) ? nullptr :
                     (const SkCanvas::Lattice::RectType*)
@@ -427,16 +428,16 @@
         case DRAW_PATCH: {
             const SkPaint* paint = fPictureData->getPaint(reader);
 
-            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts *
+            const SkPoint* cubics = (const SkPoint*)reader->skip(SkPatchUtils::kNumCtrlPts,
                                                                  sizeof(SkPoint));
             uint32_t flag = reader->readInt();
             const SkColor* colors = nullptr;
             if (flag & DRAW_VERTICES_HAS_COLORS) {
-                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners * sizeof(SkColor));
+                colors = (const SkColor*)reader->skip(SkPatchUtils::kNumCorners, sizeof(SkColor));
             }
             const SkPoint* texCoords = nullptr;
             if (flag & DRAW_VERTICES_HAS_TEXS) {
-                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners *
+                texCoords = (const SkPoint*)reader->skip(SkPatchUtils::kNumCorners,
                                                          sizeof(SkPoint));
             }
             SkBlendMode bmode = SkBlendMode::kModulate;
@@ -480,7 +481,7 @@
             const SkPaint* paint = fPictureData->getPaint(reader);
             SkCanvas::PointMode mode = (SkCanvas::PointMode)reader->readInt();
             size_t count = reader->readInt();
-            const SkPoint* pts = (const SkPoint*)reader->skip(sizeof(SkPoint)* count);
+            const SkPoint* pts = (const SkPoint*)reader->skip(count, sizeof(SkPoint));
             BREAK_ON_READ_ERROR(reader);
 
             if (paint) {
@@ -492,7 +493,7 @@
             TextContainer text(reader, paint);
             size_t points = reader->readInt();
             reader->validate(points == text.count());
-            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
+            const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint));
             BREAK_ON_READ_ERROR(reader);
 
             if (paint && text.text()) {
@@ -504,7 +505,7 @@
             TextContainer text(reader, paint);
             size_t points = reader->readInt();
             reader->validate(points == text.count());
-            const SkPoint* pos = (const SkPoint*)reader->skip(points * sizeof(SkPoint));
+            const SkPoint* pos = (const SkPoint*)reader->skip(points, sizeof(SkPoint));
             const SkScalar top = reader->readScalar();
             const SkScalar bottom = reader->readScalar();
             SkDebugf("postexth count %zu pos %p\n", points, pos);
@@ -521,7 +522,7 @@
             size_t xCount = reader->readInt();
             reader->validate(xCount == text.count());
             const SkScalar constY = reader->readScalar();
-            const SkScalar* xpos = (const SkScalar*)reader->skip(xCount * sizeof(SkScalar));
+            const SkScalar* xpos = (const SkScalar*)reader->skip(xCount, sizeof(SkScalar));
             BREAK_ON_READ_ERROR(reader);
 
             if (paint && text.text()) {
@@ -533,7 +534,8 @@
             TextContainer text(reader, paint);
             size_t xCount = reader->readInt();
             reader->validate(xCount == text.count());
-            const SkScalar* xpos = (const SkScalar*)reader->skip((3 + xCount) * sizeof(SkScalar));
+            const SkScalar* xpos = (const SkScalar*)reader->skip(SkSafeMath::Add(3, xCount),
+                                                                 sizeof(SkScalar));
             BREAK_ON_READ_ERROR(reader);
 
             const SkScalar top = *xpos++;
@@ -651,7 +653,7 @@
             int count = reader->readInt();
             uint32_t flags = reader->read32();
             TextContainer text(reader, paint);
-            const SkRSXform* xform = (const SkRSXform*)reader->skip(count * sizeof(SkRSXform));
+            const SkRSXform* xform = (const SkRSXform*)reader->skip(count, sizeof(SkRSXform));
             const SkRect* cull = nullptr;
             if (flags & DRAW_TEXT_RSXFORM_HAS_CULL) {
                 cull = (const SkRect*)reader->skip(sizeof(SkRect));
@@ -667,20 +669,20 @@
             DrawVertexFlags flags = (DrawVertexFlags)reader->readInt();
             SkVertices::VertexMode vmode = (SkVertices::VertexMode)reader->readInt();
             int vCount = reader->readInt();
-            const SkPoint* verts = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
+            const SkPoint* verts = (const SkPoint*)reader->skip(vCount, sizeof(SkPoint));
             const SkPoint* texs = nullptr;
             const SkColor* colors = nullptr;
             const uint16_t* indices = nullptr;
             int iCount = 0;
             if (flags & DRAW_VERTICES_HAS_TEXS) {
-                texs = (const SkPoint*)reader->skip(vCount * sizeof(SkPoint));
+                texs = (const SkPoint*)reader->skip(vCount, sizeof(SkPoint));
             }
             if (flags & DRAW_VERTICES_HAS_COLORS) {
-                colors = (const SkColor*)reader->skip(vCount * sizeof(SkColor));
+                colors = (const SkColor*)reader->skip(vCount, sizeof(SkColor));
             }
             if (flags & DRAW_VERTICES_HAS_INDICES) {
                 iCount = reader->readInt();
-                indices = (const uint16_t*)reader->skip(iCount * sizeof(uint16_t));
+                indices = (const uint16_t*)reader->skip(iCount, sizeof(uint16_t));
             }
             SkBlendMode bmode = SkBlendMode::kModulate;
             if (flags & DRAW_VERTICES_HAS_XFER) {
diff --git a/src/core/SkReadBuffer.cpp b/src/core/SkReadBuffer.cpp
index 9d15c1f..c4ca315 100644
--- a/src/core/SkReadBuffer.cpp
+++ b/src/core/SkReadBuffer.cpp
@@ -13,6 +13,7 @@
 #include "SkMathPriv.h"
 #include "SkMatrixPriv.h"
 #include "SkReadBuffer.h"
+#include "SkSafeMath.h"
 #include "SkStream.h"
 #include "SkTypeface.h"
 
@@ -106,6 +107,10 @@
     return addr;
 }
 
+const void* SkReadBuffer::skip(size_t count, size_t size) {
+    return this->skip(SkSafeMath::Mul(count, size));
+}
+
 void SkReadBuffer::setDeserialProcs(const SkDeserialProcs& procs) {
     fProcs = procs;
 }
diff --git a/src/core/SkReadBuffer.h b/src/core/SkReadBuffer.h
index 9c62a33..665f408 100644
--- a/src/core/SkReadBuffer.h
+++ b/src/core/SkReadBuffer.h
@@ -115,6 +115,7 @@
     size_t offset() { return fReader.offset(); }
     bool eof() { return fReader.eof(); }
     const void* skip(size_t size);
+    const void* skip(size_t count, size_t size);    // does safe multiply
 
     // primitives
     bool readBool();
diff --git a/src/core/SkSafeMath.h b/src/core/SkSafeMath.h
index 1005d06..7afd482 100644
--- a/src/core/SkSafeMath.h
+++ b/src/core/SkSafeMath.h
@@ -48,6 +48,10 @@
         return add(x, alignment - 1) & ~(alignment - 1);
     }
 
+    // These saturate to their results
+    static size_t Add(size_t x, size_t y);
+    static size_t Mul(size_t x, size_t y);
+
 private:
     uint32_t mul32(uint32_t x, uint32_t y) {
         uint64_t bx = x;