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