From 7d99a6cef80ec178c10dcf0e848394614c5e6912 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Fri, 12 Oct 2018 02:16:07 -0700 Subject: [PATCH] overhauled error handling in CFF interpreter minimized "if (error) return false" idiom --- src/hb-cff-interp-common.hh | 138 +++++++++++++++++++------------ src/hb-cff-interp-cs-common.hh | 43 +++++----- src/hb-cff-interp-dict-common.hh | 72 +++++++++------- src/hb-cff1-interp-cs.hh | 72 +++++++++------- src/hb-cff2-interp-cs.hh | 50 +++++------ src/hb-ot-cff1-table.hh | 91 +++++++++----------- src/hb-ot-cff2-table.hh | 71 +++++++--------- 7 files changed, 281 insertions(+), 256 deletions(-) diff --git a/src/hb-cff-interp-common.hh b/src/hb-cff-interp-common.hh index 52fc1ee43..9b7ccf06a 100644 --- a/src/hb-cff-interp-common.hh +++ b/src/hb-cff-interp-common.hh @@ -208,6 +208,8 @@ inline unsigned int OpCode_Size (OpCode op) { return Is_OpCode_ESC (op)? 2: 1; } #define OpCode_hflex1 Make_OpCode_ESC(36) /* CFF, CFF2 */ #define OpCode_flex1 Make_OpCode_ESC(37) /* CFF, CFF2 */ +#define OpCode_Invalid 65535 + struct Number { inline void init (void) @@ -406,21 +408,29 @@ struct SubByteStr { str = ByteStr (0); offset = 0; + error = false; } inline void fini (void) {} inline SubByteStr (const ByteStr &str_, unsigned int offset_ = 0) - : str (str_), offset (offset_) {} + : str (str_), offset (offset_), error (false) {} inline void reset (const ByteStr &str_, unsigned int offset_ = 0) { str = str_; offset = offset_; + error = false; } - inline const HBUINT8& operator [] (int i) const { - return str[offset + i]; + inline const HBUINT8& operator [] (int i) { + if (unlikely ((unsigned int)(offset + i) >= str.len)) + { + set_error (); + return Null(HBUINT8); + } + else + return str[offset + i]; } inline operator ByteStr (void) const { return ByteStr (str, offset, str.len - offset); } @@ -428,8 +438,14 @@ struct SubByteStr inline bool avail (unsigned int count=1) const { return str.check_limit (offset, count); } inline void inc (unsigned int count=1) { offset += count; assert (count <= str.len); } + inline void set_error (void) { error = true; } + inline bool in_error (void) const { return error; } + ByteStr str; unsigned int offset; /* beginning of the sub-string within str */ + + protected: + bool error; }; /* stack */ @@ -438,6 +454,7 @@ struct Stack { inline void init (void) { + error = false; count = 0; elements.init (); elements.resize (kSizeLimit); @@ -450,16 +467,18 @@ struct Stack elements.fini_deep (); } - inline const ELEM& operator [] (unsigned int i) const - { return elements[i]; } - inline ELEM& operator [] (unsigned int i) - { return elements[i]; } + { + if (unlikely (i >= count)) set_error (); + return elements[i]; + } inline void push (const ELEM &v) { if (likely (count < elements.len)) elements[count++] = v; + else + set_error (); } inline ELEM &push (void) @@ -467,7 +486,10 @@ struct Stack if (likely (count < elements.len)) return elements[count++]; else + { + set_error (); return Crap(ELEM); + } } inline ELEM& pop (void) @@ -475,13 +497,18 @@ struct Stack if (likely (count > 0)) return elements[--count]; else + { + set_error (); return Crap(ELEM); + } } inline void pop (unsigned int n) { if (likely (count >= n)) count -= n; + else + set_error (); } inline const ELEM& peek (void) @@ -489,19 +516,24 @@ struct Stack if (likely (count > 0)) return elements[count-1]; else + { + set_error (); return Null(ELEM); + } } inline void unpop (void) { if (likely (count < elements.len)) count++; + else + set_error (); } inline void clear (void) { count = 0; } - inline bool check_overflow (unsigned int n=1) const { return (n <= kSizeLimit) && (n + count <= kSizeLimit); } - inline bool check_underflow (unsigned int n=1) const { return (n <= count); } + inline bool in_error (void) const { return (error || elements.in_error ()); } + inline void set_error (void) { error = true; } inline unsigned int get_count (void) const { return count; } inline bool is_empty (void) const { return count == 0; } @@ -509,6 +541,7 @@ struct Stack static const unsigned int kSizeLimit = LIMIT; protected: + bool error; unsigned int count; hb_vector_t elements; }; @@ -535,44 +568,41 @@ struct ArgStack : Stack n.set_real (v); } - inline bool check_pop_num (ARG& n) + inline ARG& pop_num (void) { - if (unlikely (!this->check_underflow ())) - return false; - n = this->pop (); - return true; + return this->pop (); } - inline bool check_pop_num2 (ARG& n1, ARG& n2) + inline void pop_num2 (ARG& n1, ARG& n2) { - if (unlikely (!this->check_underflow (2))) - return false; n2 = this->pop (); n1 = this->pop (); - return true; } - inline bool check_pop_int (int& v) + inline int pop_int (void) { - if (unlikely (!this->check_underflow ())) - return false; - v = this->pop ().to_int (); - return true; + return this->pop ().to_int (); } - inline bool check_pop_uint (unsigned int& v) + inline unsigned int pop_uint (void) { - int i; - if (unlikely (!check_pop_int (i) || i < 0)) - return false; - v = (unsigned int)i; - return true; + + int i = pop_int (); + if (unlikely (i < 0)) + { + i = 0; + S::set_error (); + } + return (unsigned)i; } - inline bool check_pop_delta (hb_vector_t& vec, bool even=false) + inline void pop_delta (hb_vector_t& vec, bool even=false) { if (even && unlikely ((this->count & 1) != 0)) - return false; + { + S::set_error (); + return; + } float val = 0.0f; for (unsigned int i = 0; i < S::count; i++) { @@ -580,21 +610,17 @@ struct ArgStack : Stack ARG *n = vec.push (); n->set_real (val); } - return true; } - inline bool push_longint_from_substr (SubByteStr& substr) + inline void push_longint_from_substr (SubByteStr& substr) { - if (unlikely (!substr.avail (4) || !S::check_overflow (1))) - return false; - push_int ((int32_t)*(const HBUINT32*)&substr[0]); + push_int ((substr[0] << 24) | (substr[1] << 16) | (substr[2] << 8) | (substr[3])); substr.inc (4); - return true; } inline bool push_fixed_from_substr (SubByteStr& substr) { - if (unlikely (!substr.avail (4) || !S::check_overflow (1))) + if (unlikely (!substr.avail (4))) return false; push_fixed ((int32_t)*(const HBUINT32*)&substr[0]); substr.inc (4); @@ -649,6 +675,7 @@ struct InterpEnv { substr.reset (str_); argStack.init (); + error = false; } inline void fini (void) @@ -656,19 +683,27 @@ struct InterpEnv argStack.fini (); } - inline bool fetch_op (OpCode &op) + inline bool in_error (void) const { + return error || substr.in_error () || argStack.in_error (); + } + + inline void set_error (void) { error = true; } + + inline OpCode fetch_op (void) + { + OpCode op = OpCode_Reserved2; if (unlikely (!substr.avail ())) - return false; + return OpCode_Invalid; op = (OpCode)(unsigned char)substr[0]; if (op == OpCode_escape) { if (unlikely (!substr.avail ())) - return false; + return OpCode_Invalid; op = Make_OpCode_ESC(substr[1]); substr.inc (); } substr.inc (); - return true; + return op; } inline const ARG& eval_arg (unsigned int i) @@ -694,6 +729,8 @@ struct InterpEnv SubByteStr substr; ArgStack argStack; + protected: + bool error; }; typedef InterpEnv<> NumInterpEnv; @@ -701,47 +738,38 @@ typedef InterpEnv<> NumInterpEnv; template struct OpSet { - static inline bool process_op (OpCode op, InterpEnv& env) + static inline void process_op (OpCode op, InterpEnv& env) { switch (op) { case OpCode_shortint: - if (unlikely (!env.substr.avail (2) || !env.argStack.check_overflow (1))) - return false; - env.argStack.push_int ((int16_t)*(const HBUINT16*)&env.substr[0]); + env.argStack.push_int ((env.substr[0] << 8) | env.substr[1]); env.substr.inc (2); break; case OpCode_TwoBytePosInt0: case OpCode_TwoBytePosInt1: case OpCode_TwoBytePosInt2: case OpCode_TwoBytePosInt3: - if (unlikely (!env.substr.avail () || !env.argStack.check_overflow (1))) - return false; env.argStack.push_int ((int16_t)((op - OpCode_TwoBytePosInt0) * 256 + env.substr[0] + 108)); env.substr.inc (); break; case OpCode_TwoByteNegInt0: case OpCode_TwoByteNegInt1: case OpCode_TwoByteNegInt2: case OpCode_TwoByteNegInt3: - if (unlikely (!env.substr.avail () || !env.argStack.check_overflow (1))) - return false; env.argStack.push_int ((int16_t)(-(op - OpCode_TwoByteNegInt0) * 256 - env.substr[0] - 108)); env.substr.inc (); break; default: /* 1-byte integer */ - if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast)) && - likely (env.argStack.check_overflow (1))) + if (likely ((OpCode_OneByteIntFirst <= op) && (op <= OpCode_OneByteIntLast))) { env.argStack.push_int ((int)op - 139); } else { /* invalid unknown operator */ env.clear_args (); - return false; + env.set_error (); } break; } - - return true; } }; diff --git a/src/hb-cff-interp-cs-common.hh b/src/hb-cff-interp-cs-common.hh index c924f5186..5d85c85c0 100644 --- a/src/hb-cff-interp-cs-common.hh +++ b/src/hb-cff-interp-cs-common.hh @@ -98,12 +98,14 @@ struct CSInterpEnv : InterpEnv localSubrs.fini (); } + inline bool in_error (void) const + { + return callStack.in_error () || SUPER::in_error (); + } + inline bool popSubrNum (const BiasedSubrs& biasedSubrs, unsigned int &subr_num) { - int n; - if (unlikely ((!callStack.check_overflow (1) || - !SUPER::argStack.check_pop_int (n)))) - return false; + int n = SUPER::argStack.pop_int (); n += biasedSubrs.bias; if (unlikely ((n < 0) || ((unsigned int)n >= biasedSubrs.subrs->count))) return false; @@ -124,13 +126,11 @@ struct CSInterpEnv : InterpEnv return true; } - inline bool returnFromSubr (void) + inline void returnFromSubr (void) { - if (unlikely (!callStack.check_underflow ())) - return false; - + if (unlikely (SUPER::substr.in_error ())) + SUPER::set_error (); SUPER::substr = callStack.pop (); - return true; } inline void determine_hintmask_size (void) @@ -212,25 +212,29 @@ struct PathProcsNull template > struct CSOpSet : OpSet { - static inline bool process_op (OpCode op, ENV &env, PARAM& param) + static inline void process_op (OpCode op, ENV &env, PARAM& param) { switch (op) { case OpCode_return: - return env.returnFromSubr (); + env.returnFromSubr (); + break; case OpCode_endchar: env.set_endchar (true); OPSET::flush_args_and_op (op, env, param); break; case OpCode_fixedcs: - return env.argStack.push_fixed_from_substr (env.substr); + env.argStack.push_fixed_from_substr (env.substr); + break; case OpCode_callsubr: - return env.callSubr (env.localSubrs); - + env.callSubr (env.localSubrs); + break; + case OpCode_callgsubr: - return env.callSubr (env.globalSubrs); + env.callSubr (env.globalSubrs); + break; case OpCode_hstem: case OpCode_hstemhm: @@ -305,9 +309,9 @@ struct CSOpSet : OpSet break; default: - return SUPER::process_op (op, env); + SUPER::process_op (op, env); + break; } - return true; } static inline void process_hstem (OpCode op, ENV &env, PARAM& param) @@ -686,9 +690,8 @@ struct CSInterpreter : Interpreter SUPER::env.set_endchar (false); for (;;) { - OpCode op; - if (unlikely (!SUPER::env.fetch_op (op) || - !OPSET::process_op (op, SUPER::env, param))) + OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); + if (unlikely (SUPER::env.in_error ())) return false; if (SUPER::env.is_endchar ()) break; diff --git a/src/hb-cff-interp-dict-common.hh b/src/hb-cff-interp-dict-common.hh index d1b28a5f5..369206218 100644 --- a/src/hb-cff-interp-dict-common.hh +++ b/src/hb-cff-interp-dict-common.hh @@ -132,28 +132,26 @@ struct TopDictValues : DictValues struct DictOpSet : OpSet { - static inline bool process_op (OpCode op, InterpEnv& env) + static inline void process_op (OpCode op, InterpEnv& env) { switch (op) { case OpCode_longintdict: /* 5-byte integer */ - return env.argStack.push_longint_from_substr (env.substr); + env.argStack.push_longint_from_substr (env.substr); + break; + case OpCode_BCD: /* real number */ - float v; - if (unlikely (!env.argStack.check_overflow (1) || !parse_bcd (env.substr, v))) - return false; - env.argStack.push_real (v); - return true; + env.argStack.push_real (parse_bcd (env.substr)); + break; default: - return OpSet::process_op (op, env); + OpSet::process_op (op, env); + break; } - - return true; } - static inline bool parse_bcd (SubByteStr& substr, float& v) + static inline float parse_bcd (SubByteStr& substr) { - v = 0.0f; + float v = 0.0f; bool neg = false; double int_part = 0; @@ -171,7 +169,11 @@ struct DictOpSet : OpSet char d; if ((i & 1) == 0) { - if (!substr.avail ()) return false; + if (!substr.avail ()) + { + substr.set_error (); + return 0.0f; + } byte = substr[0]; substr.inc (); d = byte >> 4; @@ -182,7 +184,8 @@ struct DictOpSet : OpSet switch (d) { case RESERVED: - return false; + substr.set_error (); + return v; case END: value = (double)(neg? -int_part: int_part); @@ -195,16 +198,23 @@ struct DictOpSet : OpSet else value *= pow (10.0, (double)exp_part); } - v = (float)value; - return true; + return (float)value; case NEG: - if (i != 0) return false; + if (i != 0) + { + substr.set_error (); + return 0.0f; + } neg = true; break; case DECIMAL: - if (part != INT_PART) return false; + if (part != INT_PART) + { + substr.set_error (); + return v; + } part = FRAC_PART; break; @@ -213,7 +223,11 @@ struct DictOpSet : OpSet HB_FALLTHROUGH; case EXP_POS: - if (part == EXP_PART) return false; + if (part == EXP_PART) + { + substr.set_error (); + return v; + } part = EXP_PART; break; @@ -236,7 +250,7 @@ struct DictOpSet : OpSet } } - return false; + return v; } static inline bool is_hint_op (OpCode op) @@ -267,27 +281,24 @@ struct DictOpSet : OpSet template struct TopDictOpSet : DictOpSet { - static inline bool process_op (OpCode op, InterpEnv& env, TopDictValues & dictval) + static inline void process_op (OpCode op, InterpEnv& env, TopDictValues & dictval) { switch (op) { case OpCode_CharStrings: - if (unlikely (!env.argStack.check_pop_uint (dictval.charStringsOffset))) - return false; + dictval.charStringsOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FDArray: - if (unlikely (!env.argStack.check_pop_uint (dictval.FDArrayOffset))) - return false; + dictval.FDArrayOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FontMatrix: env.clear_args (); break; default: - return DictOpSet::process_op (op, env); + DictOpSet::process_op (op, env); + break; } - - return true; } }; @@ -299,9 +310,8 @@ struct DictInterpreter : Interpreter param.init (); do { - OpCode op; - if (unlikely (!SUPER::env.fetch_op (op) || - !OPSET::process_op (op, SUPER::env, param))) + OPSET::process_op (SUPER::env.fetch_op (), SUPER::env, param); + if (unlikely (SUPER::env.in_error ())) return false; } while (SUPER::env.substr.avail ()); diff --git a/src/hb-cff1-interp-cs.hh b/src/hb-cff1-interp-cs.hh index 09c51d3f6..b41811484 100644 --- a/src/hb-cff1-interp-cs.hh +++ b/src/hb-cff1-interp-cs.hh @@ -41,12 +41,17 @@ struct CFF1CSInterpEnv : CSInterpEnv SUPER::init (str, *acc.globalSubrs, *acc.privateDicts[fd].localSubrs); processed_width = false; has_width = false; + transient_array.init (); + transient_array.resize (kTransientArraySize); for (unsigned int i = 0; i < kTransientArraySize; i++) transient_array[i].set_int (0); } - bool check_transient_array_index (unsigned int i) const - { return i < kTransientArraySize; } + inline void fini (void) + { + transient_array.fini (); + SUPER::fini (); + } inline unsigned int check_width (void) { @@ -69,7 +74,7 @@ struct CFF1CSInterpEnv : CSInterpEnv Number width; static const unsigned int kTransientArraySize = 32; - Number transient_array[kTransientArraySize]; + hb_vector_t transient_array; private: typedef CSInterpEnv SUPER; @@ -78,109 +83,114 @@ struct CFF1CSInterpEnv : CSInterpEnv template > struct CFF1CSOpSet : CSOpSet { - static inline bool process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param) + static inline void process_op (OpCode op, CFF1CSInterpEnv &env, PARAM& param) { Number n1, n2; switch (op) { case OpCode_and: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push_int ((n1.to_real() != 0.0f) && (n2.to_real() != 0.0f)); break; case OpCode_or: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push_int ((n1.to_real() != 0.0f) || (n2.to_real() != 0.0f)); break; case OpCode_not: - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); env.argStack.push_int (n1.to_real() == 0.0f); break; case OpCode_abs: - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); env.argStack.push_real (fabs(n1.to_real ())); break; case OpCode_add: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push_real (n1.to_real() + n2.to_real()); break; case OpCode_sub: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push_real (n1.to_real() - n2.to_real()); break; case OpCode_div: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); if (unlikely (n2.to_real() == 0.0f)) env.argStack.push_int (0); else env.argStack.push_real (n1.to_real() / n2.to_real()); break; case OpCode_neg: - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); env.argStack.push_real (-n1.to_real ()); break; case OpCode_eq: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push_int (n1.to_real() == n2.to_real()); break; case OpCode_drop: - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); break; case OpCode_put: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2) || - !env.check_transient_array_index (n2.to_int ()))) return false; + env.argStack.pop_num2 (n1, n2); env.transient_array[n2.to_int ()] = n1; break; case OpCode_get: - if (unlikely (!env.argStack.check_pop_num (n1) || - !env.check_transient_array_index (n1.to_int ()))) return false; + n1 = env.argStack.pop_num (); env.argStack.push (env.transient_array[n1.to_int ()]); break; case OpCode_ifelse: { - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); bool test = n1.to_real () <= n2.to_real (); - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push (test? n1: n2); } break; case OpCode_random: - if (unlikely (!env.argStack.check_overflow (1))) return false; env.argStack.push_int (1); /* we can't deal with random behavior; make it constant */ break; case OpCode_mul: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push_real (n1.to_real() * n2.to_real()); break; case OpCode_sqrt: - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); env.argStack.push_real ((float)sqrt (n1.to_real ())); break; case OpCode_dup: - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); env.argStack.push (n1); env.argStack.push (n1); break; case OpCode_exch: - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); env.argStack.push (n2); env.argStack.push (n1); break; case OpCode_index: { - if (unlikely (!env.argStack.check_pop_num (n1))) return false; + n1 = env.argStack.pop_num (); int i = n1.to_int (); if (i < 0) i = 0; - if (unlikely ((unsigned int)i >= env.argStack.get_count () || !env.argStack.check_overflow (1))) return false; + if (unlikely ((unsigned int)i >= env.argStack.get_count ())) + { + env.set_error (); + return; + } env.argStack.push (env.argStack[env.argStack.get_count () - i - 1]); } break; case OpCode_roll: { - if (unlikely (!env.argStack.check_pop_num2 (n1, n2))) return false; + env.argStack.pop_num2 (n1, n2); int n = n1.to_int (); int j = n2.to_int (); - if (unlikely (n < 0 || (unsigned int)n > env.argStack.get_count ())) return false; + if (unlikely (n < 0 || (unsigned int)n > env.argStack.get_count ())) + { + env.set_error (); + return; + } if (likely (n > 0)) { if (j < 0) @@ -195,11 +205,9 @@ struct CFF1CSOpSet : CSOpSet } break; default: - if (unlikely (!SUPER::process_op (op, env, param))) - return false; + SUPER::process_op (op, env, param); break; } - return true; } static inline void flush_args (CFF1CSInterpEnv &env, PARAM& param, unsigned int start_arg = 0) diff --git a/src/hb-cff2-interp-cs.hh b/src/hb-cff2-interp-cs.hh index f05b10c84..71f2b4090 100644 --- a/src/hb-cff2-interp-cs.hh +++ b/src/hb-cff2-interp-cs.hh @@ -99,17 +99,16 @@ struct CFF2CSInterpEnv : CSInterpEnv SUPER::fini (); } - inline bool fetch_op (OpCode &op) + inline OpCode fetch_op (void) { if (this->substr.avail ()) - return SUPER::fetch_op (op); + return SUPER::fetch_op (); /* make up return or endchar op */ - if (this->callStack.check_underflow ()) - op = OpCode_return; + if (this->callStack.is_empty ()) + return OpCode_endchar; else - op = OpCode_endchar; - return true; + return OpCode_return; } inline const BlendArg& eval_arg (unsigned int i) @@ -140,14 +139,11 @@ struct CFF2CSInterpEnv : CSInterpEnv inline void process_vsindex (void) { - unsigned int index; - if (likely (argStack.check_pop_uint (index))) + unsigned int index = argStack.pop_uint (); + if (do_blend) { - if (do_blend) - { - if (likely (!seen_vsindex && !seen_blend)) - set_ivs (index); - } + if (likely (!seen_vsindex && !seen_blend)) + set_ivs (index); } seen_vsindex = true; } @@ -192,40 +188,45 @@ struct CFF2CSInterpEnv : CSInterpEnv template > struct CFF2CSOpSet : CSOpSet { - static inline bool process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param) + static inline void process_op (OpCode op, CFF2CSInterpEnv &env, PARAM& param) { switch (op) { case OpCode_callsubr: case OpCode_callgsubr: /* a subroutine number shoudln't be a blended value */ if (unlikely (env.argStack.peek ().blending ())) - return false; - return SUPER::process_op (op, env, param); + { + env.set_error (); + break; + } + SUPER::process_op (op, env, param); + break; case OpCode_blendcs: - return OPSET::process_blend (env, param); + OPSET::process_blend (env, param); + break; case OpCode_vsindexcs: if (unlikely (env.argStack.peek ().blending ())) - return false; + { + env.set_error (); + break; + } OPSET::process_vsindex (env, param); break; default: - return SUPER::process_op (op, env, param); + SUPER::process_op (op, env, param); } - return true; } - static inline bool process_blend (CFF2CSInterpEnv &env, PARAM& param) + static inline void process_blend (CFF2CSInterpEnv &env, PARAM& param) { unsigned int n, k; env.process_blend (); k = env.get_region_count (); - if (unlikely (!env.argStack.check_pop_uint (n) || - (k+1) * n > env.argStack.get_count ())) - return false; + n = env.argStack.pop_uint (); /* copy the blend values into blend array of the default values */ unsigned int start = env.argStack.get_count () - ((k+1) * n); for (unsigned int i = 0; i < n; i++) @@ -233,7 +234,6 @@ struct CFF2CSOpSet : CSOpSet /* pop off blend values leaving default values now adorned with blend values */ env.argStack.pop (k * n); - return true; } static inline void process_vsindex (CFF2CSInterpEnv &env, PARAM& param) diff --git a/src/hb-ot-cff1-table.hh b/src/hb-ot-cff1-table.hh index 67836d7ba..71e695337 100644 --- a/src/hb-ot-cff1-table.hh +++ b/src/hb-ot-cff1-table.hh @@ -531,7 +531,7 @@ struct CFF1StringIndex : CFF1Index TRACE_SERIALIZE (this); if (unlikely ((strings.count == 0) || (sidmap.get_count () == 0))) { - if (!unlikely (c->extend_min (*this))) + if (!unlikely (c->extend_min (this->count))) return_trace (false); count.set (0); return_trace (true); @@ -678,7 +678,7 @@ struct CFF1TopDictValues : TopDictValues struct CFF1TopDictOpSet : TopDictOpSet { - static inline bool process_op (OpCode op, CFF1TopDictInterpEnv& env, CFF1TopDictValues& dictval) + static inline void process_op (OpCode op, CFF1TopDictInterpEnv& env, CFF1TopDictValues& dictval) { CFF1TopDictVal val; val.last_arg_offset = (env.last_offset-1) - dictval.opStart; /* offset to the last argument */ @@ -692,8 +692,7 @@ struct CFF1TopDictOpSet : TopDictOpSet case OpCode_Weight: case OpCode_PostScript: case OpCode_BaseFontName: - if (unlikely (!env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::name_op_to_index (op)]))) - return false; + dictval.nameSIDs[NameDictValues::name_op_to_index (op)] = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_isFixedPitch: @@ -716,56 +715,49 @@ struct CFF1TopDictOpSet : TopDictOpSet break; case OpCode_CIDCount: - if (unlikely (!env.argStack.check_pop_uint (dictval.cidCount))) - return false; + dictval.cidCount = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_ROS: - if (unlikely (!env.argStack.check_pop_uint (dictval.ros_supplement) || - !env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::ordering]) || - !env.argStack.check_pop_uint (dictval.nameSIDs[NameDictValues::registry]))) - return false; + dictval.ros_supplement = env.argStack.pop_uint (); + dictval.nameSIDs[NameDictValues::ordering] = env.argStack.pop_uint (); + dictval.nameSIDs[NameDictValues::registry] = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_Encoding: - if (unlikely (!env.argStack.check_pop_uint (dictval.EncodingOffset))) - return false; + dictval.EncodingOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_charset: - if (unlikely (!env.argStack.check_pop_uint (dictval.CharsetOffset))) - return false; + dictval.CharsetOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FDSelect: - if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset))) - return false; + dictval.FDSelectOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_Private: - if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset))) - return false; - if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size))) - return false; + dictval.privateDictInfo.offset = env.argStack.pop_uint (); + dictval.privateDictInfo.size = env.argStack.pop_uint (); env.clear_args (); break; default: env.last_offset = env.substr.offset; - if (unlikely (!TopDictOpSet::process_op (op, env, dictval))) - return false; + TopDictOpSet::process_op (op, env, dictval); /* Record this operand below if stack is empty, otherwise done */ - if (!env.argStack.is_empty ()) return true; + if (!env.argStack.is_empty ()) return; break; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr, val); - return true; } }; @@ -789,12 +781,11 @@ struct CFF1FontDictValues : DictValues struct CFF1FontDictOpSet : DictOpSet { - static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1FontDictValues& dictval) + static inline void process_op (OpCode op, NumInterpEnv& env, CFF1FontDictValues& dictval) { switch (op) { case OpCode_FontName: - if (unlikely (!env.argStack.check_pop_uint (dictval.fontName))) - return false; + dictval.fontName = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FontMatrix: @@ -802,22 +793,20 @@ struct CFF1FontDictOpSet : DictOpSet env.clear_args (); break; case OpCode_Private: - if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset))) - return false; - if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size))) - return false; + dictval.privateDictInfo.offset = env.argStack.pop_uint (); + dictval.privateDictInfo.size = env.argStack.pop_uint (); env.clear_args (); break; default: - if (unlikely (!DictOpSet::process_op (op, env))) - return false; - if (!env.argStack.is_empty ()) return true; + DictOpSet::process_op (op, env); + if (!env.argStack.is_empty ()) return; break; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr); - return true; } }; @@ -856,7 +845,7 @@ typedef CFF1PrivateDictValues_Base CFF1PrivateDictValues; struct CFF1PrivateDictOpSet : DictOpSet { - static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues& dictval) + static inline void process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues& dictval) { NumDictVal val; val.init (); @@ -868,8 +857,7 @@ struct CFF1PrivateDictOpSet : DictOpSet case OpCode_FamilyOtherBlues: case OpCode_StemSnapH: case OpCode_StemSnapV: - if (unlikely (!env.argStack.check_pop_delta (val.multi_val))) - return false; + env.argStack.pop_delta (val.multi_val); break; case OpCode_StdHW: case OpCode_StdVW: @@ -882,31 +870,29 @@ struct CFF1PrivateDictOpSet : DictOpSet case OpCode_initialRandomSeed: case OpCode_defaultWidthX: case OpCode_nominalWidthX: - if (unlikely (!env.argStack.check_pop_num (val.single_val))) - return false; + val.single_val = env.argStack.pop_num (); env.clear_args (); break; case OpCode_Subrs: - if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) - return false; + dictval.subrsOffset = env.argStack.pop_uint (); env.clear_args (); break; default: - if (unlikely (!DictOpSet::process_op (op, env))) - return false; - if (!env.argStack.is_empty ()) return true; + DictOpSet::process_op (op, env); + if (!env.argStack.is_empty ()) return; break; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr, val); - return true; } }; struct CFF1PrivateDictOpSet_Subset : DictOpSet { - static inline bool process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues_Subset& dictval) + static inline void process_op (OpCode op, NumInterpEnv& env, CFF1PrivateDictValues_Subset& dictval) { switch (op) { case OpCode_BlueValues: @@ -930,20 +916,19 @@ struct CFF1PrivateDictOpSet_Subset : DictOpSet break; case OpCode_Subrs: - if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) - return false; + dictval.subrsOffset = env.argStack.pop_uint (); env.clear_args (); break; default: - if (unlikely (!DictOpSet::process_op (op, env))) - return false; - if (!env.argStack.is_empty ()) return true; + DictOpSet::process_op (op, env); + if (!env.argStack.is_empty ()) return; break; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr); - return true; } }; diff --git a/src/hb-ot-cff2-table.hh b/src/hb-ot-cff2-table.hh index 2e0579329..dd79b420d 100644 --- a/src/hb-ot-cff2-table.hh +++ b/src/hb-ot-cff2-table.hh @@ -176,7 +176,7 @@ struct CFF2TopDictValues : TopDictValues<> struct CFF2TopDictOpSet : TopDictOpSet<> { - static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2TopDictValues& dictval) + static inline void process_op (OpCode op, NumInterpEnv& env, CFF2TopDictValues& dictval) { switch (op) { case OpCode_FontMatrix: @@ -189,25 +189,23 @@ struct CFF2TopDictOpSet : TopDictOpSet<> break; case OpCode_vstore: - if (unlikely (!env.argStack.check_pop_uint (dictval.vstoreOffset))) - return false; + dictval.vstoreOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_FDSelect: - if (unlikely (!env.argStack.check_pop_uint (dictval.FDSelectOffset))) - return false; + dictval.FDSelectOffset = env.argStack.pop_uint (); env.clear_args (); break; default: - if (unlikely (!SUPER::process_op (op, env, dictval))) - return false; + SUPER::process_op (op, env, dictval); /* Record this operand below if stack is empty, otherwise done */ - if (!env.argStack.is_empty ()) return true; + if (!env.argStack.is_empty ()) return; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr); - return true; } typedef TopDictOpSet<> SUPER; @@ -231,26 +229,24 @@ struct CFF2FontDictValues : DictValues struct CFF2FontDictOpSet : DictOpSet { - static inline bool process_op (OpCode op, NumInterpEnv& env, CFF2FontDictValues& dictval) + static inline void process_op (OpCode op, NumInterpEnv& env, CFF2FontDictValues& dictval) { switch (op) { case OpCode_Private: - if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.offset))) - return false; - if (unlikely (!env.argStack.check_pop_uint (dictval.privateDictInfo.size))) - return false; + dictval.privateDictInfo.offset = env.argStack.pop_uint (); + dictval.privateDictInfo.size = env.argStack.pop_uint (); env.clear_args (); break; default: - if (unlikely (!SUPER::process_op (op, env))) - return false; + SUPER::process_op (op, env); if (!env.argStack.is_empty ()) - return true; + return; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr); - return true; } private: @@ -303,10 +299,9 @@ struct CFF2PrivDictInterpEnv : NumInterpEnv inline void process_vsindex (void) { - unsigned int index; - if (likely (!seen_vsindex && argStack.check_pop_uint (index))) + if (likely (!seen_vsindex)) { - set_ivs (argStack.check_pop_uint (index)); + set_ivs (argStack.pop_uint ()); } seen_vsindex = true; } @@ -321,7 +316,7 @@ struct CFF2PrivDictInterpEnv : NumInterpEnv struct CFF2PrivateDictOpSet : DictOpSet { - static inline bool process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues& dictval) + static inline void process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues& dictval) { NumDictVal val; val.init (); @@ -334,8 +329,7 @@ struct CFF2PrivateDictOpSet : DictOpSet case OpCode_BlueFuzz: case OpCode_ExpansionFactor: case OpCode_LanguageGroup: - if (unlikely (!env.argStack.check_pop_num (val.single_val))) - return false; + val.single_val = env.argStack.pop_num (); env.clear_args (); break; case OpCode_BlueValues: @@ -344,13 +338,11 @@ struct CFF2PrivateDictOpSet : DictOpSet case OpCode_FamilyOtherBlues: case OpCode_StemSnapH: case OpCode_StemSnapV: - if (unlikely (!env.argStack.check_pop_delta (val.multi_val))) - return false; + env.argStack.pop_delta (val.multi_val); env.clear_args (); break; case OpCode_Subrs: - if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) - return false; + dictval.subrsOffset = env.argStack.pop_uint (); env.clear_args (); break; case OpCode_vsindexdict: @@ -361,20 +353,20 @@ struct CFF2PrivateDictOpSet : DictOpSet break; default: - if (unlikely (!DictOpSet::process_op (op, env))) - return false; - if (!env.argStack.is_empty ()) return true; + DictOpSet::process_op (op, env); + if (!env.argStack.is_empty ()) return; break; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr, val); - return true; } }; struct CFF2PrivateDictOpSet_Subset : DictOpSet { - static inline bool process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues_Subset& dictval) + static inline void process_op (OpCode op, CFF2PrivDictInterpEnv& env, CFF2PrivateDictValues_Subset& dictval) { switch (op) { case OpCode_BlueValues: @@ -395,23 +387,22 @@ struct CFF2PrivateDictOpSet_Subset : DictOpSet case OpCode_blenddict: env.clear_args (); - return true; + return; case OpCode_Subrs: - if (unlikely (!env.argStack.check_pop_uint (dictval.subrsOffset))) - return false; + dictval.subrsOffset = env.argStack.pop_uint (); env.clear_args (); break; default: - if (unlikely (!SUPER::process_op (op, env))) - return false; - if (!env.argStack.is_empty ()) return true; + SUPER::process_op (op, env); + if (!env.argStack.is_empty ()) return; break; } + if (unlikely (env.in_error ())) return; + dictval.addOp (op, env.substr); - return true; } private: