Add a GL_ANGLE_robust_client_memory extension.

This allows specifying data size to all GL functions that provide a pointer to
client memory and a length parameter for all functions in which the driver
writes to client memory.

BUG=angleproject:1354

Change-Id: Ia68be1576b957cb529c87b5e0d1bd638c7dbd371
Reviewed-on: https://chromium-review.googlesource.com/382012
Commit-Queue: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
index b594965..b635c50 100644
--- a/src/libANGLE/validationES3.cpp
+++ b/src/libANGLE/validationES3.cpp
@@ -297,6 +297,7 @@
                                        GLint border,
                                        GLenum format,
                                        GLenum type,
+                                       GLsizei imageSize,
                                        const GLvoid *pixels)
 {
     // Validate image size
@@ -475,43 +476,24 @@
         }
     }
 
+    if (!ValidImageDataSize(context, target, width, height, 1, actualInternalFormat, type, pixels,
+                            imageSize))
+    {
+        return false;
+    }
+
     // Check for pixel unpack buffer related API errors
     gl::Buffer *pixelUnpackBuffer = context->getGLState().getTargetBuffer(GL_PIXEL_UNPACK_BUFFER);
     if (pixelUnpackBuffer != nullptr)
     {
-        // ...the data would be unpacked from the buffer object such that the memory reads required
-        // would exceed the data store size.
-        GLenum sizedFormat = GetSizedInternalFormat(actualInternalFormat, type);
-        const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedFormat);
-        const gl::Extents size(width, height, depth);
-        const auto &unpack = context->getGLState().getUnpackState();
-
-        bool targetIs3D     = target == GL_TEXTURE_3D || target == GL_TEXTURE_2D_ARRAY;
-        auto endByteOrErr   = formatInfo.computePackUnpackEndByte(type, size, unpack, targetIs3D);
-        if (endByteOrErr.isError())
-        {
-            context->handleError(endByteOrErr.getError());
-            return false;
-        }
-        CheckedNumeric<size_t> checkedEndByte(endByteOrErr.getResult());
-        CheckedNumeric<size_t> checkedOffset(reinterpret_cast<size_t>(pixels));
-        checkedEndByte += checkedOffset;
-
-        if (!checkedEndByte.IsValid() ||
-            (checkedEndByte.ValueOrDie() > static_cast<size_t>(pixelUnpackBuffer->getSize())))
-        {
-            // Overflow past the end of the buffer
-            context->handleError(Error(GL_INVALID_OPERATION));
-            return false;
-        }
-
         // ...data is not evenly divisible into the number of bytes needed to store in memory a datum
         // indicated by type.
         if (!isCompressed)
         {
+            size_t offset            = reinterpret_cast<size_t>(pixels);
             size_t dataBytesPerPixel = static_cast<size_t>(gl::GetTypeInfo(type).bytes);
 
-            if ((checkedOffset.ValueOrDie() % dataBytesPerPixel) != 0)
+            if ((offset % dataBytesPerPixel) != 0)
             {
                 context->handleError(
                     Error(GL_INVALID_OPERATION, "Reads would overflow the pixel unpack buffer."));
@@ -545,6 +527,7 @@
                                      GLint border,
                                      GLenum format,
                                      GLenum type,
+                                     GLsizei imageSize,
                                      const GLvoid *pixels)
 {
     if (!ValidTexture2DDestinationTarget(context, target))
@@ -555,7 +538,7 @@
 
     return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
                                              isSubImage, xoffset, yoffset, zoffset, width, height,
-                                             depth, border, format, type, pixels);
+                                             depth, border, format, type, imageSize, pixels);
 }
 
 bool ValidateES3TexImage3DParameters(Context *context,
@@ -583,7 +566,7 @@
 
     return ValidateES3TexImageParametersBase(context, target, level, internalformat, isCompressed,
                                              isSubImage, xoffset, yoffset, zoffset, width, height,
-                                             depth, border, format, type, pixels);
+                                             depth, border, format, type, -1, pixels);
 }
 
 struct EffectiveInternalFormatInfo