Bug 1313541 - Add ValidateArrayBufferView. - r=ethlin draft
authorJeff Gilbert (:jgilbert) <jgilbert@mozilla.com>
Tue, 11 Oct 2016 15:39:23 -0700
changeset 430637 a4c57f3c6d16b7ac759e878b6cf16a399248c94f
parent 419310 0d50320d6916ab7c21348a7532c828e5390ba0a6
child 430638 e9d649beb708cab833b498aa601146d79c4e4c41
push id33862
push userbmo:jgilbert@mozilla.com
push dateFri, 28 Oct 2016 02:14:30 +0000
reviewersethlin
bugs1313541
milestone52.0a1
Bug 1313541 - Add ValidateArrayBufferView. - r=ethlin MozReview-Commit-ID: JuiA7dD4vwR
dom/canvas/WebGLContext.cpp
dom/canvas/WebGLContext.h
--- a/dom/canvas/WebGLContext.cpp
+++ b/dom/canvas/WebGLContext.cpp
@@ -2504,16 +2504,51 @@ WebGLContext::StartVRPresentation()
             vrmc->GetBackendType(),
             TextureFlags::ORIGIN_BOTTOM_LEFT);
 
     screen->Morph(Move(factory));
     return true;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
+
+bool
+WebGLContext::ValidateArrayBufferView(const char* funcName,
+                                      const dom::ArrayBufferView& view, GLuint elemOffset,
+                                      GLuint elemCountOverride, uint8_t** const out_bytes,
+                                      size_t* const out_byteLen)
+{
+    view.ComputeLengthAndData();
+    uint8_t* const bytes = view.DataAllowShared();
+    const size_t byteLen = view.LengthAllowShared();
+
+    const auto& elemType = view.Type();
+    const auto& elemSize = js::Scalar::byteSize(elemType);
+
+    size_t elemCount = byteLen / elemSize;
+    if (elemOffset > elemCount) {
+        ErrorInvalidValue("%s: Invalid offset into ArrayBufferView.", funcName);
+        return false;
+    }
+    elemCount -= elemOffset;
+
+    if (elemCountOverride) {
+        if (elemCountOverride > elemCount) {
+            ErrorInvalidValue("%s: Invalid sub-length for ArrayBufferView.", funcName);
+            return false;
+        }
+        elemCount = elemCountOverride;
+    }
+
+    *out_bytes = bytes + (elemOffset * elemSize);
+    *out_byteLen = elemCount * elemSize;
+    return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
 // XPCOM goop
 
 void
 ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback& callback,
                             const std::vector<IndexedBufferBinding>& field,
                             const char* name, uint32_t flags)
 {
     for (const auto& cur : field) {
--- a/dom/canvas/WebGLContext.h
+++ b/dom/canvas/WebGLContext.h
@@ -1346,16 +1346,22 @@ protected:
     bool ValidateNonNegative(const char* funcName, const char* argName, int64_t val) {
         if (MOZ_UNLIKELY(val < 0)) {
             ErrorInvalidValue("%s: `%s` must be non-negative.", funcName, argName);
             return false;
         }
         return true;
     }
 
+    bool ValidateArrayBufferView(const char* funcName, const dom::ArrayBufferView& view,
+                                 GLuint elemOffset, GLuint elemCountOverride,
+                                 uint8_t** const out_bytes, size_t* const out_byteLen);
+
+    ////
+
     void Invalidate();
     void DestroyResourcesAndContext();
 
     void MakeContextCurrent() const;
 
     // helpers
 
     bool ConvertImage(size_t width, size_t height, size_t srcStride,
@@ -1844,20 +1850,17 @@ class ScopedLazyBind final
 
 public:
     ScopedLazyBind(gl::GLContext* gl, GLenum target, const WebGLBuffer* buf);
 
 private:
     void UnwrapImpl();
 };
 
-void
-ComputeLengthAndData(const dom::ArrayBufferViewOrSharedArrayBufferView& view,
-                     void** const out_data, size_t* const out_length,
-                     js::Scalar::Type* const out_type);
+////
 
 void
 Intersect(uint32_t srcSize, int32_t dstStartInSrc, uint32_t dstSize,
           uint32_t* const out_intStartInSrc, uint32_t* const out_intStartInDst,
           uint32_t* const out_intSize);
 
 bool
 ZeroTextureData(WebGLContext* webgl, const char* funcName, GLuint tex,