Browse code

avcodec/012v: redesign main loop

Fixes out of array accesses
Fixes: ffmpeg_012v_crash.ts

Found-by: Thomas Lindroth <thomas.lindroth@gmail.com>
Reviewed-by: Thomas Lindroth <thomas.lindroth@gmail.com>
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
(cherry picked from commit 48df30d36c3ca360c407d84f96749888d1fbe853)

Signed-off-by: Michael Niedermayer <michaelni@gmx.at>

Michael Niedermayer authored on 2015/03/11 03:18:34
Showing 1 changed files
... ...
@@ -38,7 +38,7 @@ static av_cold int zero12v_decode_init(AVCodecContext *avctx)
38 38
 static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
39 39
                                 int *got_frame, AVPacket *avpkt)
40 40
 {
41
-    int line = 0, ret;
41
+    int line, ret;
42 42
     const int width = avctx->width;
43 43
     AVFrame *pic = data;
44 44
     uint16_t *y, *u, *v;
... ...
@@ -67,45 +67,45 @@ static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
67 67
     pic->pict_type = AV_PICTURE_TYPE_I;
68 68
     pic->key_frame = 1;
69 69
 
70
-    y = (uint16_t *)pic->data[0];
71
-    u = (uint16_t *)pic->data[1];
72
-    v = (uint16_t *)pic->data[2];
73 70
     line_end = avpkt->data + stride;
71
+    for (line = 0; line < avctx->height; line++) {
72
+        uint16_t y_temp[6] = {0x8000, 0x8000, 0x8000, 0x8000, 0x8000, 0x8000};
73
+        uint16_t u_temp[3] = {0x8000, 0x8000, 0x8000};
74
+        uint16_t v_temp[3] = {0x8000, 0x8000, 0x8000};
75
+        int x;
76
+        y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
77
+        u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
78
+        v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
79
+
80
+        for (x = 0; x < width; x += 6) {
81
+            uint32_t t;
82
+
83
+            if (width - x < 6 || line_end - src < 16) {
84
+                y = y_temp;
85
+                u = u_temp;
86
+                v = v_temp;
87
+            }
88
+
89
+            if (line_end - src < 4)
90
+                break;
74 91
 
75
-    while (line++ < avctx->height) {
76
-        while (1) {
77
-            uint32_t t = AV_RL32(src);
92
+            t = AV_RL32(src);
78 93
             src += 4;
79 94
             *u++ = t <<  6 & 0xFFC0;
80 95
             *y++ = t >>  4 & 0xFFC0;
81 96
             *v++ = t >> 14 & 0xFFC0;
82 97
 
83
-            if (src >= line_end - 1) {
84
-                *y = 0x80;
85
-                src++;
86
-                line_end += stride;
87
-                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
88
-                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
89
-                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
98
+            if (line_end - src < 4)
90 99
                 break;
91
-            }
92 100
 
93 101
             t = AV_RL32(src);
94 102
             src += 4;
95 103
             *y++ = t <<  6 & 0xFFC0;
96 104
             *u++ = t >>  4 & 0xFFC0;
97 105
             *y++ = t >> 14 & 0xFFC0;
98
-            if (src >= line_end - 2) {
99
-                if (!(width & 1)) {
100
-                    *y = 0x80;
101
-                    src += 2;
102
-                }
103
-                line_end += stride;
104
-                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
105
-                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
106
-                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
106
+
107
+            if (line_end - src < 4)
107 108
                 break;
108
-            }
109 109
 
110 110
             t = AV_RL32(src);
111 111
             src += 4;
... ...
@@ -113,15 +113,8 @@ static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
113 113
             *y++ = t >>  4 & 0xFFC0;
114 114
             *u++ = t >> 14 & 0xFFC0;
115 115
 
116
-            if (src >= line_end - 1) {
117
-                *y = 0x80;
118
-                src++;
119
-                line_end += stride;
120
-                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
121
-                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
122
-                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
116
+            if (line_end - src < 4)
123 117
                 break;
124
-            }
125 118
 
126 119
             t = AV_RL32(src);
127 120
             src += 4;
... ...
@@ -129,18 +122,21 @@ static int zero12v_decode_frame(AVCodecContext *avctx, void *data,
129 129
             *v++ = t >>  4 & 0xFFC0;
130 130
             *y++ = t >> 14 & 0xFFC0;
131 131
 
132
-            if (src >= line_end - 2) {
133
-                if (width & 1) {
134
-                    *y = 0x80;
135
-                    src += 2;
136
-                }
137
-                line_end += stride;
138
-                y = (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
139
-                u = (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
140
-                v = (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
132
+            if (width - x < 6)
141 133
                 break;
142
-            }
143 134
         }
135
+
136
+        if (x < width) {
137
+            y = x   + (uint16_t *)(pic->data[0] + line * pic->linesize[0]);
138
+            u = x/2 + (uint16_t *)(pic->data[1] + line * pic->linesize[1]);
139
+            v = x/2 + (uint16_t *)(pic->data[2] + line * pic->linesize[2]);
140
+            memcpy(y, y_temp, sizeof(*y) * (width - x));
141
+            memcpy(u, u_temp, sizeof(*u) * (width - x + 1) / 2);
142
+            memcpy(v, v_temp, sizeof(*v) * (width - x + 1) / 2);
143
+        }
144
+
145
+        line_end += stride;
146
+        src = line_end - stride;
144 147
     }
145 148
 
146 149
     *got_frame = 1;