diff options
author | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-10 02:07:42 +0300 |
---|---|---|
committer | Oleg Oshmyan <chortos@inbox.lv> | 2020-10-18 05:01:31 +0300 |
commit | 84928b1fb100004686ac61851720da9247cad34b (patch) | |
tree | 63367c9806ddf1d783b673498c77e9a720aa70aa /libass | |
parent | 7347bb0e6d77521451707a249e04fe8c0edae267 (diff) | |
download | libass-84928b1fb100004686ac61851720da9247cad34b.tar.bz2 libass-84928b1fb100004686ac61851720da9247cad34b.tar.xz |
Factor out & improve UB-less double -> int32_t conversion
The value may be bigger than INT32_MAX as long as its *integral part* isn't.
Furthermore, make sure to avoid UB on odd platforms where int32_t limits
aren't exactly representable in double, as this isn't too hard. Do assume
that they're representable at all though. We won't necessarily match
x86 values on such platforms, but we will avoid the undefined behavior.
Diffstat (limited to 'libass')
-rw-r--r-- | libass/ass_parse.c | 19 |
1 files changed, 12 insertions, 7 deletions
diff --git a/libass/ass_parse.c b/libass/ass_parse.c index 935dbb0..b40cc33 100644 --- a/libass/ass_parse.c +++ b/libass/ass_parse.c @@ -128,6 +128,17 @@ void update_font(ASS_Renderer *render_priv) render_priv->state.font = ass_font_new(render_priv, &desc); } +/** + * \brief Convert double to int32_t without UB + * on out-of-range values; match x86 behavior + */ +static inline int32_t dtoi32(double val) +{ + if (isnan(val) || val <= INT32_MIN || val >= INT32_MAX + 1LL) + return INT32_MIN; + return val; +} + static double calc_anim(double new, double old, double pwr) { return (1 - pwr) * old + new * pwr; @@ -135,13 +146,7 @@ static double calc_anim(double new, double old, double pwr) static int32_t calc_anim_int32(uint32_t new, uint32_t old, double pwr) { - double ret = calc_anim(new, old, pwr); - - // Avoid UB on out-of-range values; match x86 behavior - if (isnan(ret) || ret < INT32_MIN || ret > INT32_MAX) - return INT32_MIN; - - return ret; + return dtoi32(calc_anim(new, old, pwr)); } /** |