rtpjitterbuffer: Avoid generation of invalid timestamps
authorEdward Hervey <edward@centricular.com>
Thu, 22 Apr 2021 06:57:23 +0000 (08:57 +0200)
committerEdward Hervey <bilboed@bilboed.com>
Thu, 22 Apr 2021 13:23:13 +0000 (15:23 +0200)
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: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-good/-/merge_requests/960>

gst/rtpmanager/gstrtpjitterbuffer.c

index 6f7185c..b360831 100644 (file)
@@ -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 (&timestamp, timestamp, priv->ts_offset))
+    timestamp = 0;
   /* add the offset, this is used when buffering */
   timestamp += priv->out_offset;