Source code

Revision control

Copy as Markdown

Other Tools

diff --git a/src/cff_charstring.cc b/src/cff_charstring.cc
--- a/src/cff_charstring.cc
+++ b/src/cff_charstring.cc
@@ -25,6 +25,11 @@ const size_t kMaxCharStringLength = 6553
const size_t kMaxNumberOfStemHints = 96;
const size_t kMaxSubrNesting = 10;
+// We reject the table if any charstring results in executing too many ops.
+// This should be more than enough for any realistic use case; only a malicious
+// font would run millions of ops for a single glyph.
+const uint32_t kMaxCharStringOps = 1024 * 1024 * 64;
+
// |dummy_result| should be a huge positive integer so callsubr and callgsubr
// will fail with the dummy value.
const int32_t dummy_result = INT_MAX;
@@ -889,6 +894,11 @@ bool ExecuteCharString(ots::OpenTypeCFF&
continue;
}
+ if (++cs_ctx.num_ops > kMaxCharStringOps) {
+ ots::Font* font = cff.GetFont();
+ return OTS_FAILURE_MSG("charstring executes too many ops");
+ }
+
// An operator is found. Execute it.
if (!ExecuteCharStringOperator(cff,
operator_or_operand,
diff --git a/src/cff_charstring.h b/src/cff_charstring.h
--- a/src/cff_charstring.h
+++ b/src/cff_charstring.h
@@ -105,14 +105,15 @@ enum HintState {
};
struct CharStringContext {
+ size_t num_stems = 0;
+ int32_t vsindex = 0;
+ uint32_t num_ops = 0;
bool endchar_seen = false;
bool width_seen = false;
- size_t num_stems = 0;
HintState hint_state = kHs;
bool cff2 = false;
bool blend_seen = false;
bool vsindex_seen = false;
- int32_t vsindex = 0;
};
} // namespace ots