X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fj2kdec.c;h=2cbd7cc529aea902170de922087bb6fee82a9ba7;hb=dd3ca3ea15392da8636c06764e2da31e6ca700f0;hp=73af6a73df1bb97a39a20f514b3c094cd79f8f52;hpb=3c54e7ed4f42d8ed5aece9484190b5294e272c36;p=ffmpeg diff --git a/libavcodec/j2kdec.c b/libavcodec/j2kdec.c index 73af6a73df1..2cbd7cc529a 100644 --- a/libavcodec/j2kdec.c +++ b/libavcodec/j2kdec.c @@ -64,9 +64,9 @@ typedef struct { J2kCodingStyle codsty[4]; J2kQuantStyle qntsty[4]; - uint8_t *buf_start; - uint8_t *buf; - uint8_t *buf_end; + const uint8_t *buf_start; + const uint8_t *buf; + const uint8_t *buf_end; int bit_index; int16_t curtileno; @@ -220,6 +220,9 @@ static int get_siz(J2kDecoderContext *s) s->tile_offset_y = bytestream_get_be32(&s->buf); // YT0Siz s->ncomponents = bytestream_get_be16(&s->buf); // CSiz + if(s->tile_width<=0 || s->tile_height<=0) + return AVERROR(EINVAL); + if (s->buf_end - s->buf < 2 * s->ncomponents) return AVERROR(EINVAL); @@ -227,7 +230,7 @@ static int get_siz(J2kDecoderContext *s) uint8_t x = bytestream_get_byte(&s->buf); s->cbps[i] = (x & 0x7f) + 1; s->precision = FFMAX(s->cbps[i], s->precision); - s->sgnd[i] = (x & 0x80) == 1; + s->sgnd[i] = !!(x & 0x80); s->cdx[i] = bytestream_get_byte(&s->buf); s->cdy[i] = bytestream_get_byte(&s->buf); } @@ -235,6 +238,9 @@ static int get_siz(J2kDecoderContext *s) s->numXtiles = ff_j2k_ceildiv(s->width - s->tile_offset_x, s->tile_width); s->numYtiles = ff_j2k_ceildiv(s->height - s->tile_offset_y, s->tile_height); + if(s->numXtiles * (uint64_t)s->numYtiles > INT_MAX/sizeof(J2kTile)) + return AVERROR(EINVAL); + s->tile = av_mallocz(s->numXtiles * s->numYtiles * sizeof(J2kTile)); if (!s->tile) return AVERROR(ENOMEM); @@ -268,7 +274,7 @@ static int get_siz(J2kDecoderContext *s) if ((ret = s->avctx->get_buffer(s->avctx, &s->picture)) < 0) return ret; - s->picture.pict_type = FF_I_TYPE; + s->picture.pict_type = AV_PICTURE_TYPE_I; s->picture.key_frame = 1; return 0; @@ -359,7 +365,7 @@ static int get_qcx(J2kDecoderContext *s, int n, J2kQuantStyle *q) if (q->quantsty == J2K_QSTY_NONE){ n -= 3; - if (s->buf_end - s->buf < n) + if (s->buf_end - s->buf < n || 32*3 < n) return AVERROR(EINVAL); for (i = 0; i < n; i++) q->expn[i] = bytestream_get_byte(&s->buf) >> 3; @@ -376,7 +382,7 @@ static int get_qcx(J2kDecoderContext *s, int n, J2kQuantStyle *q) } } else{ n = (n - 3) >> 1; - if (s->buf_end - s->buf < n) + if (s->buf_end - s->buf < n || 32*3 < n) return AVERROR(EINVAL); for (i = 0; i < n; i++){ x = bytestream_get_be16(&s->buf); @@ -421,6 +427,10 @@ static uint8_t get_sot(J2kDecoderContext *s) return AVERROR(EINVAL); s->curtileno = bytestream_get_be16(&s->buf); ///< Isot + if((unsigned)s->curtileno >= s->numXtiles * s->numYtiles){ + s->curtileno=0; + return AVERROR(EINVAL); + } s->buf += 4; ///< Psot (ignored) @@ -701,9 +711,9 @@ static int decode_cblk(J2kDecoderContext *s, J2kCodingStyle *codsty, J2kT1Contex for (y = 0; y < height; y++) memset(t1->data[y], 0, width*sizeof(int)); - ff_mqc_initdec(&t1->mqc, cblk->data); cblk->data[cblk->length] = 0xff; cblk->data[cblk->length+1] = 0xff; + ff_mqc_initdec(&t1->mqc, cblk->data); while(passno--){ switch(pass_t){ @@ -903,13 +913,15 @@ static int decode_codestream(J2kDecoderContext *s) for (;;){ int marker, len, ret = 0; - uint8_t *oldbuf; + const uint8_t *oldbuf; if (s->buf_end - s->buf < 2){ av_log(s->avctx, AV_LOG_ERROR, "Missing EOC\n"); break; } marker = bytestream_get_be16(&s->buf); + if(s->avctx->debug & FF_DEBUG_STARTCODE) + av_log(s->avctx, AV_LOG_DEBUG, "marker 0x%.4X at pos 0x%tx\n", marker, s->buf - s->buf_start - 4); oldbuf = s->buf; if (marker == J2K_SOD){ @@ -948,7 +960,7 @@ static int decode_codestream(J2kDecoderContext *s) // the comment is ignored s->buf += len - 2; break; default: - av_log(s->avctx, AV_LOG_ERROR, "unsupported marker 0x%.4X at pos 0x%x\n", marker, s->buf - s->buf_start - 4); + av_log(s->avctx, AV_LOG_ERROR, "unsupported marker 0x%.4X at pos 0x%tx\n", marker, s->buf - s->buf_start - 4); s->buf += len - 2; break; } if (s->buf - oldbuf != len || ret){ @@ -961,18 +973,20 @@ static int decode_codestream(J2kDecoderContext *s) static int jp2_find_codestream(J2kDecoderContext *s) { - int32_t atom_size; + uint32_t atom_size; int found_codestream = 0, search_range = 10; // skip jpeg2k signature atom s->buf += 12; - while(!found_codestream && search_range) { + while(!found_codestream && search_range && s->buf_end - s->buf >= 8) { atom_size = AV_RB32(s->buf); if(AV_RB32(s->buf + 4) == JP2_CODESTREAM) { found_codestream = 1; s->buf += 8; } else { + if (s->buf_end - s->buf < atom_size) + return 0; s->buf += atom_size; search_range--; } @@ -1005,7 +1019,8 @@ static int decode_frame(AVCodecContext *avctx, return AVERROR(EINVAL); // check if the image is in jp2 format - if((AV_RB32(s->buf) == 12) && (AV_RB32(s->buf + 4) == JP2_SIG_TYPE) && + if(s->buf_end - s->buf >= 12 && + (AV_RB32(s->buf) == 12) && (AV_RB32(s->buf + 4) == JP2_SIG_TYPE) && (AV_RB32(s->buf + 8) == JP2_SIG_VALUE)) { if(!jp2_find_codestream(s)) { av_log(avctx, AV_LOG_ERROR, "couldn't find jpeg2k codestream atom\n"); @@ -1053,15 +1068,15 @@ static av_cold int decode_end(AVCodecContext *avctx) } AVCodec ff_jpeg2000_decoder = { - "j2k", - AVMEDIA_TYPE_VIDEO, - CODEC_ID_JPEG2000, - sizeof(J2kDecoderContext), - j2kdec_init, - NULL, - decode_end, - decode_frame, + .name = "j2k", + .type = AVMEDIA_TYPE_VIDEO, + .id = CODEC_ID_JPEG2000, + .priv_data_size = sizeof(J2kDecoderContext), + .init = j2kdec_init, + .close = decode_end, + .decode = decode_frame, .capabilities = CODEC_CAP_EXPERIMENTAL, + .long_name = NULL_IF_CONFIG_SMALL("JPEG 2000"), .pix_fmts = - (enum PixelFormat[]) {PIX_FMT_GRAY8, PIX_FMT_RGB24, -1} + (enum PixelFormat[]) {PIX_FMT_GRAY8, PIX_FMT_RGB24, PIX_FMT_NONE} };