From aa4041f70a4068a7ce9df8bea3cda8aaf94a62f6 Mon Sep 17 00:00:00 2001
From: Dan Stoza <stoza@google.com>
Date: Wed, 29 Apr 2015 13:30:31 -0700
Subject: [PATCH] SurfaceFlinger: Fix integer overflow in Mesh ctor

Performs range checking on the inputs to Mesh::Mesh() before allocating
the storage array.

Bug: 20674682
Change-Id: I4fc918a8c312d967dd6d9f91a098b2e0a7081027
(cherry picked from commit ab79e33ef3a21a2b14bf15bc4c85aef247b4ad95)
---
 services/surfaceflinger/RenderEngine/Mesh.cpp | 30 +++++++++++++++++--
 1 file changed, 28 insertions(+), 2 deletions(-)

diff --git a/services/surfaceflinger/RenderEngine/Mesh.cpp b/services/surfaceflinger/RenderEngine/Mesh.cpp
index 3f50cb0a9..ffd9be2a8 100644
--- a/services/surfaceflinger/RenderEngine/Mesh.cpp
+++ b/services/surfaceflinger/RenderEngine/Mesh.cpp
@@ -16,14 +16,40 @@
 
 #include "Mesh.h"
 
+#include <utils/Log.h>
+
 namespace android {
 
 Mesh::Mesh(Primitive primitive, size_t vertexCount, size_t vertexSize, size_t texCoordSize)
     : mVertexCount(vertexCount), mVertexSize(vertexSize), mTexCoordsSize(texCoordSize),
       mPrimitive(primitive)
 {
-    mVertices = new float[(vertexSize + texCoordSize) * vertexCount];
-    mStride = mVertexSize + mTexCoordsSize;
+    if (vertexCount == 0) {
+        mVertices = new float[1];
+        mVertices[0] = 0.0f;
+        mStride = 0;
+        return;
+    }
+
+    size_t stride = vertexSize + texCoordSize;
+    size_t remainder = (stride * vertexCount) / vertexCount;
+    // Since all of the input parameters are unsigned, if stride is less than
+    // either vertexSize or texCoordSize, it must have overflowed. remainder
+    // will be equal to stride as long as stride * vertexCount doesn't overflow.
+    if ((stride < vertexSize) || (remainder != stride)) {
+        ALOGE("Overflow in Mesh(..., %zu, %zu, %zu)", vertexCount, vertexSize,
+                texCoordSize);
+        mVertices = new float[1];
+        mVertices[0] = 0.0f;
+        mVertexCount = 0;
+        mVertexSize = 0;
+        mTexCoordsSize = 0;
+        mStride = 0;
+        return;
+    }
+
+    mVertices = new float[stride * vertexCount];
+    mStride = stride;
 }
 
 Mesh::~Mesh() {