Limit copied uniform and vertex attribute names to the implicit size of the
buffers passed in. Increase the size of the buffer the client will allocate
for mapped names to be equal to the maximum token length.

BUG=http://code.google.com/p/angleproject/issues/detail?id=234
TEST=WebGL conformance test to be checked in soon
Review URL: http://codereview.appspot.com/5306063

git-svn-id: https://angleproject.googlecode.com/svn/trunk@804 736b8ea6-26fd-11df-bfd4-992fa37f6226
diff --git a/src/compiler/Compiler.cpp b/src/compiler/Compiler.cpp
index 5bace98..22764bd 100644
--- a/src/compiler/Compiler.cpp
+++ b/src/compiler/Compiler.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -252,7 +252,7 @@
 
 int TCompiler::getMappedNameMaxLength() const
 {
-    return MAX_IDENTIFIER_NAME_SIZE + 1;
+    return MAX_SHORTENED_IDENTIFIER_SIZE + 1;
 }
 
 const TExtensionBehavior& TCompiler::getExtensionBehavior() const
diff --git a/src/compiler/MapLongVariableNames.cpp b/src/compiler/MapLongVariableNames.cpp
index 8f35560..0b91f8c 100644
--- a/src/compiler/MapLongVariableNames.cpp
+++ b/src/compiler/MapLongVariableNames.cpp
@@ -10,13 +10,13 @@
 
 TString mapLongName(int id, const TString& name, bool isVarying)
 {
-    ASSERT(name.size() > MAX_IDENTIFIER_NAME_SIZE);
+    ASSERT(name.size() > MAX_SHORTENED_IDENTIFIER_SIZE);
     TStringStream stream;
     stream << "webgl_";
     if (isVarying)
         stream << "v";
     stream << id << "_";
-    stream << name.substr(0, MAX_IDENTIFIER_NAME_SIZE - stream.str().size());
+    stream << name.substr(0, MAX_SHORTENED_IDENTIFIER_SIZE - stream.str().size());
     return stream.str();
 }
 
@@ -31,7 +31,7 @@
 void MapLongVariableNames::visitSymbol(TIntermSymbol* symbol)
 {
     ASSERT(symbol != NULL);
-    if (symbol->getSymbol().size() > MAX_IDENTIFIER_NAME_SIZE) {
+    if (symbol->getSymbol().size() > MAX_SHORTENED_IDENTIFIER_SIZE) {
         switch (symbol->getQualifier()) {
           case EvqVaryingIn:
           case EvqVaryingOut:
diff --git a/src/compiler/MapLongVariableNames.h b/src/compiler/MapLongVariableNames.h
index 46f19b8..086f2b9 100644
--- a/src/compiler/MapLongVariableNames.h
+++ b/src/compiler/MapLongVariableNames.h
@@ -13,10 +13,10 @@
 #include "compiler/VariableInfo.h"
 
 // This size does not include '\0' in the end.
-#define MAX_IDENTIFIER_NAME_SIZE 32
+#define MAX_SHORTENED_IDENTIFIER_SIZE 32
 
 // Traverses intermediate tree to map attributes and uniforms names that are
-// longer than MAX_IDENTIFIER_NAME_SIZE to MAX_IDENTIFIER_NAME_SIZE.
+// longer than MAX_SHORTENED_IDENTIFIER_SIZE to MAX_SHORTENED_IDENTIFIER_SIZE.
 class MapLongVariableNames : public TIntermTraverser {
 public:
     MapLongVariableNames(std::map<std::string, std::string>& varyingLongNameMap);
diff --git a/src/compiler/ShaderLang.cpp b/src/compiler/ShaderLang.cpp
index 65a4d9b..4c66743 100644
--- a/src/compiler/ShaderLang.cpp
+++ b/src/compiler/ShaderLang.cpp
@@ -1,5 +1,5 @@
 //
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 //
@@ -12,6 +12,7 @@
 #include "GLSLANG/ShaderLang.h"
 
 #include "compiler/InitializeDll.h"
+#include "compiler/preprocessor/length_limits.h"
 #include "compiler/ShHandle.h"
 
 //
@@ -19,16 +20,21 @@
 // and the shading language compiler.
 //
 
-static int getVariableMaxLength(const TVariableInfoList& varList)
+static bool checkActiveUniformAndAttribMaxLengths(const ShHandle handle,
+                                                  int expectedValue)
 {
-    TString::size_type maxLen = 0;
-    for (TVariableInfoList::const_iterator i = varList.begin();
-         i != varList.end(); ++i)
-    {
-        maxLen = std::max(maxLen, i->name.size());
-    }
-    // Add 1 to include null-termination character.
-    return static_cast<int>(maxLen) + 1;
+    int activeUniformLimit = 0;
+    ShGetInfo(handle, SH_ACTIVE_UNIFORM_MAX_LENGTH, &activeUniformLimit);
+    int activeAttribLimit = 0;
+    ShGetInfo(handle, SH_ACTIVE_ATTRIBUTE_MAX_LENGTH, &activeAttribLimit);
+    return (expectedValue == activeUniformLimit && expectedValue == activeAttribLimit);
+}
+
+static bool checkMappedNameMaxLength(const ShHandle handle, int expectedValue)
+{
+    int mappedNameMaxLength = 0;
+    ShGetInfo(handle, SH_MAPPED_NAME_MAX_LENGTH, &mappedNameMaxLength);
+    return (expectedValue == mappedNameMaxLength);
 }
 
 static void getVariableInfo(ShShaderInfo varType,
@@ -59,9 +65,20 @@
     if (length) *length = varInfo.name.size();
     *size = varInfo.size;
     *type = varInfo.type;
-    strcpy(name, varInfo.name.c_str());
-    if (mappedName)
-        strcpy(mappedName, varInfo.mappedName.c_str());
+
+    // This size must match that queried by
+    // SH_ACTIVE_UNIFORM_MAX_LENGTH and SH_ACTIVE_ATTRIBUTE_MAX_LENGTH
+    // in ShGetInfo, below.
+    int activeUniformAndAttribLength = 1 + MAX_SYMBOL_NAME_LEN;
+    ASSERT(checkActiveUniformAndAttribMaxLengths(handle, activeUniformAndAttribLength));
+    strncpy(name, varInfo.name.c_str(), activeUniformAndAttribLength);
+    if (mappedName) {
+        // This size must match that queried by
+        // SH_MAPPED_NAME_MAX_LENGTH in ShGetInfo, below.
+        int maxMappedNameLength = 1 + MAX_SYMBOL_NAME_LEN;
+        ASSERT(checkMappedNameMaxLength(handle, maxMappedNameLength));
+        strncpy(mappedName, varInfo.mappedName.c_str(), maxMappedNameLength);
+    }
 }
 
 //
@@ -191,16 +208,18 @@
         *params = compiler->getUniforms().size();
         break;
     case SH_ACTIVE_UNIFORM_MAX_LENGTH:
-        *params = getVariableMaxLength(compiler->getUniforms());
+        *params = 1 +  MAX_SYMBOL_NAME_LEN;
         break;
     case SH_ACTIVE_ATTRIBUTES:
         *params = compiler->getAttribs().size();
         break;
     case SH_ACTIVE_ATTRIBUTE_MAX_LENGTH:
-        *params = getVariableMaxLength(compiler->getAttribs());
+        *params = 1 + MAX_SYMBOL_NAME_LEN;
         break;
     case SH_MAPPED_NAME_MAX_LENGTH:
-        *params = compiler->getMappedNameMaxLength();
+        // Use longer length than MAX_SHORTENED_IDENTIFIER_SIZE to
+        // handle array and struct dereferences.
+        *params = 1 + MAX_SYMBOL_NAME_LEN;
         break;
     default: UNREACHABLE();
     }
diff --git a/src/compiler/preprocessor/length_limits.h b/src/compiler/preprocessor/length_limits.h
new file mode 100644
index 0000000..4f1f713
--- /dev/null
+++ b/src/compiler/preprocessor/length_limits.h
@@ -0,0 +1,21 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+//
+// length_limits.h
+//
+
+#if !defined(__LENGTH_LIMITS_H)
+#define __LENGTH_LIMITS_H 1
+
+// These constants are factored out from the rest of the headers to
+// make it easier to reference them from the compiler sources.
+
+// These lengths do not include the NULL terminator.
+#define MAX_SYMBOL_NAME_LEN 256
+#define MAX_STRING_LEN 511
+
+#endif // !(defined(__LENGTH_LIMITS_H)
diff --git a/src/compiler/preprocessor/scanner.h b/src/compiler/preprocessor/scanner.h
index 33306e5..233d1dc 100644
--- a/src/compiler/preprocessor/scanner.h
+++ b/src/compiler/preprocessor/scanner.h
@@ -48,10 +48,7 @@
 #if !defined(__SCANNER_H)
 #define __SCANNER_H 1
 
-// These lengths do not include the NULL terminator.
-#define MAX_SYMBOL_NAME_LEN 256
-#define MAX_STRING_LEN 511
-
+#include "compiler/preprocessor/length_limits.h"
 #include "compiler/preprocessor/parser.h"
 
 // Not really atom table stuff but needed first...
diff --git a/src/compiler/translator_common.vcproj b/src/compiler/translator_common.vcproj
index d3f9b54..caaeca2 100644
--- a/src/compiler/translator_common.vcproj
+++ b/src/compiler/translator_common.vcproj
@@ -648,6 +648,10 @@
 					>

 				</File>

 				<File

+					RelativePath=".\preprocessor\length_limits.h"

+					>

+				</File>

+				<File

 					RelativePath=".\preprocessor\memory.h"

 					>

 				</File>