[1/5] dxv: Check to make sure we don't overrun buffers on corrupt inputs

Message ID 1469706841-90972-1-git-send-email-martin@martin.st
State Committed
Commit 7ebdffc353f3f0827864e8e3461fdc00cc243b14
Headers show

Commit Message

Martin Storsjö July 28, 2016, 11:53 a.m.
---
Not CCing libav-stable, since this wasn't part of the latest release.
---
 libavcodec/dxv.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

Comments

Luca Barbato July 28, 2016, 12:54 p.m. | #1
On 28/07/16 13:53, Martin Storsjö wrote:
> ---
> Not CCing libav-stable, since this wasn't part of the latest release.
> ---
>  libavcodec/dxv.c | 14 +++++++++++---
>  1 file changed, 11 insertions(+), 3 deletions(-)

Set ok, patch 5 has a nit in case you feel to change it.

Patch

diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c
index 32137f5..99327df 100644
--- a/libavcodec/dxv.c
+++ b/libavcodec/dxv.c
@@ -125,7 +125,7 @@  static int dxv_decompress_dxt1(AVCodecContext *avctx)
     AV_WL32(ctx->tex_data + 4, bytestream2_get_le32(gbc));
 
     /* Process input until the whole texture has been filled */
-    while (pos < ctx->tex_size / 4) {
+    while (pos + 2 <= ctx->tex_size / 4) {
         CHECKPOINT(2);
 
         /* Copy two elements from a previous offset or from the input buffer */
@@ -178,7 +178,7 @@  static int dxv_decompress_dxt5(AVCodecContext *avctx)
     AV_WL32(ctx->tex_data + 12, bytestream2_get_le32(gbc));
 
     /* Process input until the whole texture has been filled */
-    while (pos < ctx->tex_size / 4) {
+    while (pos + 2 <= ctx->tex_size / 4) {
         if (run) {
             run--;
 
@@ -207,7 +207,7 @@  static int dxv_decompress_dxt5(AVCodecContext *avctx)
                         check += probe;
                     } while (probe == 0xFFFF);
                 }
-                while (check && pos < ctx->tex_size / 4) {
+                while (check && pos + 4 <= ctx->tex_size / 4) {
                     prev = AV_RL32(ctx->tex_data + 4 * (pos - 4));
                     AV_WL32(ctx->tex_data + 4 * pos, prev);
                     pos++;
@@ -252,6 +252,8 @@  static int dxv_decompress_dxt5(AVCodecContext *avctx)
             case 2:
                 /* Copy two dwords from a previous index */
                 idx = 8 + bytestream2_get_le16(gbc);
+                if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
+                    return AVERROR_INVALIDDATA;
                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
                 AV_WL32(ctx->tex_data + 4 * pos, prev);
                 pos++;
@@ -274,9 +276,13 @@  static int dxv_decompress_dxt5(AVCodecContext *avctx)
         }
 
         CHECKPOINT(4);
+        if (pos + 2 > ctx->tex_size / 4)
+            return AVERROR_INVALIDDATA;
 
         /* Copy two elements from a previous offset or from the input buffer */
         if (op) {
+            if (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4)
+                return AVERROR_INVALIDDATA;
             prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
             AV_WL32(ctx->tex_data + 4 * pos, prev);
             pos++;
@@ -287,6 +293,8 @@  static int dxv_decompress_dxt5(AVCodecContext *avctx)
         } else {
             CHECKPOINT(4);
 
+            if (op && (idx > pos || (unsigned int)(pos - idx) + 2 > ctx->tex_size / 4))
+                return AVERROR_INVALIDDATA;
             if (op)
                 prev = AV_RL32(ctx->tex_data + 4 * (pos - idx));
             else