diff mbox

[FFmpeg-devel,13/13] avformat/matroskadec: Improve error/EOF checks III

Message ID 20190623234231.6348-3-andreas.rheinhardt@gmail.com
State Accepted
Commit ff5ea59f7b05cb4d37ba9e2c3ee383ff24a10ae0
Headers show

Commit Message

Andreas Rheinhardt June 23, 2019, 11:42 p.m. UTC
Up until now, when an element was skipped, it was relied upon
ffio_limit to make sure that there is enough data available to skip.
ffio_limit itself relies upon the availability of the file's size. As
this needn't be available, the check has been refined: First one byte
less than intended is skipped, then another byte is read, followed by a
check of the error flags.

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
---
 libavformat/matroskadec.c | 24 +++++++++++++++++-------
 1 file changed, 17 insertions(+), 7 deletions(-)

Comments

James Almer June 25, 2019, 1:33 a.m. UTC | #1
On 6/23/2019 8:42 PM, Andreas Rheinhardt wrote:
> Up until now, when an element was skipped, it was relied upon
> ffio_limit to make sure that there is enough data available to skip.
> ffio_limit itself relies upon the availability of the file's size. As
> this needn't be available, the check has been refined: First one byte
> less than intended is skipped, then another byte is read, followed by a
> check of the error flags.
> 
> Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com>
> ---
>  libavformat/matroskadec.c | 24 +++++++++++++++++-------
>  1 file changed, 17 insertions(+), 7 deletions(-)
> 
> diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
> index 1db7471440..caabfcf6ac 100644
> --- a/libavformat/matroskadec.c
> +++ b/libavformat/matroskadec.c
> @@ -1256,13 +1256,23 @@ static int ebml_parse_elem(MatroskaDemuxContext *matroska,
>      case EBML_STOP:
>          return 1;
>      default:
> -        if (ffio_limit(pb, length) != length) {
> -            // ffio_limit emits its own error message,
> -            // so we don't have to.
> -            return AVERROR(EIO);
> -        }
> -        res = avio_skip(pb, length);
> -        res = res < 0 ? res : 0;
> +        if (length) {
> +            if (ffio_limit(pb, length) != length) {
> +                // ffio_limit emits its own error message,
> +                // so we don't have to.
> +                return AVERROR(EIO);
> +            }
> +            if ((res = avio_skip(pb, length - 1)) >= 0) {
> +                // avio_skip might take us past EOF. We check for this
> +                // by skipping only length - 1 bytes, reading a byte and
> +                // checking the error flags. This is done in order to check
> +                // that the element has been properly skipped even when
> +                // no filesize (that ffio_limit relies on) is available.
> +                avio_r8(pb);
> +                res = NEEDS_CHECKING;
> +            }
> +        } else
> +            res = 0;
>      }
>      if (res) {
>          if (res == NEEDS_CHECKING) {

Applied, thanks.
diff mbox

Patch

diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c
index 1db7471440..caabfcf6ac 100644
--- a/libavformat/matroskadec.c
+++ b/libavformat/matroskadec.c
@@ -1256,13 +1256,23 @@  static int ebml_parse_elem(MatroskaDemuxContext *matroska,
     case EBML_STOP:
         return 1;
     default:
-        if (ffio_limit(pb, length) != length) {
-            // ffio_limit emits its own error message,
-            // so we don't have to.
-            return AVERROR(EIO);
-        }
-        res = avio_skip(pb, length);
-        res = res < 0 ? res : 0;
+        if (length) {
+            if (ffio_limit(pb, length) != length) {
+                // ffio_limit emits its own error message,
+                // so we don't have to.
+                return AVERROR(EIO);
+            }
+            if ((res = avio_skip(pb, length - 1)) >= 0) {
+                // avio_skip might take us past EOF. We check for this
+                // by skipping only length - 1 bytes, reading a byte and
+                // checking the error flags. This is done in order to check
+                // that the element has been properly skipped even when
+                // no filesize (that ffio_limit relies on) is available.
+                avio_r8(pb);
+                res = NEEDS_CHECKING;
+            }
+        } else
+            res = 0;
     }
     if (res) {
         if (res == NEEDS_CHECKING) {