Added type security checks to the DSL

Private / unsupported types are now restricted to module code.

Change-Id: I98cb2e0822560a274758d99ecf0ca09883d0c3a1
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/445097
Reviewed-by: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 51ced68..f60ca6a 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -839,21 +839,6 @@
     }
 }
 
-static bool type_contains_private_fields(const Type& type) {
-    // Checks for usage of private types, including fields inside a struct.
-    if (type.isPrivate()) {
-        return true;
-    }
-    if (type.isStruct()) {
-        for (const auto& f : type.fields()) {
-            if (type_contains_private_fields(*f.fType)) {
-                return true;
-            }
-        }
-    }
-    return false;
-}
-
 const Type* IRGenerator::convertType(const ASTNode& type, bool allowVoid) {
     skstd::string_view name = type.getStringView();
     const Symbol* symbol = (*fSymbolTable)[name];
@@ -869,7 +854,7 @@
         return nullptr;
     }
     if (!fIsBuiltinCode) {
-        if (type_contains_private_fields(*result)) {
+        if (result->containsPrivateFields()) {
             this->errorReporter().error(type.fOffset, "type '" + name + "' is private");
             return nullptr;
         }
diff --git a/src/sksl/dsl/DSLType.cpp b/src/sksl/dsl/DSLType.cpp
index 76fd7b1..2827f3a 100644
--- a/src/sksl/dsl/DSLType.cpp
+++ b/src/sksl/dsl/DSLType.cpp
@@ -27,7 +27,18 @@
                                               (int)name.length(), name.data()).c_str());
         return nullptr;
     }
-    return &symbol->as<Type>();
+    const Type& result = symbol->as<Type>();
+    if (!DSLWriter::IsModule()) {
+        if (result.containsPrivateFields()) {
+            DSLWriter::ReportError(("type '" + String(name) + "' is private").c_str());
+            return nullptr;
+        }
+        if (DSLWriter::Context().fConfig->strictES2Mode() && !result.allowedInES2()) {
+            DSLWriter::ReportError(("type '" + String(name) + "' is not supported").c_str());
+            return nullptr;
+        }
+    }
+    return &result;
 }
 
 static const Type* find_type(skstd::string_view name, const Modifiers& modifiers,
diff --git a/src/sksl/ir/SkSLType.cpp b/src/sksl/ir/SkSLType.cpp
index 38db128..c30269a 100644
--- a/src/sksl/ir/SkSLType.cpp
+++ b/src/sksl/ir/SkSLType.cpp
@@ -749,6 +749,21 @@
     return this->isArray();
 }
 
+
+bool Type::containsPrivateFields() const {
+    if (this->isPrivate()) {
+        return true;
+    }
+    if (this->isStruct()) {
+        for (const auto& f : this->fields()) {
+            if (f.fType->containsPrivateFields()) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
 bool Type::checkForOutOfRangeLiteral(const Context& context, const Expression& expr) const {
     bool foundError = false;
     const Type& baseType = this->componentType();
diff --git a/src/sksl/ir/SkSLType.h b/src/sksl/ir/SkSLType.h
index a2f5a44..3023b82 100644
--- a/src/sksl/ir/SkSLType.h
+++ b/src/sksl/ir/SkSLType.h
@@ -511,6 +511,12 @@
     bool isOrContainsArray() const;
 
     /**
+     * Returns true if this type is either itself private or is a struct which contains private
+     * fields (recursively).
+     */
+    bool containsPrivateFields() const;
+
+    /**
      * Returns the corresponding vector or matrix type with the specified number of columns and
      * rows.
      */