... | ... |
@@ -43,8 +43,8 @@ typedef struct SgiState { |
43 | 43 |
* @param pixelstride pixel stride of input buffer |
44 | 44 |
* @return size of output in bytes, -1 if buffer overflows |
45 | 45 |
*/ |
46 |
-static int expand_rle_row(SgiState *s, uint8_t *out_buf, |
|
47 |
- int len, int pixelstride) |
|
46 |
+static int expand_rle_row8(SgiState *s, uint8_t *out_buf, |
|
47 |
+ int len, int pixelstride) |
|
48 | 48 |
{ |
49 | 49 |
unsigned char pixel, count; |
50 | 50 |
unsigned char *orig = out_buf; |
... | ... |
@@ -81,6 +81,46 @@ static int expand_rle_row(SgiState *s, uint8_t *out_buf, |
81 | 81 |
return (out_buf - orig) / pixelstride; |
82 | 82 |
} |
83 | 83 |
|
84 |
+static int expand_rle_row16(SgiState *s, uint16_t *out_buf, |
|
85 |
+ int len, int pixelstride) |
|
86 |
+{ |
|
87 |
+ unsigned short pixel; |
|
88 |
+ unsigned char count; |
|
89 |
+ unsigned short *orig = out_buf; |
|
90 |
+ uint16_t *out_end = out_buf + len; |
|
91 |
+ |
|
92 |
+ while (out_buf < out_end) { |
|
93 |
+ if (bytestream2_get_bytes_left(&s->g) < 2) |
|
94 |
+ return AVERROR_INVALIDDATA; |
|
95 |
+ pixel = bytestream2_get_be16u(&s->g); |
|
96 |
+ if (!(count = (pixel & 0x7f))) |
|
97 |
+ break; |
|
98 |
+ |
|
99 |
+ /* Check for buffer overflow. */ |
|
100 |
+ if (pixelstride * (count - 1) >= len) { |
|
101 |
+ av_log(s->avctx, AV_LOG_ERROR, "Invalid pixel count.\n"); |
|
102 |
+ return AVERROR_INVALIDDATA; |
|
103 |
+ } |
|
104 |
+ |
|
105 |
+ if (pixel & 0x80) { |
|
106 |
+ while (count--) { |
|
107 |
+ pixel = bytestream2_get_ne16(&s->g); |
|
108 |
+ AV_WN16A(out_buf, pixel); |
|
109 |
+ out_buf += pixelstride; |
|
110 |
+ } |
|
111 |
+ } else { |
|
112 |
+ pixel = bytestream2_get_ne16(&s->g); |
|
113 |
+ |
|
114 |
+ while (count--) { |
|
115 |
+ AV_WN16A(out_buf, pixel); |
|
116 |
+ out_buf += pixelstride; |
|
117 |
+ } |
|
118 |
+ } |
|
119 |
+ } |
|
120 |
+ return (out_buf - orig) / pixelstride; |
|
121 |
+} |
|
122 |
+ |
|
123 |
+ |
|
84 | 124 |
/** |
85 | 125 |
* Read a run length encoded SGI image. |
86 | 126 |
* @param out_buf output buffer |
... | ... |
@@ -94,6 +134,7 @@ static int read_rle_sgi(uint8_t *out_buf, SgiState *s) |
94 | 94 |
GetByteContext g_table = s->g; |
95 | 95 |
unsigned int y, z; |
96 | 96 |
unsigned int start_offset; |
97 |
+ int linesize, ret; |
|
97 | 98 |
|
98 | 99 |
/* size of RLE offset and length tables */ |
99 | 100 |
if (len * 2 > bytestream2_get_bytes_left(&s->g)) { |
... | ... |
@@ -103,13 +144,16 @@ static int read_rle_sgi(uint8_t *out_buf, SgiState *s) |
103 | 103 |
for (z = 0; z < s->depth; z++) { |
104 | 104 |
dest_row = out_buf; |
105 | 105 |
for (y = 0; y < s->height; y++) { |
106 |
+ linesize = s->width * s->depth * s->bytes_per_channel; |
|
106 | 107 |
dest_row -= s->linesize; |
107 | 108 |
start_offset = bytestream2_get_be32(&g_table); |
108 | 109 |
bytestream2_seek(&s->g, start_offset, SEEK_SET); |
109 |
- if (expand_rle_row(s, dest_row + z, s->width * s->depth, |
|
110 |
- s->depth) != s->width) { |
|
110 |
+ if (s->bytes_per_channel == 1) |
|
111 |
+ ret = expand_rle_row8(s, dest_row + z, linesize, s->depth); |
|
112 |
+ else |
|
113 |
+ ret = expand_rle_row16(s, (uint16_t *)dest_row + z, linesize, s->depth); |
|
114 |
+ if (ret != s->width) |
|
111 | 115 |
return AVERROR_INVALIDDATA; |
112 |
- } |
|
113 | 116 |
} |
114 | 117 |
} |
115 | 118 |
return 0; |
... | ... |
@@ -183,7 +227,7 @@ static int decode_frame(AVCodecContext *avctx, |
183 | 183 |
s->height = bytestream2_get_be16(&s->g); |
184 | 184 |
s->depth = bytestream2_get_be16(&s->g); |
185 | 185 |
|
186 |
- if (s->bytes_per_channel != 1 && (s->bytes_per_channel != 2 || rle)) { |
|
186 |
+ if (s->bytes_per_channel != 1 && s->bytes_per_channel != 2) { |
|
187 | 187 |
av_log(avctx, AV_LOG_ERROR, "wrong channel number\n"); |
188 | 188 |
return -1; |
189 | 189 |
} |