Fix crash on bad structure member reference
authorGreg Fischer <greg@lunarg.com>
Wed, 11 Jan 2023 01:50:18 +0000 (18:50 -0700)
committerGreg Fischer <greg@lunarg.com>
Wed, 11 Jan 2023 23:53:39 +0000 (16:53 -0700)
Fixes #3105

Test/baseResults/struct.error.frag.out [new file with mode: 0644]
Test/struct.error.frag [new file with mode: 0644]
glslang/MachineIndependent/ParseHelper.cpp
gtests/AST.FromFile.cpp

diff --git a/Test/baseResults/struct.error.frag.out b/Test/baseResults/struct.error.frag.out
new file mode 100644 (file)
index 0000000..5b0993a
--- /dev/null
@@ -0,0 +1,37 @@
+struct.error.frag
+ERROR: 0:12: 'z' : no such field in structure 
+ERROR: 1 compilation errors.  No code generated.
+
+
+Shader version: 460
+ERROR: node is still EOpNull!
+0:7  Function Definition: test( ( global structure{ global float x})
+0:7    Function Parameters: 
+0:8    Sequence
+0:8      Branch: Return with expression
+0:8        Constant:
+0:8          1.000000
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:12    Sequence
+0:12      Function Call: test( ( global structure{ global float x})
+0:?   Linker Objects
+
+
+Linked fragment stage:
+
+
+Shader version: 460
+ERROR: node is still EOpNull!
+0:7  Function Definition: test( ( global structure{ global float x})
+0:7    Function Parameters: 
+0:8    Sequence
+0:8      Branch: Return with expression
+0:8        Constant:
+0:8          1.000000
+0:11  Function Definition: main( ( global void)
+0:11    Function Parameters: 
+0:12    Sequence
+0:12      Function Call: test( ( global structure{ global float x})
+0:?   Linker Objects
+
diff --git a/Test/struct.error.frag b/Test/struct.error.frag
new file mode 100644 (file)
index 0000000..29aba00
--- /dev/null
@@ -0,0 +1,14 @@
+#version 460
+
+struct A {
+       float x;
+};
+
+A test() {
+       return A(1.0);
+}
+
+void main() {
+       test().z; // A.z does not exist, causes a crash
+}
+
index f86e78b..515137b 100644 (file)
@@ -1035,14 +1035,22 @@ TIntermTyped* TParseContext::handleDotDereference(const TSourceLoc& loc, TInterm
             inheritMemoryQualifiers(base->getQualifier(), result->getWritableType().getQualifier());
         } else {
             auto baseSymbol = base;
-            while (baseSymbol->getAsSymbolNode() == nullptr)
-                baseSymbol = baseSymbol->getAsBinaryNode()->getLeft();
-            TString structName;
-            structName.append("\'").append(baseSymbol->getAsSymbolNode()->getName().c_str()).append( "\'");
-            error(loc, "no such field in structure", field.c_str(), structName.c_str());
+            while (baseSymbol->getAsSymbolNode() == nullptr) {
+                auto binaryNode = baseSymbol->getAsBinaryNode();
+                if (binaryNode == nullptr) break;
+                baseSymbol = binaryNode->getLeft();
+            }
+            if (baseSymbol->getAsSymbolNode() != nullptr) {
+                TString structName;
+                structName.append("\'").append(baseSymbol->getAsSymbolNode()->getName().c_str()).append("\'");
+                error(loc, "no such field in structure", field.c_str(), structName.c_str());
+            } else {
+                error(loc, "no such field in structure", field.c_str(), "");
+            }
         }
     } else
-        error(loc, "does not apply to this type:", field.c_str(), base->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str());
+        error(loc, "does not apply to this type:", field.c_str(),
+          base->getType().getCompleteString(intermediate.getEnhancedMsgs()).c_str());
 
     // Propagate noContraction up the dereference chain
     if (base->getQualifier().isNoContraction())
index 81633f9..12e0137 100644 (file)
@@ -211,6 +211,7 @@ INSTANTIATE_TEST_SUITE_P(
         "runtimeArray.vert",
         "simpleFunctionCall.frag",
         "stringToDouble.vert",
+        "struct.error.frag",
         "structAssignment.frag",
         "structDeref.frag",
         "structure.frag",