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>
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index 4350e70..6092593 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -203,6 +203,7 @@
         VECTOR_UNARY_OP(kNegateF)
         VECTOR_UNARY_OP(kNegateI)
 
+        case ByteCodeInstruction::kClampIndex: return 0;
         case ByteCodeInstruction::kNotB: return 0;
         case ByteCodeInstruction::kNegateFN: return 0;
 
@@ -454,9 +455,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,
@@ -466,6 +474,8 @@
                     return 0;
                 }
                 this->writeExpression(*i.fIndex);
+                this->write(ByteCodeInstruction::kClampIndex);
+                this->write8(length);
                 if (stride != 1) {
                     this->write(ByteCodeInstruction::kPushImmediate);
                     this->write32(stride);