174 lines
5.5 KiB
C++
174 lines
5.5 KiB
C++
/* -*- 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;
|
|
|
|
auto srcItr = src.BeginReading();
|
|
const auto srcEnd = src.EndReading();
|
|
const auto dstBegin = (decltype(src[0])*)dst.get();
|
|
auto dstItr = dstBegin;
|
|
|
|
const auto fnEmitUntil = [&](const decltype(srcItr)& nextSrcItr) {
|
|
while (srcItr != nextSrcItr) {
|
|
*dstItr = *srcItr;
|
|
++srcItr;
|
|
++dstItr;
|
|
}
|
|
};
|
|
|
|
const auto fnFindSoonestOf = [&](const nsString* needles, size_t needleCount,
|
|
size_t* const out_foundId)
|
|
{
|
|
auto foundItr = srcItr;
|
|
while (foundItr != srcEnd) {
|
|
const auto haystack = Substring(foundItr, srcEnd);
|
|
for (size_t i = 0; i < needleCount; i++) {
|
|
if (StringBeginsWith(haystack, needles[i])) {
|
|
*out_foundId = i;
|
|
return foundItr;
|
|
}
|
|
}
|
|
++foundItr;
|
|
}
|
|
*out_foundId = needleCount;
|
|
return foundItr;
|
|
};
|
|
|
|
////
|
|
|
|
const nsString commentBeginnings[] = { NS_LITERAL_STRING("//"),
|
|
NS_LITERAL_STRING("/*"),
|
|
nsString() };
|
|
const nsString lineCommentEndings[] = { NS_LITERAL_STRING("\\\n"),
|
|
NS_LITERAL_STRING("\n"),
|
|
nsString() };
|
|
const nsString blockCommentEndings[] = { NS_LITERAL_STRING("\n"),
|
|
NS_LITERAL_STRING("*/"),
|
|
nsString() };
|
|
|
|
while (srcItr != srcEnd) {
|
|
size_t foundId;
|
|
fnEmitUntil( fnFindSoonestOf(commentBeginnings, 2, &foundId) );
|
|
fnEmitUntil(srcItr + commentBeginnings[foundId].Length());
|
|
|
|
switch (foundId) {
|
|
case 0: // line comment
|
|
while (true) {
|
|
size_t endId;
|
|
srcItr = fnFindSoonestOf(lineCommentEndings, 2, &endId);
|
|
fnEmitUntil(srcItr + lineCommentEndings[endId].Length());
|
|
if (endId == 0)
|
|
continue;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case 1: // block comment
|
|
while (true) {
|
|
size_t endId;
|
|
srcItr = fnFindSoonestOf(blockCommentEndings, 2, &endId);
|
|
fnEmitUntil(srcItr + blockCommentEndings[endId].Length());
|
|
if (endId == 0)
|
|
continue;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
default: // not found
|
|
break;
|
|
}
|
|
}
|
|
|
|
MOZ_ASSERT((dstBegin+1) - dstBegin == 1);
|
|
const uint32_t dstCharLen = dstItr - dstBegin;
|
|
if (!out->Assign(dstBegin, dstCharLen, mozilla::fallible))
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
ValidateGLSLString(const nsAString& string, WebGLContext* webgl, const char* funcName)
|
|
{
|
|
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));
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
ValidateGLSLVariableName(const nsAString& name, WebGLContext* webgl, const char* funcName)
|
|
{
|
|
if (name.IsEmpty())
|
|
return false;
|
|
|
|
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;
|
|
|
|
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.",
|
|
funcName);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
} // namespace mozilla
|