History

targa: fix potential buffer overreads

Jean-Daniel Dupas committed 15 years ago

Commit 7782cb21 parent 56cbc5f1 file · +34 −10Browse files

Unified · Split

libavcodec/targa.c+34−10
@@ -33,22 +33,35 @@ typedef struct TargaContext { · 32 unmodified lines
33 int compression_type;33 int compression_type;
34} TargaContext;34} TargaContext;
35 35
36static 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
42static 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 int i, x, y;44 int i, x, y;
39 int depth = (bpp + 1) >> 3;45 int depth = (bpp + 1) >> 3;
40 int type, count;46 int type, count;
41 int diff;47 int diff;
48 const uint8_t *src_end = src + src_size;
42 49
43 diff = stride - w * depth;50 diff = stride - w * depth;
44 x = y = 0;51 x = y = 0;
45 while(y < h){52 while(y < h){
53 CHECK_BUFFER_SIZE(src, src_end, 1, "image type");
46 type = *src++;54 type = *src++;
47 count = (type & 0x7F) + 1;55 count = (type & 0x7F) + 1;
48 type &= 0x80;56 type &= 0x80;
49 if((x + count > w) && (x + count + 1 > (h - y) * w)){57 if((x + count > w) && (x + count + 1 > (h - y) * w)){
50 av_log(avctx, AV_LOG_ERROR, "Packet went out of bounds: position (%i,%i) size %i\n", x, y, count);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 for(i = 0; i < count; i++){66 for(i = 0; i < count; i++){
54 switch(depth){67 switch(depth){
@@ -81,6 +94,7 @@ static void targa_decode_rle(AVCodecContext *avctx, TargaContext *s, const uint8 · 26 unmodified lines
81 if(type)94 if(type)
82 src += depth;95 src += depth;
83 }96 }
97 return src_size;
84}98}
85 99
86static int decode_frame(AVCodecContext *avctx,100static int decode_frame(AVCodecContext *avctx,
@@ -88,7 +102,7 @@ static int decode_frame(AVCodecContext *avctx, · 1 unmodified line
88 AVPacket *avpkt)102 AVPacket *avpkt)
89{103{
90 const uint8_t *buf = avpkt->data;104 const uint8_t *buf = avpkt->data;
91 int buf_size = avpkt->size;105 const uint8_t *buf_end = avpkt->data + avpkt->size;
92 TargaContext * const s = avctx->priv_data;106 TargaContext * const s = avctx->priv_data;
93 AVFrame *picture = data;107 AVFrame *picture = data;
94 AVFrame * const p= (AVFrame*)&s->picture;108 AVFrame * const p= (AVFrame*)&s->picture;
@@ -98,6 +112,7 @@ static int decode_frame(AVCodecContext *avctx, · 3 unmodified lines
98 int first_clr, colors, csize;112 int first_clr, colors, csize;
99 113
100 /* parse image header */114 /* parse image header */
115 CHECK_BUFFER_SIZE(buf, buf_end, 18, "header");
101 idlen = *buf++;116 idlen = *buf++;
102 pal = *buf++;117 pal = *buf++;
103 compr = *buf++;118 compr = *buf++;
@@ -111,6 +126,7 @@ static int decode_frame(AVCodecContext *avctx, · 7 unmodified lines
111 bpp = *buf++;126 bpp = *buf++;
112 flags = *buf++;127 flags = *buf++;
113 //skip identifier if any128 //skip identifier if any
129 CHECK_BUFFER_SIZE(buf, buf_end, idlen, "identifiers");
114 buf += idlen;130 buf += idlen;
115 s->bpp = bpp;131 s->bpp = bpp;
116 s->width = w;132 s->width = w;
@@ -163,6 +179,7 @@ static int decode_frame(AVCodecContext *avctx, · 46 unmodified lines
163 }179 }
164 }180 }
165 if(colors){181 if(colors){
182 size_t pal_size;
166 if((colors + first_clr) > 256){183 if((colors + first_clr) > 256){
167 av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);184 av_log(avctx, AV_LOG_ERROR, "Incorrect palette: %i colors with offset %i\n", colors, first_clr);
168 return -1;185 return -1;
@@ -171,8 +188,10 @@ static int decode_frame(AVCodecContext *avctx, · 2 unmodified lines
171 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);188 av_log(avctx, AV_LOG_ERROR, "Palette entry size %i bits is not supported\n", csize);
172 return -1;189 return -1;
173 }190 }
191 pal_size = colors * ((csize + 1) >> 3);
192 CHECK_BUFFER_SIZE(buf, buf_end, pal_size, "color table");
174 if(avctx->pix_fmt != PIX_FMT_PAL8)//should not occur but skip palette anyway193 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 else{195 else{
177 int r, g, b, t;196 int r, g, b, t;
178 int32_t *pal = ((int32_t*)p->data[1]) + first_clr;197 int32_t *pal = ((int32_t*)p->data[1]) + first_clr;
@@ -188,9 +207,14 @@ static int decode_frame(AVCodecContext *avctx, · 9 unmodified lines
188 if((compr & (~TGA_RLE)) == TGA_NODATA)207 if((compr & (~TGA_RLE)) == TGA_NODATA)
189 memset(p->data[0], 0, p->linesize[0] * s->height);208 memset(p->data[0], 0, p->linesize[0] * s->height);
190 else{209 else{
191 if(compr & TGA_RLE)210 if(compr & TGA_RLE){
192 targa_decode_rle(avctx, s, buf, dst, avctx->width, avctx->height, stride, bpp);211 int res = targa_decode_rle(avctx, s, buf, buf_end - buf, dst, avctx->width, avctx->height, stride, bpp);
193 else{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 for(y = 0; y < s->height; y++){218 for(y = 0; y < s->height; y++){
195#if HAVE_BIGENDIAN219#if HAVE_BIGENDIAN
196 if((s->bpp + 1) >> 3 == 2){220 if((s->bpp + 1) >> 3 == 2){
@@ -203,10 +227,10 @@ static int decode_frame(AVCodecContext *avctx, · 6 unmodified lines
203 dst32[x] = AV_RL32(buf + x * 4);227 dst32[x] = AV_RL32(buf + x * 4);
204 }else228 }else
205#endif229#endif
206 memcpy(dst, buf, s->width * ((s->bpp + 1) >> 3));230 memcpy(dst, buf, img_size);
207 231
208 dst += stride;232 dst += stride;
209 buf += s->width * ((s->bpp + 1) >> 3);233 buf += img_size;
210 }234 }
211 }235 }
212 }236 }
@@ -214,7 +238,7 @@ static int decode_frame(AVCodecContext *avctx, · 1 unmodified line
214 *picture= *(AVFrame*)&s->picture;238 *picture= *(AVFrame*)&s->picture;
215 *data_size = sizeof(AVPicture);239 *data_size = sizeof(AVPicture);
216 240
217 return buf_size;241 return avpkt->size;
218}242}
219 243
220static av_cold int targa_init(AVCodecContext *avctx){244static av_cold int targa_init(AVCodecContext *avctx){

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t