Checking structure sizes before reading them from memory to avoid overflowing the buffer's stream.

BUG=
R=reed@google.com, mtklein@google.com, senorblanco@chromium.org

Committed: https://code.google.com/p/skia/source/detail?r=12114

Committed: https://code.google.com/p/skia/source/detail?r=12119

Author: sugoi@chromium.org

Review URL: https://codereview.chromium.org/41253002

git-svn-id: http://skia.googlecode.com/svn/trunk/include@12130 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/core/SkMatrix.h b/core/SkMatrix.h
index b6856d1..dad5ff9 100644
--- a/core/SkMatrix.h
+++ b/core/SkMatrix.h
@@ -559,9 +559,16 @@
         kMaxFlattenSize = 9 * sizeof(SkScalar) + sizeof(uint32_t)
     };
     // return the number of bytes written, whether or not buffer is null
-    uint32_t writeToMemory(void* buffer) const;
-    // return the number of bytes read
-    uint32_t readFromMemory(const void* buffer);
+    size_t writeToMemory(void* buffer) const;
+    /**
+     * Reads data from the buffer parameter
+     *
+     * @param buffer Memory to read from
+     * @param length Amount of memory available in the buffer
+     * @return number of bytes read (must be a multiple of 4) or
+     *         0 if there was not enough memory available
+     */
+    size_t readFromMemory(const void* buffer, size_t length);
 
     SkDEVCODE(void dump() const;)
     SkDEVCODE(void toString(SkString*) const;)
diff --git a/core/SkPath.h b/core/SkPath.h
index 785eb77..2b111fe 100644
--- a/core/SkPath.h
+++ b/core/SkPath.h
@@ -899,16 +899,19 @@
     void dump() const;
 
     /**
-     *  Write the region to the buffer, and return the number of bytes written.
+     *  Write the path to the buffer, and return the number of bytes written.
      *  If buffer is NULL, it still returns the number of bytes.
      */
-    uint32_t writeToMemory(void* buffer) const;
-
+    size_t writeToMemory(void* buffer) const;
     /**
-     *  Initialized the region from the buffer, returning the number
-     *  of bytes actually read.
+     * Initializes the path from the buffer
+     *
+     * @param buffer Memory to read from
+     * @param length Amount of memory available in the buffer
+     * @return number of bytes read (must be a multiple of 4) or
+     *         0 if there was not enough memory available
      */
-    uint32_t readFromMemory(const void* buffer);
+    size_t readFromMemory(const void* buffer, size_t length);
 
     /** Returns a non-zero, globally unique value corresponding to the set of verbs
         and points in the path (but not the fill type [except on Android skbug.com/1762]).
diff --git a/core/SkRRect.h b/core/SkRRect.h
index 402e6c6..3c6386f 100644
--- a/core/SkRRect.h
+++ b/core/SkRRect.h
@@ -244,14 +244,20 @@
      *  write kSizeInMemory bytes, and that value is guaranteed to always be
      *  a multiple of 4. Return kSizeInMemory.
      */
-    uint32_t writeToMemory(void* buffer) const;
+    size_t writeToMemory(void* buffer) const;
 
     /**
-     *  Read the rrect from the specified buffer. This is guaranteed to always
-     *  read kSizeInMemory bytes, and that value is guaranteed to always be
-     *  a multiple of 4. Return kSizeInMemory.
+     * Reads the rrect from the specified buffer
+     *
+     * If the specified buffer is large enough, this will read kSizeInMemory bytes,
+     * and that value is guaranteed to always be a multiple of 4.
+     *
+     * @param buffer Memory to read from
+     * @param length Amount of memory available in the buffer
+     * @return number of bytes read (must be a multiple of 4) or
+     *         0 if there was not enough memory available
      */
-    uint32_t readFromMemory(const void* buffer);
+    size_t readFromMemory(const void* buffer, size_t length);
 
 private:
     SkRect fRect;
diff --git a/core/SkReader32.h b/core/SkReader32.h
index 7a8d22a..40ae12c 100644
--- a/core/SkReader32.h
+++ b/core/SkReader32.h
@@ -106,27 +106,20 @@
     int32_t readS32() { return this->readInt(); }
     uint32_t readU32() { return this->readInt(); }
 
-    void readPath(SkPath* path) {
-        size_t size = path->readFromMemory(this->peek());
-        SkASSERT(SkAlign4(size) == size);
-        (void)this->skip(size);
+    bool readPath(SkPath* path) {
+        return readObjectFromMemory(path);
     }
 
-    void readMatrix(SkMatrix* matrix) {
-        size_t size = matrix->readFromMemory(this->peek());
-        SkASSERT(SkAlign4(size) == size);
-        (void)this->skip(size);
+    bool readMatrix(SkMatrix* matrix) {
+        return readObjectFromMemory(matrix);
     }
 
-    SkRRect* readRRect(SkRRect* rrect) {
-        rrect->readFromMemory(this->skip(SkRRect::kSizeInMemory));
-        return rrect;
+    bool readRRect(SkRRect* rrect) {
+        return readObjectFromMemory(rrect);
     }
 
-    void readRegion(SkRegion* rgn) {
-        size_t size = rgn->readFromMemory(this->peek());
-        SkASSERT(SkAlign4(size) == size);
-        (void)this->skip(size);
+    bool readRegion(SkRegion* rgn) {
+        return readObjectFromMemory(rgn);
     }
 
     /**
@@ -143,6 +136,15 @@
     size_t readIntoString(SkString* copy);
 
 private:
+    template <typename T> bool readObjectFromMemory(T* obj) {
+        size_t size = obj->readFromMemory(this->peek(), this->available());
+        // If readFromMemory() fails (which means that available() was too small), it returns 0
+        bool success = (size > 0) && (size <= this->available()) && (SkAlign4(size) == size);
+        // In case of failure, we want to skip to the end
+        (void)this->skip(success ? size : this->available());
+        return success;
+    }
+
     // these are always 4-byte aligned
     const char* fCurr;  // current position within buffer
     const char* fStop;  // end of buffer
diff --git a/core/SkRegion.h b/core/SkRegion.h
index a088d54..c9aa8da 100644
--- a/core/SkRegion.h
+++ b/core/SkRegion.h
@@ -361,13 +361,16 @@
      *  Write the region to the buffer, and return the number of bytes written.
      *  If buffer is NULL, it still returns the number of bytes.
      */
-    uint32_t writeToMemory(void* buffer) const;
-
+    size_t writeToMemory(void* buffer) const;
     /**
-     *  Initialized the region from the buffer, returning the number
-     *  of bytes actually read.
+     * Initializes the region from the buffer
+     *
+     * @param buffer Memory to read from
+     * @param length Amount of memory available in the buffer
+     * @return number of bytes read (must be a multiple of 4) or
+     *         0 if there was not enough memory available
      */
-    uint32_t readFromMemory(const void* buffer);
+    size_t readFromMemory(const void* buffer, size_t length);
 
     /**
      *  Returns a reference to a global empty region. Just a convenience for