Reland "Interpreter: Bounds check array access, add bool return from run"
This is a reland of f42de9e1e535af7e1700e4758d22751ff6a4982e
Original change's description:
> Interpreter: Bounds check array access, add bool return from run
>
> Out of bounds access with constant indices is a compile error.
> At runtime, causes the interpreter to fail. Made several other
> conditions trigger the same failure logic, and updated all
> uses of the interpreter to validate success.
>
> Change-Id: I3720b3c83903220b010ec574121fc64dbe102378
> Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228256
> Commit-Queue: Brian Osman <brianosman@google.com>
> Reviewed-by: Mike Reed <reed@google.com>
Change-Id: I8849de815f7efb730ac9c55b6edd296cb9ca7599
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/228353
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/bench/SkSLInterpreterBench.cpp b/bench/SkSLInterpreterBench.cpp
index 3903388..054781f 100644
--- a/bench/SkSLInterpreterBench.cpp
+++ b/bench/SkSLInterpreterBench.cpp
@@ -53,9 +53,10 @@
fPixels.data() + 3 * fCount,
};
- fByteCode->runStriped(fMain, args, 4, fCount, nullptr, 0, nullptr, 0);
+ SkAssertResult(fByteCode->runStriped(fMain, args, 4, fCount,
+ nullptr, 0, nullptr, 0));
} else {
- fByteCode->run(fMain, fPixels.data(), nullptr, fCount, nullptr, 0);
+ SkAssertResult(fByteCode->run(fMain, fPixels.data(), nullptr, fCount, nullptr, 0));
}
}
}
@@ -186,7 +187,7 @@
}
// Trigger one run now to check correctness
- fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0);
+ SkAssertResult(fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0));
for (int i = 0; i < fGroups; ++i) {
for (int j = 1; j < fValues; ++j) {
SkASSERT(fDst[i * fValues + j] >= fDst[i * fValues + j - 1]);
@@ -196,7 +197,7 @@
void onDraw(int loops, SkCanvas*) override {
for (int i = 0; i < loops; i++) {
- fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0);
+ SkAssertResult(fByteCode->run(fMain, fSrc.data(), fDst.data(), fGroups, nullptr, 0));
}
}
diff --git a/modules/particles/src/SkParticleAffector.cpp b/modules/particles/src/SkParticleAffector.cpp
index 7c7fe0b..fe15df9 100644
--- a/modules/particles/src/SkParticleAffector.cpp
+++ b/modules/particles/src/SkParticleAffector.cpp
@@ -477,7 +477,7 @@
void onApply(const SkParticleUpdateParams& params, SkParticleState ps[], int count) override {
for (int i = 0; i < count; ++i) {
fRandomValue->setRandom(&ps[i].fRandom);
- fByteCode->run(fMain, &ps[i].fAge, nullptr, 1, ¶ms.fDeltaTime, 2);
+ SkAssertResult(fByteCode->run(fMain, &ps[i].fAge, nullptr, 1, ¶ms.fDeltaTime, 2));
}
}
diff --git a/src/opts/SkRasterPipeline_opts.h b/src/opts/SkRasterPipeline_opts.h
index 760f0dc..979e9e4 100644
--- a/src/opts/SkRasterPipeline_opts.h
+++ b/src/opts/SkRasterPipeline_opts.h
@@ -2584,8 +2584,8 @@
sk_unaligned_store(aa, a);
}
- c->byteCode->runStriped(c->fn, in_args, in_count, tail ? tail : N,
- (const float*)c->inputs, c->ninputs, nullptr, 0);
+ SkAssertResult(c->byteCode->runStriped(c->fn, in_args, in_count, tail ? tail : N,
+ (const float*)c->inputs, c->ninputs, nullptr, 0));
r = sk_unaligned_load<F>(rr);
g = sk_unaligned_load<F>(gg);
diff --git a/src/sksl/SkSLByteCode.cpp b/src/sksl/SkSLByteCode.cpp
index 3f46c8e..9cb13a8 100644
--- a/src/sksl/SkSLByteCode.cpp
+++ b/src/sksl/SkSLByteCode.cpp
@@ -59,6 +59,7 @@
printf("callexternal %d, %d, %d", argumentCount, returnCount, externalValue);
break;
}
+ case ByteCodeInstruction::kClampIndex: printf("clampindex %d", READ8()); break;
VECTOR_DISASSEMBLE(kCompareIEQ, "compareieq")
VECTOR_DISASSEMBLE(kCompareINEQ, "compareineq")
VECTOR_MATRIX_DISASSEMBLE(kCompareFEQ, "comparefeq")
@@ -356,7 +357,7 @@
#define spf(index) sp[index].fFloat
-static void innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
+static bool innerRun(const ByteCode* byteCode, const ByteCodeFunction* f, VValue* stack,
float* outReturn[], VValue globals[], bool stripedOutput, int N,
int baseIndex) {
// Needs to be the first N non-negative integers, at least as large as VecWidth
@@ -387,8 +388,7 @@
if (f->fConditionCount + 1 > (int)SK_ARRAY_COUNT(condStack) ||
f->fLoopCount + 1 > (int)SK_ARRAY_COUNT(loopStack)) {
- SkDEBUGFAIL("Function with too much nested control flow to evaluate");
- return;
+ return false;
}
auto mask = [&]() { return *maskPtr & *loopPtr; };
@@ -468,6 +468,14 @@
break;
}
+ case ByteCodeInstruction::kClampIndex: {
+ int length = READ8();
+ if (skvx::any(mask() & ((sp[0].fSigned < 0) | (sp[0].fSigned >= length)))) {
+ return false;
+ }
+ break;
+ }
+
VECTOR_BINARY_OP(kCompareIEQ, fSigned, ==)
VECTOR_MATRIX_BINARY_OP(kCompareFEQ, fFloat, ==)
VECTOR_BINARY_OP(kCompareINEQ, fSigned, !=)
@@ -841,7 +849,7 @@
}
}
}
- return;
+ return true;
} else {
// When we were called, the caller reserved stack space for their copy of our
// return value, then 'stack' was positioned after that, where our parameters
@@ -1076,8 +1084,11 @@
default:
SkDEBUGFAILF("unsupported instruction %d\n", (int) inst);
+ return false;
}
}
+ // Unreachable
+ return false;
}
} // namespace Interpreter
@@ -1097,7 +1108,7 @@
#endif
}
-void ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
+bool ByteCode::run(const ByteCodeFunction* f, float* args, float* outReturn, int N,
const float* uniforms, int uniformCount) const {
#if defined(SK_ENABLE_SKSL_INTERPRETER)
#ifdef TRACE
@@ -1106,13 +1117,17 @@
Interpreter::VValue stack[128];
int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
- SkDEBUGFAIL("Function requires too much stack space to evaluate");
- return;
+ return false;
}
- SkASSERT(uniformCount == (int)fInputSlots.size());
+ if (uniformCount != (int)fInputSlots.size()) {
+ return false;
+ }
+
Interpreter::VValue globals[32];
- SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
+ if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
+ return false;
+ }
for (uint8_t slot : fInputSlots) {
globals[slot].fFloat = *uniforms++;
}
@@ -1136,7 +1151,9 @@
bool stripedOutput = false;
float** outArray = outReturn ? &outReturn : nullptr;
- innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex);
+ if (!innerRun(this, f, stack, outArray, globals, stripedOutput, w, baseIndex)) {
+ return false;
+ }
// Transpose out parameters back
{
@@ -1164,12 +1181,14 @@
N -= w;
baseIndex += w;
}
+ return true;
#else
SkDEBUGFAIL("ByteCode interpreter not enabled");
+ return false;
#endif
}
-void ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
+bool ByteCode::runStriped(const ByteCodeFunction* f, float* args[], int nargs, int N,
const float* uniforms, int uniformCount,
float* outArgs[], int outCount) const {
#if defined(SK_ENABLE_SKSL_INTERPRETER)
@@ -1179,8 +1198,21 @@
Interpreter::VValue stack[128];
int stackNeeded = f->fParameterCount + f->fLocalCount + f->fStackCount;
if (stackNeeded > (int)SK_ARRAY_COUNT(stack)) {
- SkDEBUGFAIL("Function requires too much stack space to evaluate");
- return;
+ return false;
+ }
+
+ if (nargs != f->fParameterCount ||
+ outCount != f->fReturnCount ||
+ uniformCount != (int)fInputSlots.size()) {
+ return false;
+ }
+
+ Interpreter::VValue globals[32];
+ if (fGlobalCount > (int)SK_ARRAY_COUNT(globals)) {
+ return false;
+ }
+ for (uint8_t slot : fInputSlots) {
+ globals[slot].fFloat = *uniforms++;
}
// innerRun just takes outArgs, so clear it if the count is zero
@@ -1188,15 +1220,6 @@
outArgs = nullptr;
}
- SkASSERT(nargs == f->fParameterCount);
- SkASSERT(outCount == f->fReturnCount);
- SkASSERT(uniformCount == (int)fInputSlots.size());
- Interpreter::VValue globals[32];
- SkASSERT((int)SK_ARRAY_COUNT(globals) >= fGlobalCount);
- for (uint8_t slot : fInputSlots) {
- globals[slot].fFloat = *uniforms++;
- }
-
int baseIndex = 0;
while (N) {
@@ -1208,7 +1231,9 @@
}
bool stripedOutput = true;
- innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex);
+ if (!innerRun(this, f, stack, outArgs, globals, stripedOutput, w, baseIndex)) {
+ return false;
+ }
// Copy out parameters back
int slot = 0;
@@ -1228,8 +1253,11 @@
N -= w;
baseIndex += w;
}
+
+ return true;
#else
SkDEBUGFAIL("ByteCode interpreter not enabled");
+ return false;
#endif
}
diff --git a/src/sksl/SkSLByteCode.h b/src/sksl/SkSLByteCode.h
index 4ae0470..27c21de 100644
--- a/src/sksl/SkSLByteCode.h
+++ b/src/sksl/SkSLByteCode.h
@@ -32,6 +32,8 @@
// Followed by three bytes indicating: the number of argument slots, the number of return slots,
// and the index of the external value to call
kCallExternal,
+ // For dynamic array access: Followed by byte indicating length of array
+ kClampIndex,
VECTOR(kCompareIEQ),
VECTOR(kCompareINEQ),
VECTOR_MATRIX(kCompareFEQ),
@@ -198,15 +200,13 @@
* The return value is stored in 'outReturn' (may be null, to discard the return value).
* 'uniforms' are mapped to 'uniform' globals, in order.
*/
- void run(const ByteCodeFunction*, float* args, float* outReturn, int N,
- const float* uniforms, int uniformCount) const;
+ bool SKSL_WARN_UNUSED_RESULT run(const ByteCodeFunction*, float* args, float* outReturn, int N,
+ const float* uniforms, int uniformCount) const;
- // For now, if outArgCount > 0, then we will memcpy VecWidth number of elements into
- // each slot in outArgs. This may change in the future, as that may be more than is actually
- // valid (depending on the N that was passed in.
- void runStriped(const ByteCodeFunction*, float* args[], int nargs, int N,
- const float* uniforms, int uniformCount,
- float* outArgs[], int outArgCount) const;
+ bool SKSL_WARN_UNUSED_RESULT runStriped(const ByteCodeFunction*,
+ float* args[], int nargs, int N,
+ const float* uniforms, int uniformCount,
+ float* outArgs[], int outArgCount) const;
};
}
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 8893ddb..f1fdbdd 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -208,6 +208,7 @@
case ByteCodeInstruction::kInverse3x3:
case ByteCodeInstruction::kInverse4x4: return 0;
+ case ByteCodeInstruction::kClampIndex: return 0;
case ByteCodeInstruction::kNotB: return 0;
case ByteCodeInstruction::kNegateFN: return 0;
@@ -459,9 +460,16 @@
case Expression::kIndex_Kind: {
const IndexExpression& i = (const IndexExpression&)expr;
int stride = SlotCount(i.fType);
+ int length = i.fBase->fType.columns();
+ SkASSERT(length <= 255);
int offset = -1;
if (i.fIndex->isConstant()) {
- offset = i.fIndex->getConstantInt() * stride;
+ int64_t index = i.fIndex->getConstantInt();
+ if (index < 0 || index >= length) {
+ fErrors.error(i.fIndex->fOffset, "Array index out of bounds.");
+ return 0;
+ }
+ offset = index * stride;
} else {
if (i.fIndex->hasSideEffects()) {
// Having a side-effect in an indexer is technically safe for an rvalue,
@@ -471,6 +479,8 @@
return 0;
}
this->writeExpression(*i.fIndex);
+ this->write(ByteCodeInstruction::kClampIndex);
+ this->write8(length);
if (stride != 1) {
this->write(ByteCodeInstruction::kPushImmediate);
this->write32(stride);
@@ -829,7 +839,7 @@
}
void ByteCodeGenerator::writeVariableExpression(const Expression& expr) {
- Variable::Storage storage;
+ Variable::Storage storage = Variable::kLocal_Storage;
int location = this->getLocation(expr, &storage);
bool isGlobal = storage == Variable::kGlobal_Storage;
int count = SlotCount(expr.fType);
@@ -1230,7 +1240,7 @@
if (!discard) {
fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
}
- Variable::Storage storage;
+ Variable::Storage storage = Variable::kLocal_Storage;
int location = fGenerator.getLocation(*fSwizzle.fBase, &storage);
bool isGlobal = storage == Variable::kGlobal_Storage;
if (location < 0) {
@@ -1275,7 +1285,7 @@
fGenerator.write(vector_instruction(ByteCodeInstruction::kDup, count));
}
}
- Variable::Storage storage;
+ Variable::Storage storage = Variable::kLocal_Storage;
int location = fGenerator.getLocation(fExpression, &storage);
bool isGlobal = storage == Variable::kGlobal_Storage;
if (location < 0 || count > 4) {
diff --git a/src/sksl/SkSLDefines.h b/src/sksl/SkSLDefines.h
index 43f89a2..c90cf3f 100644
--- a/src/sksl/SkSLDefines.h
+++ b/src/sksl/SkSLDefines.h
@@ -29,12 +29,12 @@
#include "include/core/SkTypes.h"
#endif
-#define SKSL_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
-
#if defined(__clang__) || defined(__GNUC__)
#define SKSL_PRINTF_LIKE(A, B) __attribute__((format(printf, (A), (B))))
+#define SKSL_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
#else
#define SKSL_PRINTF_LIKE(A, B)
+#define SKSL_WARN_UNUSED_RESULT
#endif
#define ABORT(...) (printf(__VA_ARGS__), sksl_abort())
diff --git a/tests/SkSLInterpreterTest.cpp b/tests/SkSLInterpreterTest.cpp
index c05a136..54ee954 100644
--- a/tests/SkSLInterpreterTest.cpp
+++ b/tests/SkSLInterpreterTest.cpp
@@ -40,7 +40,7 @@
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
std::unique_ptr<float[]> out = std::unique_ptr<float[]>(new float[expectedCount]);
- byteCode->run(main, in, out.get(), 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, in, out.get(), 1, nullptr, 0));
bool valid = exactCompare ? !memcmp(out.get(), expected, sizeof(float) * expectedCount)
: nearly_equal(out.get(), expected, expectedCount);
if (!valid) {
@@ -95,11 +95,11 @@
// First run in scalar mode to determine the expected output
for (int i = 0; i < 4; ++i) {
- byteCode->run(main, out_s + i * 4, nullptr, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, out_s + i * 4, nullptr, 1, nullptr, 0));
}
// Now run in parallel and compare results
- byteCode->run(main, out_v, nullptr, 4, nullptr, 0);
+ SkAssertResult(byteCode->run(main, out_v, nullptr, 4, nullptr, 0));
if (memcmp(out_s, out_v, sizeof(out_s)) != 0) {
printf("for program: %s\n", src);
for (int i = 0; i < 4; ++i) {
@@ -131,7 +131,7 @@
}
const SkSL::ByteCodeFunction* main = byteCode->getFunction("main");
float inoutColor[4] = { inR, inG, inB, inA };
- byteCode->run(main, inoutColor, nullptr, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, inoutColor, nullptr, 1, nullptr, 0));
if (inoutColor[0] != expectedR || inoutColor[1] != expectedG ||
inoutColor[2] != expectedB || inoutColor[3] != expectedA) {
printf("for program: %s\n", src);
@@ -559,14 +559,14 @@
{
SkIRect in = SkIRect::MakeXYWH(10, 10, 20, 30);
int out = 0;
- byteCode->run(rect_height, (float*)&in, (float*)&out, 1, (float*)gRects, 16);
+ SkAssertResult(byteCode->run(rect_height, (float*)&in, (float*)&out, 1, (float*)gRects, 16));
REPORTER_ASSERT(r, out == 30);
}
{
int in[2] = { 15, 25 };
RectAndColor out;
- byteCode->run(make_blue_rect, (float*)in, (float*)&out, 1, (float*)gRects, 16);
+ SkAssertResult(byteCode->run(make_blue_rect, (float*)in, (float*)&out, 1, (float*)gRects, 16));
REPORTER_ASSERT(r, out.fRect.width() == 15);
REPORTER_ASSERT(r, out.fRect.height() == 25);
SkColor4f blue = { 0.0f, 1.0f, 0.0f, 1.0f };
@@ -576,14 +576,14 @@
{
int in[15] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
int out = 0;
- byteCode->run(median, (float*)in, (float*)&out, 1, (float*)gRects, 16);
+ SkAssertResult(byteCode->run(median, (float*)in, (float*)&out, 1, (float*)gRects, 16));
REPORTER_ASSERT(r, out == 8);
}
{
float in[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
float out[8] = { 0 };
- byteCode->run(sums, in, out, 1, (float*)gRects, 16);
+ SkAssertResult(byteCode->run(sums, in, out, 1, (float*)gRects, 16));
for (int i = 0; i < 8; ++i) {
REPORTER_ASSERT(r, out[i] == static_cast<float>((i + 1) * (i + 2) / 2));
}
@@ -592,7 +592,7 @@
{
int in = 2;
SkIRect out = SkIRect::MakeEmpty();
- byteCode->run(get_rect, (float*)&in, (float*)&out, 1, (float*)gRects, 16);
+ SkAssertResult(byteCode->run(get_rect, (float*)&in, (float*)&out, 1, (float*)gRects, 16));
REPORTER_ASSERT(r, out == gRects[2]);
}
@@ -600,7 +600,7 @@
ManyRects in;
memset(&in, 0, sizeof(in));
in.fNumRects = 2;
- byteCode->run(fill_rects, (float*)&in, nullptr, 1, (float*)gRects, 16);
+ SkAssertResult(byteCode->run(fill_rects, (float*)&in, nullptr, 1, (float*)gRects, 16));
ManyRects expected;
memset(&expected, 0, sizeof(expected));
expected.fNumRects = 2;
@@ -613,27 +613,55 @@
}
}
+static void expect_failure(skiatest::Reporter* r, const char* src) {
+ SkSL::Compiler compiler;
+ auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind, SkSL::String(src),
+ SkSL::Program::Settings());
+ REPORTER_ASSERT(r, program);
+
+ auto byteCode = compiler.toByteCode(*program);
+ REPORTER_ASSERT(r, compiler.errorCount() > 0);
+ REPORTER_ASSERT(r, !byteCode);
+}
+
+static void expect_run_failure(skiatest::Reporter* r, const char* src, float* in) {
+ SkSL::Compiler compiler;
+ auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind, SkSL::String(src),
+ SkSL::Program::Settings());
+ REPORTER_ASSERT(r, program);
+
+ auto byteCode = compiler.toByteCode(*program);
+ REPORTER_ASSERT(r, byteCode);
+
+ bool result = byteCode->run(byteCode->getFunction("main"), in, nullptr, 1, nullptr, 0);
+ REPORTER_ASSERT(r, !result);
+}
+
DEF_TEST(SkSLInterpreterRestrictFunctionCalls, r) {
- auto check = [r](const char* src) {
- SkSL::Compiler compiler;
- auto program = compiler.convertProgram(SkSL::Program::kGeneric_Kind, SkSL::String(src),
- SkSL::Program::Settings());
- REPORTER_ASSERT(r, program);
-
- auto byteCode = compiler.toByteCode(*program);
- REPORTER_ASSERT(r, compiler.errorCount() > 0);
- REPORTER_ASSERT(r, !byteCode);
- };
-
// Ensure that simple recursion is not allowed
- check("float main() { return main() + 1; }");
+ expect_failure(r, "float main() { return main() + 1; }");
// Ensure that calls to undefined functions are not allowed (to prevent mutual recursion)
- check("float foo(); float bar() { return foo(); } float foo() { return bar(); }");
+ expect_failure(r, "float foo(); float bar() { return foo(); } float foo() { return bar(); }");
// returns are not allowed inside conditionals (or loops, which are effectively the same thing)
- check("float main(float x, float y) { if (x < y) { return x; } return y; }");
- check("float main(float x) { while (x > 1) { return x; } return 0; }");
+ expect_failure(r, "float main(float x, float y) { if (x < y) { return x; } return y; }");
+ expect_failure(r, "float main(float x) { while (x > 1) { return x; } return 0; }");
+}
+
+DEF_TEST(SkSLInterpreterArrayBounds, r) {
+ // Out of bounds array access at compile time
+ expect_failure(r, "float main(float x[4]) { return x[-1]; }");
+ expect_failure(r, "float2 main(float2 x[2]) { return x[2]; }");
+
+ // Out of bounds array access at runtime is pinned, and we don't update any inout data
+ float in[3] = { -1.0f, 1.0f, 2.0f };
+ expect_run_failure(r, "void main(inout float data[3]) { data[int(data[0])] = 0; }", in);
+ REPORTER_ASSERT(r, in[0] == -1.0f && in[1] == 1.0f && in[2] == 2.0f);
+
+ in[0] = 3.0f;
+ expect_run_failure(r, "void main(inout float data[3]) { data[int(data[0])] = 0; }", in);
+ REPORTER_ASSERT(r, in[0] == 3.0f && in[1] == 1.0f && in[2] == 2.0f);
}
DEF_TEST(SkSLInterpreterFunctions, r) {
@@ -674,13 +702,13 @@
float out = 0.0f;
float in = 3.0f;
- byteCode->run(main, &in, &out, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, &in, &out, 1, nullptr, 0));
REPORTER_ASSERT(r, out = 6.0f);
- byteCode->run(dot3, &in, &out, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(dot3, &in, &out, 1, nullptr, 0));
REPORTER_ASSERT(r, out = 9.0f);
- byteCode->run(dot2, &in, &out, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(dot2, &in, &out, 1, nullptr, 0));
REPORTER_ASSERT(r, out = -1.0f);
}
@@ -910,7 +938,7 @@
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
float out;
- byteCode->run(main, nullptr, &out, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, nullptr, &out, 1, nullptr, 0));
REPORTER_ASSERT(r, out == 66.0);
REPORTER_ASSERT(r, outValue == 152);
} else {
@@ -942,7 +970,7 @@
return;
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
- byteCode->run(main, nullptr, nullptr, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, nullptr, nullptr, 1, nullptr, 0));
REPORTER_ASSERT(r, value[0] == 2);
REPORTER_ASSERT(r, value[1] == 4);
REPORTER_ASSERT(r, value[2] == 6);
@@ -1008,7 +1036,7 @@
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
float out;
- byteCode->run(main, nullptr, &out, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, nullptr, &out, 1, nullptr, 0));
REPORTER_ASSERT(r, out == 5.0);
} else {
printf("%s\n%s", src, compiler.errorText().c_str());
@@ -1076,7 +1104,7 @@
}
SkSL::ByteCodeFunction* main = byteCode->fFunctions[0].get();
float out[4];
- byteCode->run(main, nullptr, out, 1, nullptr, 0);
+ SkAssertResult(byteCode->run(main, nullptr, out, 1, nullptr, 0));
REPORTER_ASSERT(r, out[0] == 1.0);
REPORTER_ASSERT(r, out[1] == 2.0);
REPORTER_ASSERT(r, out[2] == 3.0);