Revision 7782cb20 libavcodec/targa.c

View differences:

libavcodec/targa.c
33 33
    int compression_type;
34 34
} TargaContext;
35 35

  
36
static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8_t *src, uint8_t *dst, int w, int h, int stride, int bpp)
36
#define CHECK_BUFFER_SIZE(buf, buf_end, needed, where) \
37
    if(buf + needed > buf_end){ \
38
        av_log(avctx, AV_LOG_ERROR, "Problem: unexpected end of data while reading " where "\n"); \
39
        return -1; \
40
    } \
41

  
42
static int targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8_t *src, int src_size, uint8_t *dst, int w, int h, int stride, int bpp)
37 43
{
38 44
    int i, x, y;
39 45
    int depth = (bpp + 1) >> 3;
40 46
    int type, count;
41 47
    int diff;
48
    const uint8_t *src_end = src + src_size;
42 49

  
43 50
    diff = stride - w * depth;
44 51
    x = y = 0;
45 52
    while(y < h){
53
        CHECK_BUFFER_SIZE(src, src_end, 1, "image type");
46 54
        type = *src++;
47 55
        count = (type & 0x7F) + 1;
48 56
        type &= 0x80;
49 57
        if((x + count > w) && (x + count + 1 > (h - y) * w)){
50 58
            av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count);
51
            return;
59
            return -1;
60
        }
61
        if(type){
62
            CHECK_BUFFER_SIZE(src, src_end, depth, "image data");
63
        }else{
64
            CHECK_BUFFER_SIZE(src, src_end, count * depth, "image data");
52 65
        }
53 66
        for(i = 0; i < count; i++){
54 67
            switch(depth){
......
81 94
        if(type)
82 95
            src += depth;
83 96
    }
97
    return src_size;
84 98
}
85 99

  
86 100
static int decode_frame(AVCodecContext *avctx,
......
88 102
                        AVPacket *avpkt)
89 103
{
90 104
    const uint8_t *buf = avpkt->data;
91
    int buf_size = avpkt->size;
105
    const uint8_t *buf_end = avpkt->data + avpkt->size;
92 106
    TargaContext * const s = avctx->priv_data;
93 107
    AVFrame *picture = data;
94 108
    AVFrame * const p= (AVFrame*)&s->picture;
......
98 112
    int first_clr, colors, csize;
99 113

  
100 114
    /* parse image header */
115
    CHECK_BUFFER_SIZE(buf, buf_end, 18, "header");
101 116
    idlen = *buf++;
102 117
    pal = *buf++;
103 118
    compr = *buf++;
......
111 126
    bpp = *buf++;
112 127
    flags = *buf++;
113 128
    //skip identifier if any
129
    CHECK_BUFFER_SIZE(buf, buf_end, idlen, "identifiers");
114 130
    buf += idlen;
115 131
    s->bpp = bpp;
116 132
    s->width = w;
......
163 179
        }
164 180
    }
165 181
    if(colors){
182
        size_t pal_size;
166 183
        if((colors + first_clr) > 256){
167 184
            av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
168 185
            return -1;
......
171 188
            av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
172 189
            return -1;
173 190
        }
191
        pal_size = colors * ((csize + 1) >> 3);
192
        CHECK_BUFFER_SIZE(buf, buf_end, pal_size, "color table");
174 193
        if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway
175
            buf += colors * ((csize + 1) >> 3);
194
            buf += pal_size;
176 195
        else{
177 196
            int r, g, b, t;
178 197
            int32_t *pal = ((int32_t*)p->data[1]) + first_clr;
......
188 207
    if((compr & (~TGA_RLE)) == TGA_NODATA)
189 208
        memset(p->data[0], 0, p->linesize[0] * s->height);
190 209
    else{
191
        if(compr & TGA_RLE)
192
            targa_decode_rle(avctx, s, buf, dst, avctx->width, avctx->height, stride, bpp);
193
        else{
210
        if(compr & TGA_RLE){
211
            int res = targa_decode_rle(avctx, s, buf, buf_end - buf, dst, avctx->width, avctx->height, stride, bpp);
212
            if (res < 0)
213
                return -1;
214
            buf += res;
215
        }else{
216
            size_t img_size = s->width * ((s->bpp + 1) >> 3);
217
            CHECK_BUFFER_SIZE(buf, buf_end, img_size, "image data");
194 218
            for(y = 0; y < s->height; y++){
195 219
#if HAVE_BIGENDIAN
196 220
                if((s->bpp + 1) >> 3 == 2){
......
203 227
                        dst32[x] = AV_RL32(buf + x * 4);
204 228
                }else
205 229
#endif
206
                    memcpy(dst, buf, s->width * ((s->bpp + 1) >> 3));
230
                    memcpy(dst, buf, img_size);
207 231

  
208 232
                dst += stride;
209
                buf += s->width * ((s->bpp + 1) >> 3);
233
                buf += img_size;
210 234
            }
211 235
        }
212 236
    }
......
214 238
    *picture= *(AVFrame*)&s->picture;
215 239
    *data_size = sizeof(AVPicture);
216 240

  
217
    return buf_size;
241
    return avpkt->size;
218 242
}
219 243

  
220 244
static av_cold int targa_init(AVCodecContext *avctx){

Also available in: Unified diff