Avoid double-free in functions cloned for vulkan relaxed mode (#2987)
authorDavid Neto <dneto@google.com>
Wed, 3 Aug 2022 00:07:01 +0000 (20:07 -0400)
committerGitHub <noreply@github.com>
Wed, 3 Aug 2022 00:07:01 +0000 (18:07 -0600)
* Avoid double-free in functions cloned for vulkan relaxed mode

When rewriting function calls atomicCounterIncrement and
atoicCounterDecrement, clone the parameters so that the TParameter
'type' field is cloned.  This avoids double-free when both the original
and transformed functions are deleted by the parser.

Fixes a ubsan failure.

glslang/MachineIndependent/ParseHelper.cpp
glslang/MachineIndependent/SymbolTable.cpp
glslang/MachineIndependent/SymbolTable.h

index 6f41bfa..e6e3db8 100644 (file)
@@ -7035,12 +7035,14 @@ TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, T
 
         TFunction realFunc(&name, function->getType());
 
+        // Use copyParam to avoid shared ownership of the 'type' field
+        // of the parameter.
         for (int i = 0; i < function->getParamCount(); ++i) {
-            realFunc.addParameter((*function)[i]);
+            realFunc.addParameter(TParameter().copyParam((*function)[i]));
         }
 
         TParameter tmpP = { 0, &uintType };
-        realFunc.addParameter(tmpP);
+        realFunc.addParameter(TParameter().copyParam(tmpP));
         arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(1, loc, true));
 
         result = handleFunctionCall(loc, &realFunc, arguments);
@@ -7053,11 +7055,11 @@ TIntermTyped* TParseContext::vkRelaxedRemapFunctionCall(const TSourceLoc& loc, T
         TFunction realFunc(&name, function->getType());
 
         for (int i = 0; i < function->getParamCount(); ++i) {
-            realFunc.addParameter((*function)[i]);
+            realFunc.addParameter(TParameter().copyParam((*function)[i]));
         }
 
         TParameter tmpP = { 0, &uintType };
-        realFunc.addParameter(tmpP);
+        realFunc.addParameter(TParameter().copyParam(tmpP));
         arguments = intermediate.growAggregate(arguments, intermediate.addConstantUnion(-1, loc, true));
 
         result = handleFunctionCall(loc, &realFunc, arguments);
index a3ffa0c..2f1b5ac 100644 (file)
@@ -383,7 +383,7 @@ TFunction::TFunction(const TFunction& copyOf) : TSymbol(copyOf)
     for (unsigned int i = 0; i < copyOf.parameters.size(); ++i) {
         TParameter param;
         parameters.push_back(param);
-        parameters.back().copyParam(copyOf.parameters[i]);
+        (void)parameters.back().copyParam(copyOf.parameters[i]);
     }
 
     extensions = nullptr;
index 31312ec..2e570bb 100644 (file)
@@ -224,7 +224,7 @@ struct TParameter {
     TString *name;
     TType* type;
     TIntermTyped* defaultValue;
-    void copyParam(const TParameter& param)
+    TParameter& copyParam(const TParameter& param)
     {
         if (param.name)
             name = NewPoolTString(param.name->c_str());
@@ -232,6 +232,7 @@ struct TParameter {
             name = 0;
         type = param.type->clone();
         defaultValue = param.defaultValue;
+        return *this;
     }
     TBuiltInVariable getDeclaredBuiltIn() const { return type->getQualifier().declaredBuiltIn; }
 };