identity: Fix crash when receiving a gap event outside the current segment
authorVivia Nikolaidou <vivia@ahiru.eu>
Fri, 29 Oct 2021 10:27:37 +0000 (13:27 +0300)
committerVivia Nikolaidou <vivia@ahiru.eu>
Fri, 29 Oct 2021 11:08:49 +0000 (14:08 +0300)
We were checking if the start time of the gap event was
GST_CLOCK_TIME_NONE, which is superfluous because that cannot happen,
and then not checking if it was NONE after gst_segment_to_running_time,
which caused a crash if an identity received a gap event fully or
partially outside the current segment.

This patch was done in cooperation with:
Jan Alexander Steffens (heftig) <jan.steffens@ltnglobal.com>

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/1269>

subprojects/gstreamer/plugins/elements/gstidentity.c

index 25bdae9..482147d 100644 (file)
@@ -480,19 +480,34 @@ gst_identity_sink_event (GstBaseTransform * trans, GstEvent * event)
 
   if (GST_EVENT_TYPE (event) == GST_EVENT_GAP &&
       trans->have_segment && trans->segment.format == GST_FORMAT_TIME) {
-    GstClockTime start, dur;
+    GstClockTime start, dur, old_start;
 
-    gst_event_parse_gap (event, &start, &dur);
-    if (GST_CLOCK_TIME_IS_VALID (start)) {
-      start = gst_segment_to_running_time (&trans->segment,
-          GST_FORMAT_TIME, start);
+    gst_event_parse_gap (event, &old_start, &dur);
 
-      gst_identity_do_sync (identity, start);
+    start = gst_segment_to_running_time (&trans->segment,
+        GST_FORMAT_TIME, old_start);
 
-      /* also transform GAP timestamp similar to buffer timestamps */
-      if (identity->single_segment) {
+    gst_identity_do_sync (identity,
+        GST_CLOCK_TIME_IS_VALID (start) ? start : 0);
+
+    /* also transform GAP timestamp similar to buffer timestamps */
+    if (identity->single_segment) {
+      guint64 clip_start, clip_stop;
+      if (GST_CLOCK_TIME_IS_VALID (start)) {
         gst_event_unref (event);
         event = gst_event_new_gap (start, dur);
+      } else if (GST_CLOCK_TIME_IS_VALID (dur) &&
+          gst_segment_clip (&trans->segment, GST_FORMAT_TIME, old_start,
+              old_start + dur, &clip_start, &clip_stop)) {
+        gst_event_unref (event);
+        event = gst_event_new_gap (clip_start, clip_stop - clip_start);
+      } else {
+        /* Gap event is completely outside the segment, drop it */
+        GST_DEBUG_OBJECT (identity,
+            "Dropping GAP event outside segment: %" GST_PTR_FORMAT, event);
+        gst_event_unref (event);
+        ret = TRUE;
+        goto done;
       }
     }
   }