Reland "Disallow constructors of ES3 types in ES2 code."
This is a reland of 36f53ec7e10e16ad6c33156a5d5fa25975cc7fac
Original change's description:
> Disallow constructors of ES3 types in ES2 code.
>
> The fuzzer found that we constructed TypeReferences without first
> checking for disallowed tyoes. (In fact, TypeReference creation had no
> error checking at all; it didn't even have Convert/Make functions.)
>
> Added proper Convert/Make to TypeReference, and used those calls to
> report errors or cause assertions if trying to make a TypeReference to a
> type that the program did not support.
>
> (While tracking down this bug, I added strict-ES2 type assertions to our
> constructor IR nodes as well. This helped pinpoint the error and seem
> reasonable to leave in, just in case.)
>
> Change-Id: I896b68ae9d3d9e1f30d7eba9fa594617ab851c74
> Bug: oss-fuzz:39540
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/455498
> Commit-Queue: John Stiles <johnstiles@google.com>
> Commit-Queue: Brian Osman <brianosman@google.com>
> Auto-Submit: John Stiles <johnstiles@google.com>
> Reviewed-by: Brian Osman <brianosman@google.com>
Bug: oss-fuzz:39540
Change-Id: Id8e323c22b18726214613b6061c08873048b7c69
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/455617
Auto-Submit: John Stiles <johnstiles@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/gn/sksl.gni b/gn/sksl.gni
index ea8d8f4..213e364 100644
--- a/gn/sksl.gni
+++ b/gn/sksl.gni
@@ -176,6 +176,7 @@
"$_src/sksl/ir/SkSLTernaryExpression.h",
"$_src/sksl/ir/SkSLType.cpp",
"$_src/sksl/ir/SkSLType.h",
+ "$_src/sksl/ir/SkSLTypeReference.cpp",
"$_src/sksl/ir/SkSLTypeReference.h",
"$_src/sksl/ir/SkSLUnresolvedFunction.h",
"$_src/sksl/ir/SkSLVarDeclarations.cpp",
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 4427d70..bcfdd90 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -360,8 +360,7 @@
FieldAccess::OwnerKind::kAnonymousInterfaceBlock);
}
case Symbol::Kind::kType: {
- const Type* t = &result->as<Type>();
- return std::make_unique<TypeReference>(fContext, line, t);
+ return TypeReference::Convert(fContext, line, &result->as<Type>());
}
case Symbol::Kind::kExternal: {
const ExternalFunction* r = &result->as<ExternalFunction>();
diff --git a/src/sksl/ir/SkSLConstructorArrayCast.cpp b/src/sksl/ir/SkSLConstructorArrayCast.cpp
index 46c97d4..55030ec 100644
--- a/src/sksl/ir/SkSLConstructorArrayCast.cpp
+++ b/src/sksl/ir/SkSLConstructorArrayCast.cpp
@@ -45,6 +45,7 @@
SkASSERT(type.isArray());
SkASSERT(arg->type().isArray());
SkASSERT(type.columns() == arg->type().columns());
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
// If this is a no-op cast, return the expression as-is.
if (type == arg->type()) {
diff --git a/src/sksl/ir/SkSLConstructorCompound.cpp b/src/sksl/ir/SkSLConstructorCompound.cpp
index 59a9a96..41c3954 100644
--- a/src/sksl/ir/SkSLConstructorCompound.cpp
+++ b/src/sksl/ir/SkSLConstructorCompound.cpp
@@ -17,6 +17,8 @@
int line,
const Type& type,
ExpressionArray args) {
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
+
// A scalar "composite" type with a single scalar argument is a no-op and can be eliminated.
// (Pedantically, this isn't a composite at all, but it's harmless to allow and simplifies
// call sites which need to narrow a vector and may sometimes end up with a scalar.)
diff --git a/src/sksl/ir/SkSLConstructorCompoundCast.cpp b/src/sksl/ir/SkSLConstructorCompoundCast.cpp
index e96c3d0..9f6b5d6 100644
--- a/src/sksl/ir/SkSLConstructorCompoundCast.cpp
+++ b/src/sksl/ir/SkSLConstructorCompoundCast.cpp
@@ -66,6 +66,7 @@
std::unique_ptr<Expression> arg) {
// Only vectors or matrices of the same dimensions are allowed.
SkASSERT(type.isVector() || type.isMatrix());
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
SkASSERT(arg->type().isVector() == type.isVector());
SkASSERT(arg->type().isMatrix() == type.isMatrix());
SkASSERT(type.columns() == arg->type().columns());
diff --git a/src/sksl/ir/SkSLConstructorDiagonalMatrix.cpp b/src/sksl/ir/SkSLConstructorDiagonalMatrix.cpp
index 1762df6..2f85d16 100644
--- a/src/sksl/ir/SkSLConstructorDiagonalMatrix.cpp
+++ b/src/sksl/ir/SkSLConstructorDiagonalMatrix.cpp
@@ -17,6 +17,7 @@
const Type& type,
std::unique_ptr<Expression> arg) {
SkASSERT(type.isMatrix());
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
SkASSERT(arg->type().isScalar());
SkASSERT(arg->type() == type.componentType());
return std::make_unique<ConstructorDiagonalMatrix>(line, type, std::move(arg));
diff --git a/src/sksl/ir/SkSLConstructorMatrixResize.cpp b/src/sksl/ir/SkSLConstructorMatrixResize.cpp
index 3639e4c..c9fcf70 100644
--- a/src/sksl/ir/SkSLConstructorMatrixResize.cpp
+++ b/src/sksl/ir/SkSLConstructorMatrixResize.cpp
@@ -17,6 +17,7 @@
const Type& type,
std::unique_ptr<Expression> arg) {
SkASSERT(type.isMatrix());
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
SkASSERT(arg->type().componentType() == type.componentType());
// If the matrix isn't actually changing size, return it as-is.
diff --git a/src/sksl/ir/SkSLConstructorScalarCast.cpp b/src/sksl/ir/SkSLConstructorScalarCast.cpp
index a34b9e4..0c1d353 100644
--- a/src/sksl/ir/SkSLConstructorScalarCast.cpp
+++ b/src/sksl/ir/SkSLConstructorScalarCast.cpp
@@ -52,6 +52,7 @@
const Type& type,
std::unique_ptr<Expression> arg) {
SkASSERT(type.isScalar());
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
SkASSERT(arg->type().isScalar());
// No cast required when the types match.
diff --git a/src/sksl/ir/SkSLConstructorSplat.cpp b/src/sksl/ir/SkSLConstructorSplat.cpp
index 54d30bf..ac07690 100644
--- a/src/sksl/ir/SkSLConstructorSplat.cpp
+++ b/src/sksl/ir/SkSLConstructorSplat.cpp
@@ -14,6 +14,7 @@
int line,
const Type& type,
std::unique_ptr<Expression> arg) {
+ SkASSERT(type.allowedInES2() || !context.fConfig->strictES2Mode());
SkASSERT(arg->type().scalarTypeForLiteral() == type.componentType().scalarTypeForLiteral());
SkASSERT(arg->type().isScalar());
diff --git a/src/sksl/ir/SkSLIndexExpression.cpp b/src/sksl/ir/SkSLIndexExpression.cpp
index e4434e2..35752bd 100644
--- a/src/sksl/ir/SkSLIndexExpression.cpp
+++ b/src/sksl/ir/SkSLIndexExpression.cpp
@@ -8,6 +8,7 @@
#include "src/sksl/SkSLConstantFolder.h"
#include "src/sksl/ir/SkSLIndexExpression.h"
#include "src/sksl/ir/SkSLSwizzle.h"
+#include "src/sksl/ir/SkSLTypeReference.h"
namespace SkSL {
@@ -43,8 +44,8 @@
if (!arraySize) {
return nullptr;
}
- return std::make_unique<TypeReference>(context, base->fLine,
- symbolTable.addArrayDimension(&baseType, arraySize));
+ return TypeReference::Convert(context, base->fLine,
+ symbolTable.addArrayDimension(&baseType, arraySize));
}
// Convert an index expression with an expression inside of it: `arr[a * 3]`.
const Type& baseType = base->type();
diff --git a/src/sksl/ir/SkSLTypeReference.cpp b/src/sksl/ir/SkSLTypeReference.cpp
new file mode 100644
index 0000000..dda468b
--- /dev/null
+++ b/src/sksl/ir/SkSLTypeReference.cpp
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2021 Google LLC
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "src/sksl/ir/SkSLTypeReference.h"
+
+#include "include/sksl/SkSLErrorReporter.h"
+#include "src/sksl/SkSLProgramSettings.h"
+
+namespace SkSL {
+
+std::unique_ptr<TypeReference> TypeReference::Convert(const Context& context,
+ int line,
+ const Type* type) {
+ if (context.fConfig->strictES2Mode() && !type->allowedInES2()) {
+ context.fErrors->error(line, "type '" + type->displayName() + "' is not supported");
+ return nullptr;
+ }
+ return TypeReference::Make(context, line, type);
+}
+
+std::unique_ptr<TypeReference> TypeReference::Make(const Context& context,
+ int line,
+ const Type* type) {
+ SkASSERT(type->allowedInES2() || !context.fConfig->strictES2Mode());
+ return std::make_unique<TypeReference>(context, line, type);
+}
+
+} // namespace SkSL
diff --git a/src/sksl/ir/SkSLTypeReference.h b/src/sksl/ir/SkSLTypeReference.h
index 5bab7ed..38b6ff4 100644
--- a/src/sksl/ir/SkSLTypeReference.h
+++ b/src/sksl/ir/SkSLTypeReference.h
@@ -22,8 +22,15 @@
static constexpr Kind kExpressionKind = Kind::kTypeReference;
TypeReference(const Context& context, int line, const Type* value)
- : INHERITED(line, kExpressionKind, context.fTypes.fInvalid.get())
- , fValue(*value) {}
+ : TypeReference(line, value, context.fTypes.fInvalid.get()) {}
+
+ // Creates a reference to an SkSL type; uses the ErrorReporter to report errors.
+ static std::unique_ptr<TypeReference> Convert(const Context& context,
+ int line,
+ const Type* type);
+
+ // Creates a reference to an SkSL type; reports errors via ASSERT.
+ static std::unique_ptr<TypeReference> Make(const Context& context, int line, const Type* type);
const Type& value() const {
return fValue;
diff --git a/tests/sksl/runtime_errors/ES3Types.skvm b/tests/sksl/runtime_errors/ES3Types.skvm
index f65aeb6..650f19b 100644
--- a/tests/sksl/runtime_errors/ES3Types.skvm
+++ b/tests/sksl/runtime_errors/ES3Types.skvm
@@ -26,5 +26,9 @@
error: 29: type 'half4x2' is not supported
error: 30: type 'ushort' is not supported
error: 31: type 'uint' is not supported
-error: 37: construction of array type 'ushort[2]' is not supported
-27 errors
+error: 33: type 'float2x3' is not supported
+error: 34: type 'half4x2' is not supported
+error: 35: type 'uint' is not supported
+error: 36: type 'ushort4' is not supported
+error: 37: type 'ushort' is not supported
+31 errors