summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOleg Oshmyan <chortos@inbox.lv>2020-10-10 02:07:42 +0300
committerOleg Oshmyan <chortos@inbox.lv>2020-10-18 05:01:31 +0300
commit84928b1fb100004686ac61851720da9247cad34b (patch)
tree63367c9806ddf1d783b673498c77e9a720aa70aa
parent7347bb0e6d77521451707a249e04fe8c0edae267 (diff)
downloadlibass-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.
-rw-r--r--libass/ass_parse.c19
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));
}
/**