Validate function return and parameter types in IR generator
Prevents invalid types from making it to the pipeline stage generator,
when it's too late to do anything.
Bug: oss-fuzz:24542
Change-Id: I8b6fa2afd5d586b0e60bea82e0ec4f3ae43de973
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/307656
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/gpu/effects/GrSkSLFP.cpp b/src/gpu/effects/GrSkSLFP.cpp
index ab553be..235755b 100644
--- a/src/gpu/effects/GrSkSLFP.cpp
+++ b/src/gpu/effects/GrSkSLFP.cpp
@@ -212,7 +212,8 @@
GrGLSLFragmentProcessor* GrSkSLFP::onCreateGLSLInstance() const {
// Note: This is actually SkSL (again) but with inline format specifiers.
SkSL::PipelineStageArgs args;
- fEffect->toPipelineStage(fInputs->data(), fShaderCaps.get(), fShaderErrorHandler, &args);
+ SkAssertResult(fEffect->toPipelineStage(fInputs->data(), fShaderCaps.get(), fShaderErrorHandler,
+ &args));
return new GrGLSLSkSLFP(std::move(args));
}
diff --git a/src/sksl/SkSLGLSLCodeGenerator.cpp b/src/sksl/SkSLGLSLCodeGenerator.cpp
index e41967a..36b9391 100644
--- a/src/sksl/SkSLGLSLCodeGenerator.cpp
+++ b/src/sksl/SkSLGLSLCodeGenerator.cpp
@@ -1794,7 +1794,7 @@
}
write_stringstream(fExtraFunctions, *rawOut);
write_stringstream(body, *rawOut);
- return true;
+ return 0 == fErrors.errorCount();
}
}
diff --git a/src/sksl/SkSLIRGenerator.cpp b/src/sksl/SkSLIRGenerator.cpp
index 6c9ff18..1e240a5 100644
--- a/src/sksl/SkSLIRGenerator.cpp
+++ b/src/sksl/SkSLIRGenerator.cpp
@@ -13,6 +13,7 @@
#include "src/sksl/SkSLCompiler.h"
#include "src/sksl/SkSLParser.h"
+#include "src/sksl/SkSLUtil.h"
#include "src/sksl/ir/SkSLBinaryExpression.h"
#include "src/sksl/ir/SkSLBoolLiteral.h"
#include "src/sksl/ir/SkSLBreakStatement.h"
@@ -832,7 +833,17 @@
if (!returnType) {
return;
}
- if (returnType->nonnullable() == *fContext.fFragmentProcessor_Type) {
+ auto type_is_allowed = [&](const Type* t) {
+#if defined(SKSL_STANDALONE)
+ return true;
+#else
+ GrSLType unusedSLType;
+ return fKind != Program::kPipelineStage_Kind ||
+ type_to_grsltype(fContext, *t, &unusedSLType);
+#endif
+ };
+ if (returnType->nonnullable() == *fContext.fFragmentProcessor_Type ||
+ !type_is_allowed(returnType)) {
fErrors.error(f.fOffset,
"functions may not return type '" + returnType->displayName() + "'");
return;
@@ -848,12 +859,6 @@
if (!type) {
return;
}
- // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
- if (type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) {
- fErrors.error(param.fOffset,
- "parameters of type '" + type->displayName() + "' not allowed");
- return;
- }
for (int j = (int) pd.fSizeCount; j >= 1; j--) {
int size = (param.begin() + j)->getInt();
String name = type->name() + "[" + to_string(size) + "]";
@@ -863,6 +868,13 @@
*type,
size)));
}
+ // Only the (builtin) declarations of 'sample' are allowed to have FP parameters
+ if ((type->nonnullable() == *fContext.fFragmentProcessor_Type && !fIsBuiltinCode) ||
+ !type_is_allowed(type)) {
+ fErrors.error(param.fOffset,
+ "parameters of type '" + type->displayName() + "' not allowed");
+ return;
+ }
StringFragment name = pd.fName;
const Variable* var = (const Variable*) fSymbolTable->takeOwnership(
std::unique_ptr<const Symbol>(new Variable(param.fOffset,
diff --git a/src/sksl/SkSLPipelineStageCodeGenerator.cpp b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
index ababa98..acbeed0 100644
--- a/src/sksl/SkSLPipelineStageCodeGenerator.cpp
+++ b/src/sksl/SkSLPipelineStageCodeGenerator.cpp
@@ -177,26 +177,6 @@
INHERITED::writeSwitchStatement(s);
}
-static GrSLType glsltype(const Context& context, const Type& type) {
- if (type == *context.fFloat_Type) { return kFloat_GrSLType; }
- if (type == *context.fHalf_Type) { return kHalf_GrSLType; }
- if (type == *context.fFloat2_Type) { return kFloat2_GrSLType; }
- if (type == *context.fHalf2_Type) { return kHalf2_GrSLType; }
- if (type == *context.fFloat3_Type) { return kFloat3_GrSLType; }
- if (type == *context.fHalf3_Type) { return kHalf3_GrSLType; }
- if (type == *context.fFloat4_Type) { return kFloat4_GrSLType; }
- if (type == *context.fHalf4_Type) { return kHalf4_GrSLType; }
- if (type == *context.fFloat2x2_Type) { return kFloat2x2_GrSLType; }
- if (type == *context.fHalf2x2_Type) { return kHalf2x2_GrSLType; }
- if (type == *context.fFloat3x3_Type) { return kFloat3x3_GrSLType; }
- if (type == *context.fHalf3x3_Type) { return kHalf3x3_GrSLType; }
- if (type == *context.fFloat4x4_Type) { return kFloat4x4_GrSLType; }
- if (type == *context.fHalf4x4_Type) { return kHalf4x4_GrSLType; }
- if (type == *context.fVoid_Type) { return kVoid_GrSLType; }
- SK_ABORT("Unsupported type");
-}
-
-
void PipelineStageCodeGenerator::writeFunction(const FunctionDefinition& f) {
fFunctionHeader = "";
OutputStream* oldOut = fOut;
@@ -219,10 +199,18 @@
} else {
const FunctionDeclaration& decl = f.fDeclaration;
Compiler::GLSLFunction result;
- result.fReturnType = glsltype(fContext, decl.fReturnType);
+ if (!type_to_grsltype(fContext, decl.fReturnType, &result.fReturnType)) {
+ fErrors.error(f.fOffset, "unsupported return type");
+ return;
+ }
result.fName = decl.fName;
for (const Variable* v : decl.fParameters) {
- result.fParameters.emplace_back(v->fName, glsltype(fContext, v->fType));
+ GrSLType paramSLType;
+ if (!type_to_grsltype(fContext, v->fType, ¶mSLType)) {
+ fErrors.error(v->fOffset, "unsupported parameter type");
+ return;
+ }
+ result.fParameters.emplace_back(v->fName, paramSLType);
}
for (const auto& s : ((Block&) *f.fBody).fStatements) {
this->writeStatement(*s);
diff --git a/src/sksl/SkSLUtil.cpp b/src/sksl/SkSLUtil.cpp
index ae9157b..dca493e 100644
--- a/src/sksl/SkSLUtil.cpp
+++ b/src/sksl/SkSLUtil.cpp
@@ -7,6 +7,7 @@
#include "src/sksl/SkSLUtil.h"
+#include "src/sksl/SkSLContext.h"
#include "src/sksl/SkSLStringStream.h"
#ifndef __STDC_FORMAT_MACROS
@@ -73,4 +74,25 @@
}
}
+#if !defined(SKSL_STANDALONE)
+bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType) {
+ if (type == *context.fFloat_Type) { *outType = kFloat_GrSLType; return true; }
+ if (type == *context.fHalf_Type) { *outType = kHalf_GrSLType; return true; }
+ if (type == *context.fFloat2_Type) { *outType = kFloat2_GrSLType; return true; }
+ if (type == *context.fHalf2_Type) { *outType = kHalf2_GrSLType; return true; }
+ if (type == *context.fFloat3_Type) { *outType = kFloat3_GrSLType; return true; }
+ if (type == *context.fHalf3_Type) { *outType = kHalf3_GrSLType; return true; }
+ if (type == *context.fFloat4_Type) { *outType = kFloat4_GrSLType; return true; }
+ if (type == *context.fHalf4_Type) { *outType = kHalf4_GrSLType; return true; }
+ if (type == *context.fFloat2x2_Type) { *outType = kFloat2x2_GrSLType; return true; }
+ if (type == *context.fHalf2x2_Type) { *outType = kHalf2x2_GrSLType; return true; }
+ if (type == *context.fFloat3x3_Type) { *outType = kFloat3x3_GrSLType; return true; }
+ if (type == *context.fHalf3x3_Type) { *outType = kHalf3x3_GrSLType; return true; }
+ if (type == *context.fFloat4x4_Type) { *outType = kFloat4x4_GrSLType; return true; }
+ if (type == *context.fHalf4x4_Type) { *outType = kHalf4x4_GrSLType; return true; }
+ if (type == *context.fVoid_Type) { *outType = kVoid_GrSLType; return true; }
+ return false;
+}
+#endif
+
} // namespace
diff --git a/src/sksl/SkSLUtil.h b/src/sksl/SkSLUtil.h
index 552a99b..1c316a2 100644
--- a/src/sksl/SkSLUtil.h
+++ b/src/sksl/SkSLUtil.h
@@ -17,6 +17,7 @@
#ifndef SKSL_STANDALONE
#include "include/core/SkTypes.h"
+#include "include/private/GrTypesPriv.h"
#if SK_SUPPORT_GPU
#include "include/gpu/GrContextOptions.h"
#include "src/gpu/GrShaderCaps.h"
@@ -27,8 +28,10 @@
namespace SkSL {
+class Context;
class OutputStream;
class StringStream;
+class Type;
#if defined(SKSL_STANDALONE) || !SK_SUPPORT_GPU
@@ -401,6 +404,10 @@
};
#endif
+#if !defined(SKSL_STANDALONE)
+bool type_to_grsltype(const Context& context, const Type& type, GrSLType* outType);
+#endif
+
void write_stringstream(const StringStream& d, OutputStream& out);
// Returns true if op is '=' or any compound assignment operator ('+=', '-=', etc.)