@@ -110,6 +110,7 @@ j2ku_gray_l(opj_image_t *in, const JPEG2KTILEINFO *tileinfo,
110110 if (shift < 0 )
111111 offset += 1 << (- shift - 1 );
112112
113+ /* csiz*h*w + offset = tileinfo.datasize */
113114 switch (csiz ) {
114115 case 1 :
115116 for (y = 0 ; y < h ; ++ y ) {
@@ -557,8 +558,10 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
557558 opj_dparameters_t params ;
558559 OPJ_COLOR_SPACE color_space ;
559560 j2k_unpacker_t unpack = NULL ;
560- size_t buffer_size = 0 ;
561- unsigned n ;
561+ size_t buffer_size = 0 , tile_bytes = 0 ;
562+ unsigned n , tile_height , tile_width ;
563+ int components ;
564+
562565
563566 stream = opj_stream_create (BUFFER_SIZE , OPJ_TRUE );
564567
@@ -703,8 +706,44 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
703706 tile_info .x1 = (tile_info .x1 + correction ) >> context -> reduce ;
704707 tile_info .y1 = (tile_info .y1 + correction ) >> context -> reduce ;
705708
709+ /* Check the tile bounds; if the tile is outside the image area,
710+ or if it has a negative width or height (i.e. the coordinates are
711+ swapped), bail. */
712+ if (tile_info .x0 >= tile_info .x1
713+ || tile_info .y0 >= tile_info .y1
714+ || tile_info .x0 < image -> x0
715+ || tile_info .y0 < image -> y0
716+ || tile_info .x1 - image -> x0 > im -> xsize
717+ || tile_info .y1 - image -> y0 > im -> ysize ) {
718+ state -> errcode = IMAGING_CODEC_BROKEN ;
719+ state -> state = J2K_STATE_FAILED ;
720+ goto quick_exit ;
721+ }
722+
723+ /* Sometimes the tile_info.datasize we get back from openjpeg
724+ is less than numcomps*w*h, and we overflow in the
725+ shuffle stage */
726+
727+ tile_width = tile_info .x1 - tile_info .x0 ;
728+ tile_height = tile_info .y1 - tile_info .y0 ;
729+ components = tile_info .nb_comps == 3 ? 4 : tile_info .nb_comps ;
730+ if (( tile_width > UINT_MAX / components ) ||
731+ ( tile_height > UINT_MAX / components ) ||
732+ ( tile_width > UINT_MAX / (tile_height * components )) ||
733+ ( tile_height > UINT_MAX / (tile_width * components ))) {
734+ state -> errcode = IMAGING_CODEC_BROKEN ;
735+ state -> state = J2K_STATE_FAILED ;
736+ goto quick_exit ;
737+ }
738+
739+ tile_bytes = tile_width * tile_height * components ;
740+
741+ if (tile_bytes > tile_info .data_size ) {
742+ tile_info .data_size = tile_bytes ;
743+ }
744+
706745 if (buffer_size < tile_info .data_size ) {
707- /* malloc check ok, tile_info.data_size from openjpeg */
746+ /* malloc check ok, overflow and tile size sanity check above */
708747 UINT8 * new = realloc (state -> buffer , tile_info .data_size );
709748 if (!new ) {
710749 state -> errcode = IMAGING_CODEC_MEMORY ;
@@ -715,6 +754,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
715754 buffer_size = tile_info .data_size ;
716755 }
717756
757+
718758 if (!opj_decode_tile_data (codec ,
719759 tile_info .tile_index ,
720760 (OPJ_BYTE * )state -> buffer ,
@@ -725,20 +765,6 @@ j2k_decode_entry(Imaging im, ImagingCodecState state)
725765 goto quick_exit ;
726766 }
727767
728- /* Check the tile bounds; if the tile is outside the image area,
729- or if it has a negative width or height (i.e. the coordinates are
730- swapped), bail. */
731- if (tile_info .x0 >= tile_info .x1
732- || tile_info .y0 >= tile_info .y1
733- || tile_info .x0 < image -> x0
734- || tile_info .y0 < image -> y0
735- || tile_info .x1 - image -> x0 > im -> xsize
736- || tile_info .y1 - image -> y0 > im -> ysize ) {
737- state -> errcode = IMAGING_CODEC_BROKEN ;
738- state -> state = J2K_STATE_FAILED ;
739- goto quick_exit ;
740- }
741-
742768 unpack (image , & tile_info , state -> buffer , im );
743769 }
744770
0 commit comments