Bug 1325995 - Do our own GLSL char validity checks based on ESSL3 rules. - r=daoshengmu draft
authorJeff Gilbert <jgilbert@mozilla.com>
Thu, 29 Dec 2016 18:48:04 -0800
changeset 454803 716347f3af9eb0076c11368a48eb8c9cc1fc42f4
parent 454802 2cb2412f24d463f89a7216fa88c9d5d248e44c77
child 454804 18db10b566b8ae1c9279d1c95808b409531ffb75
push id40055
push userbmo:jgilbert@mozilla.com
push dateFri, 30 Dec 2016 11:02:59 +0000
reviewersdaoshengmu
bugs1325995
milestone53.0a1
Bug 1325995 - Do our own GLSL char validity checks based on ESSL3 rules. - r=daoshengmu MozReview-Commit-ID: 60mJqYFTQBA
dom/canvas/WebGLShader.cpp
dom/canvas/WebGLValidateStrings.cpp
dom/canvas/WebGLValidateStrings.h
--- a/dom/canvas/WebGLShader.cpp
+++ b/dom/canvas/WebGLShader.cpp
@@ -161,17 +161,17 @@ WebGLShader::ShaderSource(const nsAStrin
     const char funcName[] = "shaderSource";
     nsString sourceWithoutComments;
     if (!TruncateComments(source, &sourceWithoutComments)) {
         mContext->ErrorOutOfMemory("%s: Failed to alloc for empting comment contents.",
                                    funcName);
         return;
     }
 
-    if (!ValidateGLSLString(sourceWithoutComments, mContext, funcName))
+    if (!ValidateGLSLPreprocString(mContext, funcName, sourceWithoutComments))
         return;
 
     // We checked that the source stripped of comments is in the
     // 7-bit ASCII range, so we can skip the NS_IsAscii() check.
     const NS_LossyConvertUTF16toASCII cleanSource(sourceWithoutComments);
 
     if (mContext->gl->WorkAroundDriverBugs()) {
         const size_t maxSourceLength = 0x3ffff;
--- a/dom/canvas/WebGLValidateStrings.cpp
+++ b/dom/canvas/WebGLValidateStrings.cpp
@@ -1,42 +1,18 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "WebGLValidateStrings.h"
 
-#include "nsString.h"
 #include "WebGLContext.h"
 
 namespace mozilla {
-// The following code was taken from the WebKit WebGL implementation,
-// which can be found here:
-// http://trac.webkit.org/browser/trunk/Source/WebCore/html/canvas/WebGLRenderingContext.cpp?rev=93625#L121
-// Note that some modifications were done to adapt it to Mozilla.
-/****** BEGIN CODE TAKEN FROM WEBKIT ******/
-bool IsValidGLSLCharacter(char16_t c)
-{
-    // Printing characters are valid except " $ ` @ \ ' DEL.
-    if (c >= 32 && c <= 126 &&
-        c != '"' && c != '$' && c != '`' && c != '@' && c != '\\' && c != '\'')
-    {
-         return true;
-    }
-
-    // Horizontal tab, line feed, vertical tab, form feed, carriage return
-    // are also valid.
-    if (c >= 9 && c <= 13) {
-         return true;
-    }
-
-    return false;
-}
-/****** END CODE TAKEN FROM WEBKIT ******/
 
 bool
 TruncateComments(const nsAString& src, nsAString* const out)
 {
     const size_t dstByteCount = src.Length() * sizeof(src[0]);
     const UniqueBuffer dst(malloc(dstByteCount));
     if (!dst)
         return false;
@@ -118,23 +94,94 @@ TruncateComments(const nsAString& src, n
     MOZ_ASSERT((dstBegin+1) - dstBegin == 1);
     const uint32_t dstCharLen = dstItr - dstBegin;
     if (!out->Assign(dstBegin, dstCharLen, mozilla::fallible))
         return false;
 
     return true;
 }
 
+////////////////////////////////////////////////////////////////////////////////
+
+static bool
+IsValidGLSLChar(char16_t c)
+{
+    if (('a' <= c && c <= 'z') ||
+        ('A' <= c && c <= 'Z') ||
+        ('0' <= c && c <= '9'))
+    {
+        return true;
+    }
+
+    switch (c) {
+    case ' ':
+    case '\t':
+    case '\v':
+    case '\f':
+    case '\r':
+    case '\n':
+    case '_':
+    case '.':
+    case '+':
+    case '-':
+    case '/':
+    case '*':
+    case '%':
+    case '<':
+    case '>':
+    case '[':
+    case ']':
+    case '(':
+    case ')':
+    case '{':
+    case '}':
+    case '^':
+    case '|':
+    case '&':
+    case '~':
+    case '=':
+    case '!':
+    case ':':
+    case ';':
+    case ',':
+    case '?':
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+static bool
+IsValidGLSLPreprocChar(char16_t c)
+{
+    if (IsValidGLSLChar(c))
+        return true;
+
+    switch (c) {
+    case '\\':
+    case '#':
+        return true;
+
+    default:
+        return false;
+    }
+}
+
+////
+
 bool
-ValidateGLSLString(const nsAString& string, WebGLContext* webgl, const char* funcName)
+ValidateGLSLPreprocString(WebGLContext* webgl, const char* funcName,
+                          const nsAString& string)
 {
     for (size_t i = 0; i < string.Length(); ++i) {
-        if (!IsValidGLSLCharacter(string.CharAt(i))) {
-           webgl->ErrorInvalidValue("%s: String contains the illegal character '%d'",
-                                    funcName, string.CharAt(i));
+        const auto& cur = string[i];
+        if (!IsValidGLSLPreprocChar(cur)) {
+           webgl->ErrorInvalidValue("%s: String contains the illegal character '%d'.",
+                                    funcName, cur);
            return false;
         }
     }
 
     return true;
 }
 
 bool
@@ -146,18 +193,24 @@ ValidateGLSLVariableName(const nsAString
     const uint32_t maxSize = webgl->IsWebGL2() ? 1024 : 256;
     if (name.Length() > maxSize) {
         webgl->ErrorInvalidValue("%s: Identifier is %d characters long, exceeds the"
                                  " maximum allowed length of %d characters.",
                                  funcName, name.Length(), maxSize);
         return false;
     }
 
-    if (!ValidateGLSLString(name, webgl, funcName))
-        return false;
+    for (size_t i = 0; i < name.Length(); ++i) {
+        const auto& cur = name[i];
+        if (!IsValidGLSLChar(cur)) {
+           webgl->ErrorInvalidValue("%s: String contains the illegal character '%d'.",
+                                    funcName, cur);
+           return false;
+        }
+    }
 
     nsString prefix1 = NS_LITERAL_STRING("webgl_");
     nsString prefix2 = NS_LITERAL_STRING("_webgl_");
 
     if (Substring(name, 0, prefix1.Length()).Equals(prefix1) ||
         Substring(name, 0, prefix2.Length()).Equals(prefix2))
     {
         webgl->ErrorInvalidOperation("%s: String contains a reserved GLSL prefix.",
--- a/dom/canvas/WebGLValidateStrings.h
+++ b/dom/canvas/WebGLValidateStrings.h
@@ -23,26 +23,25 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef WEBGL_VALIDATE_STRINGS_H_
 #define WEBGL_VALIDATE_STRINGS_H_
 
 #include "nsString.h"
-#include "nsTArray.h"
 
 namespace mozilla {
 
 class WebGLContext;
 
 bool
 TruncateComments(const nsAString& src, nsAString* const out);
-
-bool ValidateGLSLString(const nsAString& string, WebGLContext* webgl,
-                        const char* funcName);
-
-bool ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl,
-                              const char* funcName);
+bool
+ValidateGLSLPreprocString(WebGLContext* webgl, const char* funcName,
+                          const nsAString& string);
+bool
+ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl,
+                         const char* funcName);
 
 } // namespace mozilla
 
 #endif // WEBGL_VALIDATE_STRINGS_H_