From 4d3b8d1129d8b863e4156cd0334e93257b9d0cc4 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 22 Apr 2021 08:57:23 +0200 Subject: [PATCH] rtpjitterbuffer: Avoid generation of invalid timestamps When updating timestamps and timer timeouts with a new offset, make sure that the resulting value is valid (and not a negative (signed) value which ends up in a massive (unsigned) value). Fixes #571 Part-of: --- gst/rtpmanager/gstrtpjitterbuffer.c | 35 ++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/gst/rtpmanager/gstrtpjitterbuffer.c b/gst/rtpmanager/gstrtpjitterbuffer.c index 6f7185c2d9..b360831a5f 100644 --- a/gst/rtpmanager/gstrtpjitterbuffer.c +++ b/gst/rtpmanager/gstrtpjitterbuffer.c @@ -2072,6 +2072,27 @@ get_pts_timeout (const RtpTimer * timer) return timer->timeout - timer->offset; } +static inline gboolean +safe_add (guint64 * res, guint64 val, gint64 offset) +{ + if (val <= G_MAXINT64) { + gint64 tmp = (gint64) val + offset; + if (tmp >= 0) { + *res = tmp; + return TRUE; + } + return FALSE; + } + /* From here, val > G_MAXINT64 */ + + /* Negative value */ + if (offset < 0 && val < -offset) + return FALSE; + + *res = val + offset; + return TRUE; +} + static void update_timer_offsets (GstRtpJitterBuffer * jitterbuffer) { @@ -2081,8 +2102,15 @@ update_timer_offsets (GstRtpJitterBuffer * jitterbuffer) while (test) { if (test->type != RTP_TIMER_EXPECTED) { - test->timeout = get_pts_timeout (test) + new_offset; - test->offset = new_offset; + GstClockTime pts = get_pts_timeout (test); + if (safe_add (&test->timeout, pts, new_offset)) { + test->offset = new_offset; + } else { + GST_DEBUG_OBJECT (jitterbuffer, + "Invalidating timeout (pts lower than new offset)"); + test->timeout = GST_CLOCK_TIME_NONE; + test->offset = 0; + } /* as we apply the offset on all timers, the order of timers won't * change and we can skip updating the timer queue */ } @@ -2130,7 +2158,8 @@ apply_offset (GstRtpJitterBuffer * jitterbuffer, GstClockTime timestamp) return -1; /* apply the timestamp offset, this is used for inter stream sync */ - timestamp += priv->ts_offset; + if (!safe_add (×tamp, timestamp, priv->ts_offset)) + timestamp = 0; /* add the offset, this is used when buffering */ timestamp += priv->out_offset;