overhauled error handling in CFF interpreter

minimized "if (error) return false" idiom
This commit is contained in:
Michiharu Ariza 2018-10-12 02:16:07 -07:00
parent ca37172ee3
commit 7d99a6cef8
7 changed files with 281 additions and 256 deletions

View File

@ -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<ELEM, kSizeLimit> elements;
};
@ -535,44 +568,41 @@ struct ArgStack : Stack<ARG, 513>
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<ARG>& vec, bool even=false)
inline void pop_delta (hb_vector_t<ARG>& 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, 513>
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<ARG> argStack;
protected:
bool error;
};
typedef InterpEnv<> NumInterpEnv;
@ -701,47 +738,38 @@ typedef InterpEnv<> NumInterpEnv;
template <typename ARG=Number>
struct OpSet
{
static inline bool process_op (OpCode op, InterpEnv<ARG>& env)
static inline void process_op (OpCode op, InterpEnv<ARG>& 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;
}
};

View File

@ -98,12 +98,14 @@ struct CSInterpEnv : InterpEnv<ARG>
localSubrs.fini ();
}
inline bool in_error (void) const
{
return callStack.in_error () || SUPER::in_error ();
}
inline bool popSubrNum (const BiasedSubrs<SUBRS>& 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<ARG>
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 <typename ARG, typename OPSET, typename ENV, typename PARAM, typename PATH=PathProcsNull<ENV, PARAM> >
struct CSOpSet : OpSet<ARG>
{
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<ARG>
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<ENV>
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;

View File

@ -132,28 +132,26 @@ struct TopDictValues : DictValues<OPSTR>
struct DictOpSet : OpSet<Number>
{
static inline bool process_op (OpCode op, InterpEnv<Number>& env)
static inline void process_op (OpCode op, InterpEnv<Number>& 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<Number>::process_op (op, env);
OpSet<Number>::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<Number>
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<Number>
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<Number>
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<Number>
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<Number>
}
}
return false;
return v;
}
static inline bool is_hint_op (OpCode op)
@ -267,27 +281,24 @@ struct DictOpSet : OpSet<Number>
template <typename VAL=OpStr>
struct TopDictOpSet : DictOpSet
{
static inline bool process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & dictval)
static inline void process_op (OpCode op, InterpEnv<Number>& env, TopDictValues<VAL> & 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<ENV>
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 ());

View File

@ -41,12 +41,17 @@ struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
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, CFF1Subrs>
Number width;
static const unsigned int kTransientArraySize = 32;
Number transient_array[kTransientArraySize];
hb_vector_t<Number, kTransientArraySize> transient_array;
private:
typedef CSInterpEnv<Number, CFF1Subrs> SUPER;
@ -78,109 +83,114 @@ struct CFF1CSInterpEnv : CSInterpEnv<Number, CFF1Subrs>
template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF1CSInterpEnv, PARAM> >
struct CFF1CSOpSet : CSOpSet<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
{
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<Number, OPSET, CFF1CSInterpEnv, PARAM, PATH>
}
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)

View File

@ -99,17 +99,16 @@ struct CFF2CSInterpEnv : CSInterpEnv<BlendArg, CFF2Subrs>
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<BlendArg, CFF2Subrs>
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<BlendArg, CFF2Subrs>
template <typename OPSET, typename PARAM, typename PATH=PathProcsNull<CFF2CSInterpEnv, PARAM> >
struct CFF2CSOpSet : CSOpSet<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
{
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<BlendArg, OPSET, CFF2CSInterpEnv, PARAM, PATH>
/* 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)

View File

@ -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<CFF1TopDictVal>
struct CFF1TopDictOpSet : TopDictOpSet<CFF1TopDictVal>
{
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<CFF1TopDictVal>
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<CFF1TopDictVal>
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<CFF1TopDictVal>::process_op (op, env, dictval)))
return false;
TopDictOpSet<CFF1TopDictVal>::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<OpStr>
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<NumDictVal> 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;
}
};

View File

@ -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<OpStr>
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: