flvdec: Check the avio_seek return value after reading a metadata packet

Message ID 20170903101754.8340-1-martin@martin.st
State Committed
Commit 585dc1aecef0371ad6f16cb3750ae2a6da9cf00a
Headers show

Commit Message

Martin Storsjö Sept. 3, 2017, 10:17 a.m.
If the metadata packet is corrupted, flv_read_metabody can accidentally
read past the start of the next packet. If the start of the next packet
had been flushed out of the IO buffer, we would be unable to seek to
the right position (on a nonseekable stream).

Prefer to clearly error out instead of silently trying to read from a
desynced stream which will only be interpreted as garbage.
---
 libavformat/flvdec.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

Comments

Luca Barbato Sept. 3, 2017, 2:25 p.m. | #1
On 03/09/2017 12:17, Martin Storsjö wrote:
> If the metadata packet is corrupted, flv_read_metabody can accidentally
> read past the start of the next packet. If the start of the next packet
> had been flushed out of the IO buffer, we would be unable to seek to
> the right position (on a nonseekable stream).
> 
> Prefer to clearly error out instead of silently trying to read from a
> desynced stream which will only be interpreted as garbage.
> ---
>   libavformat/flvdec.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
> index 1b29740f41..81a71d39f4 100644
> --- a/libavformat/flvdec.c
> +++ b/libavformat/flvdec.c
> @@ -801,7 +801,13 @@ static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
>                              type, size, flags);
>   
>   skip:
> -            avio_seek(s->pb, next, SEEK_SET);
> +            if (avio_seek(s->pb, next, SEEK_SET) != next) {
> +                // This can happen if flv_read_metabody above read past
> +                // next, on a non-seekable input, and the preceding data has
> +                // been flushed out from the IO buffer.
> +                av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n");
> +                return AVERROR_INVALIDDATA;
> +            }
>               continue;
>           }
>   
> 

Ok.

Patch

diff --git a/libavformat/flvdec.c b/libavformat/flvdec.c
index 1b29740f41..81a71d39f4 100644
--- a/libavformat/flvdec.c
+++ b/libavformat/flvdec.c
@@ -801,7 +801,13 @@  static int flv_read_packet(AVFormatContext *s, AVPacket *pkt)
                            type, size, flags);
 
 skip:
-            avio_seek(s->pb, next, SEEK_SET);
+            if (avio_seek(s->pb, next, SEEK_SET) != next) {
+                // This can happen if flv_read_metabody above read past
+                // next, on a non-seekable input, and the preceding data has
+                // been flushed out from the IO buffer.
+                av_log(s, AV_LOG_ERROR, "Unable to seek to the next packet\n");
+                return AVERROR_INVALIDDATA;
+            }
             continue;
         }