|
|
@@ -173,6 +173,9 @@ typedef struct EXRContext {
|
|
|
|
|
|
int is_luma;/* 1 if there is an Y plane */
|
|
|
|
|
|
+#define M(chr) (1<<chr - 'A')
|
|
|
+ int has_channel; ///< combination of flags representing the channel codes A-Z
|
|
|
+
|
|
|
GetByteContext gb;
|
|
|
const uint8_t *buf;
|
|
|
int buf_size;
|
|
|
@@ -739,12 +742,12 @@ static int pxr24_uncompress(const EXRContext *s, const uint8_t *src,
|
|
|
break;
|
|
|
case EXR_UINT:
|
|
|
ptr[0] = in;
|
|
|
- ptr[1] = ptr[0] + s->xdelta;
|
|
|
- ptr[2] = ptr[1] + s->xdelta;
|
|
|
- ptr[3] = ptr[2] + s->xdelta;
|
|
|
- in = ptr[3] + s->xdelta;
|
|
|
+ ptr[1] = ptr[0] + td->xsize;
|
|
|
+ ptr[2] = ptr[1] + td->xsize;
|
|
|
+ ptr[3] = ptr[2] + td->xsize;
|
|
|
+ in = ptr[3] + td->xsize;
|
|
|
|
|
|
- for (j = 0; j < s->xdelta; ++j) {
|
|
|
+ for (j = 0; j < td->xsize; ++j) {
|
|
|
uint32_t diff = ((uint32_t)*(ptr[0]++) << 24) |
|
|
|
(*(ptr[1]++) << 16) |
|
|
|
(*(ptr[2]++) << 8 ) |
|
|
|
@@ -986,8 +989,8 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse
|
|
|
int64_t version, lo_usize, lo_size;
|
|
|
int64_t ac_size, dc_size, rle_usize, rle_csize, rle_raw_size;
|
|
|
int64_t ac_count, dc_count, ac_compression;
|
|
|
- const int dc_w = td->xsize >> 3;
|
|
|
- const int dc_h = td->ysize >> 3;
|
|
|
+ const int dc_w = (td->xsize + 7) >> 3;
|
|
|
+ const int dc_h = (td->ysize + 7) >> 3;
|
|
|
GetByteContext gb, agb;
|
|
|
int skip, ret;
|
|
|
int have_rle = 0;
|
|
|
@@ -999,6 +1002,11 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse
|
|
|
if (version != 2)
|
|
|
return AVERROR_INVALIDDATA;
|
|
|
|
|
|
+ if (s->nb_channels < 3) {
|
|
|
+ avpriv_request_sample(s->avctx, "Gray DWA");
|
|
|
+ return AVERROR_PATCHWELCOME;
|
|
|
+ }
|
|
|
+
|
|
|
lo_usize = AV_RL64(src + 8);
|
|
|
lo_size = AV_RL64(src + 16);
|
|
|
ac_size = AV_RL64(src + 24);
|
|
|
@@ -1015,11 +1023,20 @@ static int dwa_uncompress(const EXRContext *s, const uint8_t *src, int compresse
|
|
|
)
|
|
|
return AVERROR_INVALIDDATA;
|
|
|
|
|
|
+ if (ac_size <= 0) {
|
|
|
+ avpriv_request_sample(s->avctx, "Zero ac_size");
|
|
|
+ return AVERROR_INVALIDDATA;
|
|
|
+ }
|
|
|
+
|
|
|
if ((uint64_t)rle_raw_size > INT_MAX) {
|
|
|
avpriv_request_sample(s->avctx, "Too big rle_raw_size");
|
|
|
return AVERROR_INVALIDDATA;
|
|
|
}
|
|
|
|
|
|
+ if (td->xsize % 8 || td->ysize % 8) {
|
|
|
+ avpriv_request_sample(s->avctx, "odd dimensions DWA");
|
|
|
+ }
|
|
|
+
|
|
|
bytestream2_init(&gb, src + 88, compressed_size - 88);
|
|
|
skip = bytestream2_get_le16(&gb);
|
|
|
if (skip < 2)
|
|
|
@@ -1580,6 +1597,7 @@ static int decode_header(EXRContext *s, AVFrame *frame)
|
|
|
s->is_tile = 0;
|
|
|
s->is_multipart = 0;
|
|
|
s->is_luma = 0;
|
|
|
+ s->has_channel = 0;
|
|
|
s->current_part = 0;
|
|
|
|
|
|
if (bytestream2_get_bytes_left(gb) < 10) {
|
|
|
@@ -1683,23 +1701,26 @@ static int decode_header(EXRContext *s, AVFrame *frame)
|
|
|
}
|
|
|
|
|
|
if (layer_match) { /* only search channel if the layer match is valid */
|
|
|
+ if (strlen(ch_gb.buffer) == 1) {
|
|
|
+ int ch_chr = av_toupper(*ch_gb.buffer);
|
|
|
+ if (ch_chr >= 'A' && ch_chr <= 'Z')
|
|
|
+ s->has_channel |= M(ch_chr);
|
|
|
+ av_log(s->avctx, AV_LOG_DEBUG, "%c\n", ch_chr);
|
|
|
+ }
|
|
|
+
|
|
|
if (!av_strcasecmp(ch_gb.buffer, "R") ||
|
|
|
!av_strcasecmp(ch_gb.buffer, "X") ||
|
|
|
!av_strcasecmp(ch_gb.buffer, "U")) {
|
|
|
channel_index = 0;
|
|
|
- s->is_luma = 0;
|
|
|
} else if (!av_strcasecmp(ch_gb.buffer, "G") ||
|
|
|
!av_strcasecmp(ch_gb.buffer, "V")) {
|
|
|
channel_index = 1;
|
|
|
- s->is_luma = 0;
|
|
|
} else if (!av_strcasecmp(ch_gb.buffer, "Y")) {
|
|
|
channel_index = 1;
|
|
|
- s->is_luma = 1;
|
|
|
} else if (!av_strcasecmp(ch_gb.buffer, "B") ||
|
|
|
!av_strcasecmp(ch_gb.buffer, "Z") ||
|
|
|
!av_strcasecmp(ch_gb.buffer, "W")) {
|
|
|
channel_index = 2;
|
|
|
- s->is_luma = 0;
|
|
|
} else if (!av_strcasecmp(ch_gb.buffer, "A")) {
|
|
|
channel_index = 3;
|
|
|
} else {
|
|
|
@@ -1775,6 +1796,20 @@ static int decode_header(EXRContext *s, AVFrame *frame)
|
|
|
s->current_channel_offset += 4;
|
|
|
}
|
|
|
}
|
|
|
+ if (!((M('R') + M('G') + M('B')) & ~s->has_channel)) {
|
|
|
+ s->is_luma = 0;
|
|
|
+ } else if (!((M('X') + M('Y') + M('Z')) & ~s->has_channel)) {
|
|
|
+ s->is_luma = 0;
|
|
|
+ } else if (!((M('Y') + M('U') + M('V')) & ~s->has_channel)) {
|
|
|
+ s->is_luma = 0;
|
|
|
+ } else if (!((M('Y') ) & ~s->has_channel) &&
|
|
|
+ !((M('R') + M('G') + M('B') + M('U') + M('V') + M('X') + M('Z')) & s->has_channel)) {
|
|
|
+ s->is_luma = 1;
|
|
|
+ } else {
|
|
|
+ avpriv_request_sample(s->avctx, "Uncommon channel combination");
|
|
|
+ ret = AVERROR(AVERROR_PATCHWELCOME);
|
|
|
+ goto fail;
|
|
|
+ }
|
|
|
|
|
|
/* Check if all channels are set with an offset or if the channels
|
|
|
* are causing an overflow */
|