Bug 674042 - WebGL: crash in getUniformLocation with too long uniform identifiers - r=jrmuizel
authorBenoit Jacob <bjacob@mozilla.com>
Thu, 28 Jul 2011 17:12:31 -0400
changeset 73496 6fd3e4c0082dd2e8eff2efa5a935ba3d1ccd9b99
parent 73495 267ada59f86f2a956fb16756356035a9a3e9ccd0
child 73497 dd7d71277a15b7f485c42499a1699d0ca41a5e78
push id20878
push userbjacob@mozilla.com
push dateThu, 28 Jul 2011 21:12:49 +0000
treeherdermozilla-central@6fd3e4c0082d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs674042
milestone8.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 674042 - WebGL: crash in getUniformLocation with too long uniform identifiers - r=jrmuizel This limits the length of uniform and attrib identifiers to 4095 characters, to steer clear GL implementation bugs with too long identifiers. The 4095 is totally arbitrary, all we know is that crashes happen after 2^22 chars.
content/canvas/src/WebGLContext.h
content/canvas/src/WebGLContextGL.cpp
content/canvas/src/WebGLContextValidate.cpp
gfx/layers/d3d10/CanvasLayerD3D10.cpp
--- a/content/canvas/src/WebGLContext.h
+++ b/content/canvas/src/WebGLContext.h
@@ -486,16 +486,18 @@ protected:
     PRBool ValidateFaceEnum(WebGLenum face, const char *info);
     PRBool ValidateBufferUsageEnum(WebGLenum target, const char *info);
     PRBool ValidateTexFormatAndType(WebGLenum format, WebGLenum type, int jsArrayType,
                                       PRUint32 *texelSize, const char *info);
     PRBool ValidateDrawModeEnum(WebGLenum mode, const char *info);
     PRBool ValidateAttribIndex(WebGLuint index, const char *info);
     PRBool ValidateStencilParamsForDrawCall();
     
+    bool  ValidateGLSLIdentifier(const nsAString& name, const char *info);
+
     static PRUint32 GetTexelSize(WebGLenum format, WebGLenum type);
 
     void Invalidate();
     void DestroyResourcesAndContext();
 
     void MakeContextCurrent() { gl->MakeCurrent(); }
 
     // helpers
--- a/content/canvas/src/WebGLContextGL.cpp
+++ b/content/canvas/src/WebGLContextGL.cpp
@@ -1834,16 +1834,19 @@ WebGLContext::GetAttribLocation(nsIWebGL
                                 PRInt32 *retval)
 {
     *retval = 0;
 
     WebGLuint progname;
     if (!GetGLName<WebGLProgram>("getAttribLocation: program", pobj, &progname))
         return NS_OK;
 
+    if (!ValidateGLSLIdentifier(name, "getAttribLocation"))
+        return NS_OK; 
+
     MakeContextCurrent();
     *retval = gl->fGetAttribLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
     return NS_OK;
 }
 
 NS_IMETHODIMP
 WebGLContext::GetParameter(PRUint32 pname, nsIVariant **retval)
 {
@@ -2656,16 +2659,19 @@ WebGLContext::GetUniformLocation(nsIWebG
 {
     *retval = nsnull;
 
     WebGLuint progname;
     WebGLProgram *prog;
     if (!GetConcreteObjectAndGLName("getUniformLocation: program", pobj, &prog, &progname))
         return NS_OK;
 
+    if (!ValidateGLSLIdentifier(name, "getUniformLocation"))
+        return NS_OK; 
+
     MakeContextCurrent();
 
     GLint intlocation = gl->fGetUniformLocation(progname, NS_LossyConvertUTF16toASCII(name).get());
 
     nsRefPtr<nsIWebGLUniformLocation> loc = prog->GetUniformLocationObject(intlocation);
     *retval = loc.forget().get();
 
     return NS_OK;
--- a/content/canvas/src/WebGLContextValidate.cpp
+++ b/content/canvas/src/WebGLContextValidate.cpp
@@ -323,16 +323,27 @@ PRBool WebGLContext::ValidateDrawModeEnu
         case LOCAL_GL_LINES:
             return PR_TRUE;
         default:
             ErrorInvalidEnumInfo(info, mode);
             return PR_FALSE;
     }
 }
 
+bool WebGLContext::ValidateGLSLIdentifier(const nsAString& name, const char *info)
+{
+    const PRUint32 maxSize = 4095;
+    if (name.Length() > maxSize) {
+        ErrorInvalidValue("%s: identifier is %d characters long, exceeds the maximum allowed length of %d characters",
+                          info, name.Length(), maxSize);
+        return false;
+    }
+    return true;
+}
+
 PRUint32 WebGLContext::GetTexelSize(WebGLenum format, WebGLenum type)
 {
     if (type == LOCAL_GL_UNSIGNED_BYTE || type == LOCAL_GL_FLOAT) {
         int multiplier = type == LOCAL_GL_FLOAT ? 4 : 1;
         switch (format) {
             case LOCAL_GL_ALPHA:
             case LOCAL_GL_LUMINANCE:
                 return 1 * multiplier;
--- a/gfx/layers/d3d10/CanvasLayerD3D10.cpp
+++ b/gfx/layers/d3d10/CanvasLayerD3D10.cpp
@@ -113,17 +113,17 @@ CanvasLayerD3D10::Initialize(const Data&
   HANDLE shareHandle = mGLContext ? mGLContext->GetD3DShareHandle() : nsnull;
   if (shareHandle) {
     HRESULT hr = device()->OpenSharedResource(shareHandle, __uuidof(ID3D10Texture2D), getter_AddRefs(mTexture));
     if (SUCCEEDED(hr))
       mUsingSharedTexture = PR_TRUE;
   }
 
   if (mUsingSharedTexture) {
-      mNeedsYFlip = PR_FALSE;
+    mNeedsYFlip = PR_FALSE;
   } else {
     CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM, mBounds.width, mBounds.height, 1, 1);
     desc.Usage = D3D10_USAGE_DYNAMIC;
     desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
 
     HRESULT hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTexture));
     if (FAILED(hr)) {
       NS_WARNING("Failed to create texture for CanvasLayer!");