@@ -644,7 +644,7 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
644
644
j2k_unpacker_t unpack = NULL ;
645
645
size_t buffer_size = 0 , tile_bytes = 0 ;
646
646
unsigned n , tile_height , tile_width ;
647
- int components ;
647
+ int total_component_width = 0 ;
648
648
649
649
stream = opj_stream_create (BUFFER_SIZE , OPJ_TRUE );
650
650
@@ -814,23 +814,40 @@ j2k_decode_entry(Imaging im, ImagingCodecState state) {
814
814
goto quick_exit ;
815
815
}
816
816
817
+ if (tile_info .nb_comps != image -> numcomps ) {
818
+ state -> errcode = IMAGING_CODEC_BROKEN ;
819
+ state -> state = J2K_STATE_FAILED ;
820
+ goto quick_exit ;
821
+ }
822
+
817
823
/* Sometimes the tile_info.datasize we get back from openjpeg
818
- is less than numcomps *w*h, and we overflow in the
824
+ is less than sum(comp_bytes) *w*h, and we overflow in the
819
825
shuffle stage */
820
826
821
827
tile_width = tile_info .x1 - tile_info .x0 ;
822
828
tile_height = tile_info .y1 - tile_info .y0 ;
823
- components = tile_info .nb_comps == 3 ? 4 : tile_info .nb_comps ;
824
- if ((tile_width > UINT_MAX / components ) ||
825
- (tile_height > UINT_MAX / components ) ||
826
- (tile_width > UINT_MAX / (tile_height * components )) ||
827
- (tile_height > UINT_MAX / (tile_width * components ))) {
829
+
830
+ /* Total component width = sum (component_width) e.g, it's
831
+ legal for an la file to have a 1 byte width for l, and 4 for
832
+ a. and then a malicious file could have a smaller tile_bytes
833
+ */
834
+
835
+ for (n = 0 ; n < tile_info .nb_comps ; n ++ ) {
836
+ // see csize /acsize calcs
837
+ int csize = (image -> comps [n ].prec + 7 ) >> 3 ;
838
+ csize = (csize == 3 ) ? 4 : csize ;
839
+ total_component_width += csize ;
840
+ }
841
+ if ((tile_width > UINT_MAX / total_component_width ) ||
842
+ (tile_height > UINT_MAX / total_component_width ) ||
843
+ (tile_width > UINT_MAX / (tile_height * total_component_width )) ||
844
+ (tile_height > UINT_MAX / (tile_width * total_component_width ))) {
828
845
state -> errcode = IMAGING_CODEC_BROKEN ;
829
846
state -> state = J2K_STATE_FAILED ;
830
847
goto quick_exit ;
831
848
}
832
849
833
- tile_bytes = tile_width * tile_height * components ;
850
+ tile_bytes = tile_width * tile_height * total_component_width ;
834
851
835
852
if (tile_bytes > tile_info .data_size ) {
836
853
tile_info .data_size = tile_bytes ;
0 commit comments