rmdemux: Make sure we have enough data available when parsing audio/video packets
[platform/upstream/gstreamer.git] / gst / realmedia / rmdemux.c
index 4a4eda0..68b0736 100644 (file)
@@ -527,8 +527,11 @@ gst_rmdemux_perform_seek (GstRMDemux * rmdemux, GstEvent * event)
   GST_LOG_OBJECT (rmdemux, "Took streamlock");
 
   if (event) {
-    gst_segment_do_seek (&rmdemux->segment, rate, format, flags,
-        cur_type, cur, stop_type, stop, &update);
+    if (!gst_segment_do_seek (&rmdemux->segment, rate, format, flags,
+            cur_type, cur, stop_type, stop, &update)) {
+      ret = FALSE;
+      goto done;
+    }
   }
 
   GST_DEBUG_OBJECT (rmdemux, "segment positions set to %" GST_TIME_FORMAT "-%"
@@ -967,8 +970,7 @@ need_pause:
         gst_rmdemux_send_event (rmdemux, gst_event_new_eos ());
       }
     } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) {
-      GST_ELEMENT_ERROR (rmdemux, STREAM, FAILED,
-          (NULL), ("stream stopped, reason %s", reason));
+      GST_ELEMENT_FLOW_ERROR (rmdemux, ret);
       gst_rmdemux_send_event (rmdemux, gst_event_new_eos ());
     }
     return;
@@ -2221,6 +2223,9 @@ gst_rmdemux_parse_video_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
 
   gst_buffer_map (in, &map, GST_MAP_READ);
 
+  if (map.size < offset)
+    goto not_enough_data;
+
   data = map.data + offset;
   size = map.size - offset;
 
@@ -2287,6 +2292,9 @@ gst_rmdemux_parse_video_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
     }
     GST_DEBUG_OBJECT (rmdemux, "fragment size %d", fragment_size);
 
+    if (map.size < (data - map.data) + fragment_size)
+      goto not_enough_data;
+
     /* get the fragment */
     fragment =
         gst_buffer_copy_region (in, GST_BUFFER_COPY_ALL, data - map.data,
@@ -2435,6 +2443,9 @@ gst_rmdemux_parse_audio_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
   GstFlowReturn ret;
   GstBuffer *buffer;
 
+  if (gst_buffer_get_size (in) < offset)
+    goto not_enough_data;
+
   buffer = gst_buffer_copy_region (in, GST_BUFFER_COPY_MEMORY, offset, -1);
 
   if (rmdemux->first_ts != -1 && timestamp > rmdemux->first_ts)
@@ -2465,9 +2476,19 @@ gst_rmdemux_parse_audio_packet (GstRMDemux * rmdemux, GstRMDemuxStream * stream,
     ret = gst_pad_push (stream->pad, buffer);
   }
 
+done:
   gst_buffer_unref (in);
 
   return ret;
+
+  /* ERRORS */
+not_enough_data:
+  {
+    GST_ELEMENT_WARNING (rmdemux, STREAM, DECODE, ("Skipping bad packet."),
+        (NULL));
+    ret = GST_FLOW_OK;
+    goto done;
+  }
 }
 
 static GstFlowReturn
@@ -2488,6 +2509,9 @@ gst_rmdemux_parse_packet (GstRMDemux * rmdemux, GstBuffer * in, guint16 version)
   data = map.data;
   size = map.size;
 
+  if (size < 4 + 6 + 1 + 2)
+    goto not_enough_data;
+
   /* stream number */
   id = RMDEMUX_GUINT16_GET (data);
 
@@ -2523,6 +2547,9 @@ gst_rmdemux_parse_packet (GstRMDemux * rmdemux, GstBuffer * in, guint16 version)
 
   /* version 1 has an extra byte */
   if (version == 1) {
+    if (size < 1)
+      goto not_enough_data;
+
     data += 1;
     size -= 1;
   }
@@ -2594,6 +2621,16 @@ unknown_stream:
     gst_buffer_unref (in);
     return GST_FLOW_OK;
   }
+
+  /* ERRORS */
+not_enough_data:
+  {
+    GST_ELEMENT_WARNING (rmdemux, STREAM, DECODE, ("Skipping bad packet."),
+        (NULL));
+    gst_buffer_unmap (in, &map);
+    gst_buffer_unref (in);
+    return GST_FLOW_OK;
+  }
 }
 
 gboolean