X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fjpeg2000dec.c;h=96dab8e1766c1675a89782c48c54418efc96e807;hb=27e30c73d722ec13e59753dea91be00859c72bf2;hp=62b9009a82c15ada20049685e6da25c6438a1910;hpb=b449af20d5d4b53cdc51696a04477a16336dc22d;p=ffmpeg diff --git a/libavcodec/jpeg2000dec.c b/libavcodec/jpeg2000dec.c index 62b9009a82c..96dab8e1766 100644 --- a/libavcodec/jpeg2000dec.c +++ b/libavcodec/jpeg2000dec.c @@ -34,6 +34,7 @@ #include "libavutil/imgutils.h" #include "libavutil/opt.h" #include "libavutil/pixdesc.h" +#include "libavutil/thread.h" #include "avcodec.h" #include "bytestream.h" #include "internal.h" @@ -81,7 +82,7 @@ typedef struct Jpeg2000Tile { Jpeg2000CodingStyle codsty[4]; Jpeg2000QuantStyle qntsty[4]; Jpeg2000POC poc; - Jpeg2000TilePart tile_part[256]; + Jpeg2000TilePart tile_part[32]; uint16_t tp_idx; // Tile-part index int coord[2][2]; // border coordinates {{x0, x1}, {y0, y1}} } Jpeg2000Tile; @@ -284,7 +285,7 @@ static int get_siz(Jpeg2000DecoderContext *s) avpriv_request_sample(s->avctx, "Support for image offsets"); return AVERROR_PATCHWELCOME; } - if (av_image_check_size(s->width, s->height, 0, s->avctx)) { + if (av_image_check_size2(s->width, s->height, s->avctx->max_pixels, AV_PIX_FMT_NONE, 0, s->avctx)) { avpriv_request_sample(s->avctx, "Large Dimensions"); return AVERROR_PATCHWELCOME; } @@ -342,7 +343,10 @@ static int get_siz(Jpeg2000DecoderContext *s) s->numXtiles = ff_jpeg2000_ceildiv(s->width - s->tile_offset_x, s->tile_width); s->numYtiles = ff_jpeg2000_ceildiv(s->height - s->tile_offset_y, s->tile_height); - if (s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(*s->tile)) { + // There must be at least a SOT and SOD per tile, their minimum size is 14 + if (s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(*s->tile) || + s->numXtiles * s->numYtiles * 14LL > bytestream2_size(&s->g) + ) { s->numXtiles = s->numYtiles = 0; return AVERROR(EINVAL); } @@ -760,7 +764,10 @@ static int get_sot(Jpeg2000DecoderContext *s, int n) return AVERROR_INVALIDDATA; } - av_assert0(TPsot < FF_ARRAY_ELEMS(s->tile[Isot].tile_part)); + if (TPsot >= FF_ARRAY_ELEMS(s->tile[Isot].tile_part)) { + avpriv_request_sample(s->avctx, "Too many tile parts"); + return AVERROR_PATCHWELCOME; + } s->tile[Isot].tp_idx = TPsot; tp = s->tile[Isot].tile_part + TPsot; @@ -949,6 +956,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) { Jpeg2000Cblk *cblk = prec->cblk + cblkno; int incl, newpasses, llen; + void *tmp; if (cblk->npasses) incl = get_bits(s, 1); @@ -988,6 +996,14 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, cblk->nb_lengthinc = 0; cblk->nb_terminationsinc = 0; + av_free(cblk->lengthinc); + cblk->lengthinc = av_mallocz_array(newpasses , sizeof(*cblk->lengthinc)); + if (!cblk->lengthinc) + return AVERROR(ENOMEM); + tmp = av_realloc_array(cblk->data_start, cblk->nb_terminations + newpasses + 1, sizeof(*cblk->data_start)); + if (!tmp) + return AVERROR(ENOMEM); + cblk->data_start = tmp; do { int newpasses1 = 0; @@ -1001,10 +1017,18 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, if ((ret = get_bits(s, av_log2(newpasses1) + cblk->lblock)) < 0) return ret; - if (ret > sizeof(cblk->data)) { + if (ret > cblk->data_allocated) { + size_t new_size = FFMAX(2*cblk->data_allocated, ret); + void *new = av_realloc(cblk->data, new_size); + if (new) { + cblk->data = new; + cblk->data_allocated = new_size; + } + } + if (ret > cblk->data_allocated) { avpriv_request_sample(s->avctx, "Block with lengthinc greater than %"SIZE_SPECIFIER"", - sizeof(cblk->data)); + cblk->data_allocated); return AVERROR_PATCHWELCOME; } cblk->lengthinc[cblk->nb_lengthinc++] = ret; @@ -1029,9 +1053,19 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, nb_code_blocks = prec->nb_codeblocks_height * prec->nb_codeblocks_width; for (cblkno = 0; cblkno < nb_code_blocks; cblkno++) { Jpeg2000Cblk *cblk = prec->cblk + cblkno; + if (!cblk->nb_terminationsinc && !cblk->lengthinc) + continue; for (cwsno = 0; cwsno < cblk->nb_lengthinc; cwsno ++) { + if (cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4) { + size_t new_size = FFMAX(2*cblk->data_allocated, cblk->length + cblk->lengthinc[cwsno] + 4); + void *new = av_realloc(cblk->data, new_size); + if (new) { + cblk->data = new; + cblk->data_allocated = new_size; + } + } if ( bytestream2_get_bytes_left(&s->g) < cblk->lengthinc[cwsno] - || sizeof(cblk->data) < cblk->length + cblk->lengthinc[cwsno] + 4 + || cblk->data_allocated < cblk->length + cblk->lengthinc[cwsno] + 4 ) { av_log(s->avctx, AV_LOG_ERROR, "Block length %"PRIu16" or lengthinc %d is too large, left %d\n", @@ -1050,6 +1084,7 @@ static int jpeg2000_decode_packet(Jpeg2000DecoderContext *s, Jpeg2000Tile *tile, cblk->data_start[cblk->nb_terminations] = cblk->length; } } + av_freep(&cblk->lengthinc); } } return 0; @@ -1127,6 +1162,9 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2 step_x = 32; step_y = 32; + if (RSpoc > FFMIN(codsty->nreslevels, REpoc)) + continue; + for (reslevelno = RSpoc; reslevelno < FFMIN(codsty->nreslevels, REpoc); reslevelno++) { uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; @@ -1146,10 +1184,10 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2 int xc = x / s->cdx[compno]; int yc = y / s->cdy[compno]; - if (yc % (1 << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check + if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check continue; - if (xc % (1 << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check + if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check continue; // check if a precinct exists @@ -1216,10 +1254,10 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2 if (reslevelno >= codsty->nreslevels) continue; - if (yc % (1 << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check + if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check continue; - if (xc % (1 << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check + if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check continue; // check if a precinct exists @@ -1287,10 +1325,10 @@ static int jpeg2000_decode_packets_po_iteration(Jpeg2000DecoderContext *s, Jpeg2 uint8_t reducedresno = codsty->nreslevels - 1 -reslevelno; // ==> N_L - r Jpeg2000ResLevel *rlevel = comp->reslevel + reslevelno; - if (yc % (1 << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check + if (yc % (1LL << (rlevel->log2_prec_height + reducedresno)) && y != tile->coord[1][0]) //FIXME this is a subset of the check continue; - if (xc % (1 << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check + if (xc % (1LL << (rlevel->log2_prec_width + reducedresno)) && x != tile->coord[0][0]) //FIXME this is a subset of the check continue; // check if a precinct exists @@ -1981,7 +2019,16 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) bytestream2_get_bytes_left(&s->g) >= 8) { atom_size = bytestream2_get_be32u(&s->g); atom = bytestream2_get_be32u(&s->g); - atom_end = bytestream2_tell(&s->g) + atom_size - 8; + if (atom_size == 1) { + if (bytestream2_get_be32u(&s->g)) { + avpriv_request_sample(s->avctx, "Huge atom"); + return 0; + } + atom_size = bytestream2_get_be32u(&s->g); + atom_end = bytestream2_tell(&s->g) + atom_size - 16; + } else { + atom_end = bytestream2_tell(&s->g) + atom_size - 8; + } if (atom == JP2_CODESTREAM) return 1; @@ -2009,7 +2056,6 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) } } else if (atom2 == MKBETAG('p','c','l','r') && atom2_size >= 6) { int i, size, colour_count, colour_channels, colour_depth[3]; - uint32_t r, g, b; colour_count = bytestream2_get_be16u(&s->g); colour_channels = bytestream2_get_byteu(&s->g); // FIXME: Do not ignore channel_sign @@ -2019,7 +2065,7 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) size = (colour_depth[0] + 7 >> 3) * colour_count + (colour_depth[1] + 7 >> 3) * colour_count + (colour_depth[2] + 7 >> 3) * colour_count; - if (colour_count > 256 || + if (colour_count > AVPALETTE_COUNT || colour_channels != 3 || colour_depth[0] > 16 || colour_depth[1] > 16 || @@ -2031,6 +2077,7 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) } s->pal8 = 1; for (i = 0; i < colour_count; i++) { + uint32_t r, g, b; if (colour_depth[0] <= 8) { r = bytestream2_get_byteu(&s->g) << 8 - colour_depth[0]; r |= r >> colour_depth[0]; @@ -2105,10 +2152,18 @@ static int jp2_find_codestream(Jpeg2000DecoderContext *s) return 0; } +static av_cold void jpeg2000_init_static_data(void) +{ + ff_jpeg2000_init_tier1_luts(); + ff_mqc_init_context_tables(); +} + static av_cold int jpeg2000_decode_init(AVCodecContext *avctx) { + static AVOnce init_static_once = AV_ONCE_INIT; Jpeg2000DecoderContext *s = avctx->priv_data; + ff_thread_once(&init_static_once, jpeg2000_init_static_data); ff_jpeg2000dsp_init(&s->dsp); return 0; @@ -2186,12 +2241,6 @@ end: return ret; } -static av_cold void jpeg2000_init_static_data(AVCodec *codec) -{ - ff_jpeg2000_init_tier1_luts(); - ff_mqc_init_context_tables(); -} - #define OFFSET(x) offsetof(Jpeg2000DecoderContext, x) #define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM @@ -2215,7 +2264,6 @@ AVCodec ff_jpeg2000_decoder = { .id = AV_CODEC_ID_JPEG2000, .capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS | AV_CODEC_CAP_DR1, .priv_data_size = sizeof(Jpeg2000DecoderContext), - .init_static_data = jpeg2000_init_static_data, .init = jpeg2000_decode_init, .decode = jpeg2000_decode_frame, .priv_class = &jpeg2000_class,