Revision 8458dab1 libavcodec/vmdav.c

View differences:

libavcodec/vmdav.c
66 66

  
67 67
    unsigned char palette[PALETTE_COUNT * 4];
68 68
    unsigned char *unpack_buffer;
69
    int unpack_buffer_size;
69 70

  
70 71
} VmdVideoContext;
71 72

  
72 73
#define QUEUE_SIZE 0x1000
73 74
#define QUEUE_MASK 0x0FFF
74 75

  
75
static void lz_unpack(unsigned char *src, unsigned char *dest)
76
static void lz_unpack(unsigned char *src, unsigned char *dest, int dest_len)
76 77
{
77 78
    unsigned char *s;
78 79
    unsigned char *d;
80
    unsigned char *d_end;
79 81
    unsigned char queue[QUEUE_SIZE];
80 82
    unsigned int qpos;
81 83
    unsigned int dataleft;
......
87 89

  
88 90
    s = src;
89 91
    d = dest;
92
    d_end = d + dest_len;
90 93
    dataleft = LE_32(s);
91 94
    s += 4;
92 95
    memset(queue, QUEUE_SIZE, 0x20);
......
102 105
    while (dataleft > 0) {
103 106
        tag = *s++;
104 107
        if ((tag == 0xFF) && (dataleft > 8)) {
108
            if (d + 8 > d_end)
109
                return;
105 110
            for (i = 0; i < 8; i++) {
106 111
                queue[qpos++] = *d++ = *s++;
107 112
                qpos &= QUEUE_MASK;
......
112 117
                if (dataleft == 0)
113 118
                    break;
114 119
                if (tag & 0x01) {
120
                    if (d + 1 > d_end)
121
                        return;
115 122
                    queue[qpos++] = *d++ = *s++;
116 123
                    qpos &= QUEUE_MASK;
117 124
                    dataleft--;
......
121 128
                    chainlen = (*s++ & 0x0F) + 3;
122 129
                    if (chainlen == speclen)
123 130
                        chainlen = *s++ + 0xF + 3;
131
                    if (d + chainlen > d_end)
132
                        return;
124 133
                    for (j = 0; j < chainlen; j++) {
125 134
                        *d = queue[chainofs++ & QUEUE_MASK];
126 135
                        queue[qpos++] = *d++;
......
134 143
    }
135 144
}
136 145

  
137
static int rle_unpack(unsigned char *src, unsigned char *dest, int len)
146
static int rle_unpack(unsigned char *src, unsigned char *dest, 
147
    int src_len, int dest_len)
138 148
{
139 149
    unsigned char *ps;
140 150
    unsigned char *pd;
141 151
    int i, l;
152
    unsigned char *dest_end = dest + dest_len;
142 153

  
143 154
    ps = src;
144 155
    pd = dest;
145
    if (len & 1)
156
    if (src_len & 1)
146 157
        *pd++ = *ps++;
147 158

  
148
    len >>= 1;
159
    src_len >>= 1;
149 160
    i = 0;
150 161
    do {
151 162
        l = *ps++;
152 163
        if (l & 0x80) {
153 164
            l = (l & 0x7F) * 2;
165
            if (pd + l > dest_end)
166
                return (ps - src);
154 167
            memcpy(pd, ps, l);
155 168
            ps += l;
156 169
            pd += l;
157 170
        } else {
171
            if (pd + i > dest_end)
172
                return (ps - src);
158 173
            for (i = 0; i < l; i++) {
159 174
                *pd++ = ps[0];
160 175
                *pd++ = ps[1];
......
162 177
            ps += 2;
163 178
        }
164 179
        i += l;
165
    } while (i < len);
180
    } while (i < src_len);
166 181

  
167 182
    return (ps - src);
168 183
}
......
185 200

  
186 201
    int frame_x, frame_y;
187 202
    int frame_width, frame_height;
203
    int dp_size;
188 204

  
189 205
    frame_x = LE_16(&s->buf[6]);
190 206
    frame_y = LE_16(&s->buf[8]);
......
217 233
        pb = p;
218 234
        meth = *pb++;
219 235
        if (meth & 0x80) {
220
            lz_unpack(pb, s->unpack_buffer);
236
            lz_unpack(pb, s->unpack_buffer, s->unpack_buffer_size);
221 237
            meth &= 0x7F;
222 238
            pb = s->unpack_buffer;
223 239
        }
224 240

  
225 241
        dp = &s->frame.data[0][frame_y * s->frame.linesize[0] + frame_x];
242
        dp_size = s->frame.linesize[0] * s->avctx->height;
226 243
        pp = &s->prev_frame.data[0][frame_y * s->prev_frame.linesize[0] + frame_x];
227 244
        switch (meth) {
228 245
        case 1:
......
232 249
                    len = *pb++;
233 250
                    if (len & 0x80) {
234 251
                        len = (len & 0x7F) + 1;
252
                        if (ofs + len > frame_width)
253
                            return;
235 254
                        memcpy(&dp[ofs], pb, len);
236 255
                        pb += len;
237 256
                        ofs += len;
238 257
                    } else {
239 258
                        /* interframe pixel copy */
259
                        if (ofs + len + 1 > frame_width)
260
                            return;
240 261
                        memcpy(&dp[ofs], &pp[ofs], len + 1);
241 262
                        ofs += len + 1;
242 263
                    }
......
268 289
                    if (len & 0x80) {
269 290
                        len = (len & 0x7F) + 1;
270 291
                        if (*pb++ == 0xFF)
271
                            len = rle_unpack(pb, &dp[ofs], len);
292
                            len = rle_unpack(pb, &dp[ofs], len, frame_width - ofs);
272 293
                        else
273 294
                            memcpy(&dp[ofs], pb, len);
274 295
                        pb += len;
275 296
                        ofs += len;
276 297
                    } else {
277 298
                        /* interframe pixel copy */
299
                        if (ofs + len + 1 > frame_width)
300
                            return;
278 301
                        memcpy(&dp[ofs], &pp[ofs], len + 1);
279 302
                        ofs += len + 1;
280 303
                    }
......
314 337
    }
315 338
    vmd_header = (unsigned char *)avctx->extradata;
316 339

  
317
    s->unpack_buffer = av_malloc(LE_32(&vmd_header[800]));
340
    s->unpack_buffer_size = LE_32(&vmd_header[800]);
341
    s->unpack_buffer = av_malloc(s->unpack_buffer_size);
318 342
    if (!s->unpack_buffer)
319 343
        return -1;
320 344

  

Also available in: Unified diff