Harden MetalCodeGenerator::writeFields

Prevent signed integer overflow, and return early once an error is
detected (so that the invariants of the logic are guaranteed on
subsequent iterations).

Also: Make the generator actually return false when there are errors.

Bug: oss-fuzz:23178
Change-Id: Ic8777f144f747a9b74e39636c4ee175170cbe497
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/315649
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLMetalCodeGenerator.cpp b/src/sksl/SkSLMetalCodeGenerator.cpp
index bafa4d5..ab536f2 100644
--- a/src/sksl/SkSLMetalCodeGenerator.cpp
+++ b/src/sksl/SkSLMetalCodeGenerator.cpp
@@ -1153,6 +1153,7 @@
                 fErrors.error(parentOffset,
                                 "offset of field '" + field.fName + "' must be at least " +
                                 to_string((int) currentOffset));
+                return;
             } else if (currentOffset < fieldOffset) {
                 this->write("char pad");
                 this->write(to_string(fPaddingCount++));
@@ -1166,9 +1167,15 @@
                 fErrors.error(parentOffset,
                               "offset of field '" + field.fName + "' must be a multiple of " +
                               to_string((int) alignment));
+                return;
             }
         }
-        currentOffset += memoryLayout.size(*fieldType);
+        size_t fieldSize = memoryLayout.size(*fieldType);
+        if (fieldSize > static_cast<size_t>(std::numeric_limits<int>::max() - currentOffset)) {
+            fErrors.error(parentOffset, "field offset overflow");
+            return;
+        }
+        currentOffset += fieldSize;
         std::vector<int> sizes;
         while (fieldType->typeKind() == Type::TypeKind::kArray) {
             sizes.push_back(fieldType->columns());
@@ -1876,7 +1883,7 @@
     write_stringstream(fHeader, *rawOut);
     write_stringstream(fExtraFunctions, *rawOut);
     write_stringstream(body, *rawOut);
-    return true;
+    return 0 == fErrors.errorCount();
 }
 
 }  // namespace SkSL