From 5a7c371e4c6f1775ebbfe120fafe92afe402a954 Mon Sep 17 00:00:00 2001 From: Michiharu Ariza Date: Tue, 4 Dec 2018 22:24:38 -0800 Subject: [PATCH] check overflow & clamp --- src/hb-cff-interp-dict-common.hh | 36 ++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/hb-cff-interp-dict-common.hh b/src/hb-cff-interp-dict-common.hh index 2822af40c..62c87e94a 100644 --- a/src/hb-cff-interp-dict-common.hh +++ b/src/hb-cff-interp-dict-common.hh @@ -105,16 +105,17 @@ struct DictOpSet : OpSet static inline double parse_bcd (SubByteStr& substr) { - double v = 0.0; - bool neg = false; double int_part = 0; long frac_part = 0; unsigned int frac_count = 0; bool exp_neg = false; unsigned int exp_part = 0; + bool exp_overflow = false; enum Part { INT_PART=0, FRAC_PART, EXP_PART } part = INT_PART; enum Nibble { DECIMAL=10, EXP_POS, EXP_NEG, RESERVED, NEG, END }; + const unsigned long MAX_FRACT = 0xFFFFFFFFFFFFFlu; /* 1^52-1 */ + const unsigned int MAX_EXP = 0x7FFu; /* 1^11-1 */ double value = 0.0; unsigned char byte = 0; @@ -139,12 +140,21 @@ struct DictOpSet : OpSet { case RESERVED: substr.set_error (); - return v; + return value; case END: value = (double)(neg? -int_part: int_part); if (frac_count > 0) value += (frac_part / pow (10.0, (double)frac_count)); + if (unlikely (exp_overflow)) + { + if (value == 0.0) + return value; + if (exp_neg) + return neg? -DBL_MIN: DBL_MIN; + else + return neg? -DBL_MAX: DBL_MAX; + } if (exp_part != 0) { if (exp_neg) @@ -167,7 +177,7 @@ struct DictOpSet : OpSet if (part != INT_PART) { substr.set_error (); - return v; + return value; } part = FRAC_PART; break; @@ -180,7 +190,7 @@ struct DictOpSet : OpSet if (part == EXP_PART) { substr.set_error (); - return v; + return value; } part = EXP_PART; break; @@ -193,18 +203,26 @@ struct DictOpSet : OpSet break; case FRAC_PART: - frac_part = (frac_part * 10) + d; - frac_count++; + if (likely ((fract_count <= MAX_FRACT / 10))) + { + frac_part = (frac_part * 10) + d; + frac_count++; + } break; case EXP_PART: - exp_part = (exp_part * 10) + d; + if (likely (exp_part * 10) + d <= MAX_EXP) + { + exp_part = (exp_part * 10) + d; + } + else + exp_overflow = true; break; } } } - return v; + return value; } static inline bool is_hint_op (OpCode op)