Merge pull request #529 from renevanderark/master
[openjpeg.git] / src / lib / openjp2 / j2k.c
index daa63a0ee2895202eb18b1e435c2b474c19a934b..ee988b6d5716e35dc8622f0c7b09457dddcdf691 100644 (file)
@@ -353,8 +353,6 @@ static void opj_get_tile_dimensions(opj_image_t * l_image,
 static void opj_j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data);
 
 static OPJ_BOOL opj_j2k_post_write_tile (opj_j2k_t * p_j2k,
-                                                                             OPJ_BYTE * p_data,
-                                                                             OPJ_UINT32 p_data_size,
                                                                              opj_stream_private_t *p_stream,
                                                                              opj_event_mgr_t * p_manager );
 
@@ -782,12 +780,32 @@ static OPJ_BOOL opj_j2k_write_sot(      opj_j2k_t *p_j2k,
                                                                         opj_event_mgr_t * p_manager );
 
 /**
- * Reads a PPT marker (Packed packet headers, tile-part header)
+ * Reads values from a SOT marker (Start of tile-part)
  *
- * @param       p_header_data   the data contained in the PPT box.
- * @param       p_j2k                   the jpeg2000 codec.
+ * the j2k decoder state is not affected. No side effects, no checks except for p_header_size.
+ *
+ * @param       p_header_data   the data contained in the SOT marker.
+ * @param       p_header_size   the size of the data contained in the SOT marker.
+ * @param       p_tile_no       Isot.
+ * @param       p_tot_len       Psot.
+ * @param       p_current_part  TPsot.
+ * @param       p_num_parts     TNsot.
+ * @param       p_manager       the user event manager.
+ */
+static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE *  p_header_data,
+                                                                                                                                                        OPJ_UINT32  p_header_size,
+                                                                                                                                                        OPJ_UINT32* p_tile_no,
+                                                                                                                                                        OPJ_UINT32* p_tot_len,
+                                                                                                                                                        OPJ_UINT32* p_current_part,
+                                                                                                                                                        OPJ_UINT32* p_num_parts,
+                                                                                                                                                        opj_event_mgr_t * p_manager );
+/**
+ * Reads a SOT marker (Start of tile-part)
+ *
+ * @param       p_header_data   the data contained in the SOT marker.
+ * @param       p_j2k           the jpeg2000 codec.
  * @param       p_header_size   the size of the data contained in the PPT marker.
- * @param       p_manager               the user event manager.
+ * @param       p_manager       the user event manager.
 */
 static OPJ_BOOL opj_j2k_read_sot (  opj_j2k_t *p_j2k,
                                     OPJ_BYTE * p_header_data,
@@ -1181,6 +1199,18 @@ static void opj_j2k_set_cinema_parameters(opj_cparameters_t *parameters, opj_ima
 
 static OPJ_BOOL opj_j2k_is_cinema_compliant(opj_image_t *image, OPJ_UINT16 rsiz, opj_event_mgr_t *p_manager);
 
+/**
+ * Checks for invalid number of tile-parts in SOT marker (TPsot==TNsot). See issue 254.
+ *
+ * @param       p_stream            the stream to read data from.
+ * @param       tile_no             tile number we're looking for.
+ * @param       p_correction_needed output value. if true, non conformant codestream needs TNsot correction.
+ * @param       p_manager       the user event manager.
+ *
+ * @return true if the function was successful, false else.
+ */
+static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, opj_event_mgr_t * p_manager );
+
 /*@}*/
 
 /*@}*/
@@ -1921,7 +1951,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         OPJ_UINT32 l_nb_comp_remain;
         OPJ_UINT32 l_remaining_size;
         OPJ_UINT32 l_nb_tiles;
-        OPJ_UINT32 l_tmp;
+        OPJ_UINT32 l_tmp, l_tx1, l_ty1;
         opj_image_t *l_image = 00;
         opj_cp_t *l_cp = 00;
         opj_image_comp_t * l_img_comp = 00;
@@ -1983,8 +2013,9 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         }
 
         /* testcase 4035.pdf.SIGSEGV.d8b.3375 */
-        if (l_image->x0 > l_image->x1 || l_image->y0 > l_image->y1) {
-                opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0);
+        /* testcase issue427-null-image-size.jp2 */
+        if ((l_image->x0 >= l_image->x1) || (l_image->y0 >= l_image->y1)) {
+                opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: negative or zero image size (%d x %d)\n", l_image->x1 - l_image->x0, l_image->y1 - l_image->y0);
                 return OPJ_FALSE;
         }
         /* testcase 2539.pdf.SIGFPE.706.1712 (also 3622.pdf.SIGFPE.706.2916 and 4008.pdf.SIGFPE.706.3345 and maybe more) */
@@ -1999,6 +2030,14 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                 return OPJ_FALSE;
         }
 
+        /* testcase issue427-illegal-tile-offset.jp2 */
+        l_tx1 = opj_uint_adds(l_cp->tx0, l_cp->tdx); /* manage overflow */
+        l_ty1 = opj_uint_adds(l_cp->ty0, l_cp->tdy); /* manage overflow */
+        if ((l_cp->tx0 > l_image->x0) || (l_cp->ty0 > l_image->y0) || (l_tx1 <= l_image->x0) || (l_ty1 <= l_image->y0) ) {
+                opj_event_msg(p_manager, EVT_ERROR, "Error with SIZ marker: illegal tile offset\n");
+                return OPJ_FALSE;
+        }
+
 #ifdef USE_JPWL
         if (l_cp->correct) {
                 /* if JPWL is on, we check whether TX errors have damaged
@@ -2418,7 +2457,14 @@ static OPJ_BOOL opj_j2k_read_cod (  opj_j2k_t *p_j2k,
         l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH) ?
                                 &l_cp->tcps[p_j2k->m_current_tile_number] :
                                 p_j2k->m_specific_param.m_decoder.m_default_tcp;
-
+       
+        /* Only one COD per tile */
+        if (l_tcp->cod) {
+                opj_event_msg(p_manager, EVT_ERROR, "COD marker already read. No more than one COD marker per tile.\n");
+                return OPJ_FALSE;
+        }
+        l_tcp->cod = 1;
+       
         /* Make sure room is sufficient */
         if (p_header_size < 5) {
                 opj_event_msg(p_manager, EVT_ERROR, "Error reading COD marker\n");
@@ -2442,6 +2488,11 @@ static OPJ_BOOL opj_j2k_read_cod (  opj_j2k_t *p_j2k,
         }
         opj_read_bytes(p_header_data,&l_tcp->numlayers,2);      /* SGcod (B) */
         p_header_data+=2;
+       
+        if ((l_tcp->numlayers < 1U) || (l_tcp->numlayers > 65535U)) {
+                opj_event_msg(p_manager, EVT_ERROR, "Invalid number of layers in COD marker : %d not in range [1-65535]\n", l_tcp->numlayers);
+                return OPJ_FALSE;
+        }
 
         /* If user didn't set a number layer to decode take the max specify in the codestream. */
         if      (l_cp->m_specific_param.m_dec.m_layer) {
@@ -3993,6 +4044,35 @@ OPJ_BOOL opj_j2k_write_sot(     opj_j2k_t *p_j2k,
         return OPJ_TRUE;
 }
 
+static OPJ_BOOL opj_j2k_get_sot_values(OPJ_BYTE *  p_header_data,
+                                                                                                                                                        OPJ_UINT32  p_header_size,
+                                                                                                                                                        OPJ_UINT32* p_tile_no,
+                                                                                                                                                        OPJ_UINT32* p_tot_len,
+                                                                                                                                                        OPJ_UINT32* p_current_part,
+                                                                                                                                                        OPJ_UINT32* p_num_parts,
+                                                                                                                                                        opj_event_mgr_t * p_manager )
+{
+       /* preconditions */
+       assert(p_header_data != 00);
+       assert(p_manager != 00);
+       
+       /* Size of this marker is fixed = 12 (we have already read marker and its size)*/
+       if (p_header_size != 8) {
+               opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n");
+               return OPJ_FALSE;
+       }
+       
+       opj_read_bytes(p_header_data,p_tile_no,2);      /* Isot */
+       p_header_data+=2;
+       opj_read_bytes(p_header_data,p_tot_len,4);      /* Psot */
+       p_header_data+=4;
+       opj_read_bytes(p_header_data,p_current_part,1); /* TPsot */
+       ++p_header_data;
+       opj_read_bytes(p_header_data,p_num_parts ,1);   /* TNsot */
+       ++p_header_data;
+       return OPJ_TRUE;
+}
+
 OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k,
                             OPJ_BYTE * p_header_data,
                             OPJ_UINT32 p_header_size,
@@ -4005,19 +4085,16 @@ OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k,
         OPJ_UINT32 l_tile_x,l_tile_y;
 
         /* preconditions */
-        assert(p_header_data != 00);
+       
         assert(p_j2k != 00);
         assert(p_manager != 00);
-
-        /* Size of this marker is fixed = 12 (we have already read marker and its size)*/
-        if (p_header_size != 8) {
+       
+        if (! opj_j2k_get_sot_values(p_header_data, p_header_size, &(p_j2k->m_current_tile_number), &l_tot_len, &l_current_part, &l_num_parts, p_manager)) {
                 opj_event_msg(p_manager, EVT_ERROR, "Error reading SOT marker\n");
                 return OPJ_FALSE;
         }
 
         l_cp = &(p_j2k->m_cp);
-        opj_read_bytes(p_header_data,&(p_j2k->m_current_tile_number),2);                /* Isot */
-        p_header_data+=2;
 
         /* testcase 2.pdf.SIGFPE.706.1112 */
         if (p_j2k->m_current_tile_number >= l_cp->tw * l_cp->th) {
@@ -4060,9 +4137,6 @@ OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k,
         /* Optimization possible here with a more complex data structure and with the removing of tiles */
         /* since the time taken by this function can only grow at the time */
 
-        opj_read_bytes(p_header_data,&l_tot_len,4);             /* Psot */
-        p_header_data+=4;
-
         /* PSot should be equal to zero or >=14 or <= 2^32-1 */
         if ((l_tot_len !=0 ) && (l_tot_len < 14) )
         {
@@ -4105,13 +4179,8 @@ OPJ_BOOL opj_j2k_read_sot ( opj_j2k_t *p_j2k,
                         p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1;
                 }
 
-                opj_read_bytes(p_header_data,&l_current_part ,1);       /* TPsot */
-                ++p_header_data;
-
-                opj_read_bytes(p_header_data,&l_num_parts ,1);          /* TNsot */
-                ++p_header_data;
-
                 if (l_num_parts != 0) { /* Number of tile-part header is provided by this tile-part header */
+                        l_num_parts += p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction;
                         /* Useful to manage the case of textGBR.jp2 file because two values of TNSot are allowed: the correct numbers of
                          * tile-parts for that tile and zero (A.4.2 of 15444-1 : 2002). */
                         if (l_tcp->m_nb_tile_parts) {
@@ -5223,6 +5292,7 @@ static OPJ_BOOL opj_j2k_read_mct (      opj_j2k_t *p_j2k,
                 }
 
                 l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records;
+                ++l_tcp->m_nb_mct_records;
         }
 
         if (l_mct_data->m_data) {
@@ -5251,7 +5321,6 @@ static OPJ_BOOL opj_j2k_read_mct (      opj_j2k_t *p_j2k,
         memcpy(l_mct_data->m_data,p_header_data,p_header_size);
 
         l_mct_data->m_data_size = p_header_size;
-        ++l_tcp->m_nb_mct_records;
 
         return OPJ_TRUE;
 }
@@ -6573,7 +6642,7 @@ OPJ_BOOL opj_j2k_setup_encoder(     opj_j2k_t *p_j2k,
                     }
                 }
                 else {
-                    if(tcp->mct==1 && image->numcomps == 3) { /* RGB->YCC MCT is enabled */
+                    if(tcp->mct==1 && image->numcomps >= 3) { /* RGB->YCC MCT is enabled */
                         if ((image->comps[0].dx != image->comps[1].dx) ||
                                 (image->comps[0].dx != image->comps[2].dx) ||
                                 (image->comps[0].dy != image->comps[1].dy) ||
@@ -7061,21 +7130,20 @@ OPJ_BOOL opj_j2k_encoding_validation (  opj_j2k_t * p_j2k,
         /* make sure a validation list is present */
         l_is_valid &= (p_j2k->m_validation_list != 00);
 
-             /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */
-             /* 33 (32) would always fail the 2 checks below (if a cast to 64bits was done) */
-             /* 32 (31) would always fail the 2 checks below (if a cast to 64bits was done) */
-        /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 31 ? */
-        if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 31)) {
+        /* ISO 15444-1:2004 states between 1 & 33 (0 -> 32) */
+        /* 33 (32) would always fail the check below (if a cast to 64bits was done) */
+        /* FIXME Shall we change OPJ_J2K_MAXRLVLS to 32 ? */
+        if ((p_j2k->m_cp.tcps->tccps->numresolutions <= 0) || (p_j2k->m_cp.tcps->tccps->numresolutions > 32)) {
                 opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
                 return OPJ_FALSE;
         }
 
-        if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+        if ((p_j2k->m_cp.tdx) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) {
                 opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
                 return OPJ_FALSE;
         }
 
-        if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << p_j2k->m_cp.tcps->tccps->numresolutions)) {
+        if ((p_j2k->m_cp.tdy) < (OPJ_UINT32) (1 << (p_j2k->m_cp.tcps->tccps->numresolutions - 1U))) {
                 opj_event_msg(p_manager, EVT_ERROR, "Number of resolutions is too high in comparison to the size of tiles\n");
                 return OPJ_FALSE;
         }
@@ -7153,7 +7221,7 @@ OPJ_BOOL opj_j2k_read_header_procedure( opj_j2k_t *p_j2k,
 
                 /* Check if the current marker ID is valid */
                 if (l_current_marker < 0xff00) {
-                        opj_event_msg(p_manager, EVT_ERROR, "We expected read a marker ID (0xff--) instead of %.8x\n", l_current_marker);
+                        opj_event_msg(p_manager, EVT_ERROR, "A marker ID was expected (0xff--) instead of %.8x\n", l_current_marker);
                         return OPJ_FALSE;
                 }
 
@@ -7338,8 +7406,15 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd (       opj_j2k_t * p_j2
                 /*Copy default coding parameters into the current tile coding parameters*/
                 memcpy(l_tcp, l_default_tcp, sizeof(opj_tcp_t));
                 /* Initialize some values of the current tile coding parameters*/
+                l_tcp->cod = 0;
                 l_tcp->ppt = 0;
                 l_tcp->ppt_data = 00;
+                /* Remove memory not owned by this tile in case of early error return. */
+                l_tcp->m_mct_decoding_matrix = 00;
+                l_tcp->m_nb_max_mct_records = 0;
+                l_tcp->m_mct_records = 00;
+                l_tcp->m_nb_max_mcc_records = 0;
+                l_tcp->m_mcc_records = 00;
                 /* Reconnect the tile-compo coding parameters pointer to the current tile coding parameters*/
                 l_tcp->tccps = l_current_tccp;
 
@@ -7377,6 +7452,8 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd (       opj_j2k_t * p_j2
 
                         ++l_src_mct_rec;
                         ++l_dest_mct_rec;
+                        /* Update with each pass to free exactly what has been allocated on early return. */
+                        l_tcp->m_nb_max_mct_records += 1;
                 }
 
                 /* Get the mcc_record of the dflt_tile_cp and copy them into the current tile cp*/
@@ -7386,6 +7463,7 @@ static OPJ_BOOL opj_j2k_copy_default_tcp_and_create_tcd (       opj_j2k_t * p_j2
                         return OPJ_FALSE;
                 }
                 memcpy(l_tcp->m_mcc_records,l_default_tcp->m_mcc_records,l_mcc_records_size);
+                l_tcp->m_nb_max_mcc_records = l_default_tcp->m_nb_max_mcc_records;
 
                 /* Copy the mcc record data from dflt_tile_cp to the current tile*/
                 l_src_mcc_rec = l_default_tcp->m_mcc_records;
@@ -7646,6 +7724,104 @@ void opj_j2k_cp_destroy (opj_cp_t *p_cp)
         }
 }
 
+static OPJ_BOOL opj_j2k_need_nb_tile_parts_correction(opj_stream_private_t *p_stream, OPJ_UINT32 tile_no, OPJ_BOOL* p_correction_needed, opj_event_mgr_t * p_manager )
+{
+       OPJ_BYTE   l_header_data[10];
+       OPJ_OFF_T  l_stream_pos_backup;
+       OPJ_UINT32 l_current_marker;
+       OPJ_UINT32 l_marker_size;
+       OPJ_UINT32 l_tile_no, l_tot_len, l_current_part, l_num_parts;
+       
+       /* initialize to no correction needed */
+       *p_correction_needed = OPJ_FALSE;
+       
+       l_stream_pos_backup = opj_stream_tell(p_stream);
+       if (l_stream_pos_backup == -1) {
+               /* let's do nothing */
+               return OPJ_TRUE;
+       }
+       
+       for (;;) {
+               /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
+               if (opj_stream_read_data(p_stream,l_header_data, 2, p_manager) != 2) {
+                       /* assume all is OK */
+                       if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+                               return OPJ_FALSE;
+                       }
+                       return OPJ_TRUE;
+               }
+               
+               /* Read 2 bytes from buffer as the new marker ID */
+               opj_read_bytes(l_header_data, &l_current_marker, 2);
+               
+               if (l_current_marker != J2K_MS_SOT) {
+                       /* assume all is OK */
+                       if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+                               return OPJ_FALSE;
+                       }
+                       return OPJ_TRUE;
+               }
+               
+               /* Try to read 2 bytes (the marker size) from stream and copy them into the buffer */
+               if (opj_stream_read_data(p_stream, l_header_data, 2, p_manager) != 2) {
+                       opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
+                       return OPJ_FALSE;
+               }
+               
+               /* Read 2 bytes from the buffer as the marker size */
+               opj_read_bytes(l_header_data, &l_marker_size, 2);
+               
+               /* Check marker size for SOT Marker */
+               if (l_marker_size != 10) {
+                       opj_event_msg(p_manager, EVT_ERROR, "Inconsistent marker size\n");
+                       return OPJ_FALSE;
+               }
+               l_marker_size -= 2;
+               
+               if (opj_stream_read_data(p_stream, l_header_data, l_marker_size, p_manager) != l_marker_size) {
+                       opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
+                       return OPJ_FALSE;
+               }
+               
+               if (! opj_j2k_get_sot_values(l_header_data, l_marker_size, &l_tile_no, &l_tot_len, &l_current_part, &l_num_parts, p_manager)) {
+                       return OPJ_FALSE;
+               }
+               
+               if (l_tile_no == tile_no) {
+                       /* we found what we were looking for */
+                       break;
+               }
+               
+               if ((l_tot_len == 0U) || (l_tot_len < 14U)) {
+                       /* last SOT until EOC or invalid Psot value */
+                       /* assume all is OK */
+                       if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+                               return OPJ_FALSE;
+                       }
+                       return OPJ_TRUE;
+               }
+               l_tot_len -= 12U;
+               /* look for next SOT marker */
+               if (opj_stream_skip(p_stream, (OPJ_OFF_T)(l_tot_len), p_manager) != (OPJ_OFF_T)(l_tot_len)) {
+                       /* assume all is OK */
+                       if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+                               return OPJ_FALSE;
+                       }
+                       return OPJ_TRUE;
+               }
+       }
+       
+       /* check for correction */
+       if (l_current_part == l_num_parts) {
+               *p_correction_needed = OPJ_TRUE;
+       }
+       
+       if (! opj_stream_seek(p_stream, l_stream_pos_backup, p_manager)) {
+               return OPJ_FALSE;
+       }
+       return OPJ_TRUE;
+}
+
 OPJ_BOOL opj_j2k_read_tile_header(      opj_j2k_t * p_j2k,
                                                                     OPJ_UINT32 * p_tile_index,
                                                                     OPJ_UINT32 * p_data_size,
@@ -7810,7 +7986,30 @@ OPJ_BOOL opj_j2k_read_tile_header(      opj_j2k_t * p_j2k,
                         if (! opj_j2k_read_sod(p_j2k, p_stream, p_manager)) {
                                 return OPJ_FALSE;
                         }
-
+                        if (p_j2k->m_specific_param.m_decoder.m_can_decode && !p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked) {
+                                /* Issue 254 */
+                                OPJ_BOOL l_correction_needed;
+                                                                                                       
+                                p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1;
+                                if(!opj_j2k_need_nb_tile_parts_correction(p_stream, p_j2k->m_current_tile_number, &l_correction_needed, p_manager)) {
+                                        opj_event_msg(p_manager, EVT_ERROR, "opj_j2k_apply_nb_tile_parts_correction error\n");
+                                        return OPJ_FALSE;
+                                }
+                                if (l_correction_needed) {
+                                        OPJ_UINT32 l_nb_tiles = p_j2k->m_cp.tw * p_j2k->m_cp.th;
+                                        OPJ_UINT32 l_tile_no;
+
+                                        p_j2k->m_specific_param.m_decoder.m_can_decode = 0;
+                                        p_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction = 1;
+                                        /* correct tiles */
+                                        for (l_tile_no = 0U; l_tile_no < l_nb_tiles; ++l_tile_no) {
+                                                if (p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts != 0U) {
+                                                        p_j2k->m_cp.tcps[l_tile_no].m_nb_tile_parts+=1;
+                                                }
+                                        }
+                                        opj_event_msg(p_manager, EVT_WARNING, "Non conformant codestream TPsot==TNsot.\n");
+                                }
+                        }
                         if (! p_j2k->m_specific_param.m_decoder.m_can_decode){
                                 /* Try to read 2 bytes (the next marker ID) from stream and copy them into the buffer */
                                 if (opj_stream_read_data(p_stream,p_j2k->m_specific_param.m_decoder.m_header_data,2,p_manager) != 2) {
@@ -7975,10 +8174,10 @@ OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_im
         OPJ_UINT32 l_width_src,l_height_src;
         OPJ_UINT32 l_width_dest,l_height_dest;
         OPJ_INT32 l_offset_x0_src, l_offset_y0_src, l_offset_x1_src, l_offset_y1_src;
-        OPJ_INT32 l_start_offset_src, l_line_offset_src, l_end_offset_src ;
+        OPJ_SIZE_T l_start_offset_src, l_line_offset_src, l_end_offset_src ;
         OPJ_UINT32 l_start_x_dest , l_start_y_dest;
         OPJ_UINT32 l_x0_dest, l_y0_dest, l_x1_dest, l_y1_dest;
-        OPJ_INT32 l_start_offset_dest, l_line_offset_dest;
+        OPJ_SIZE_T l_start_offset_dest, l_line_offset_dest;
 
         opj_image_comp_t * l_img_comp_src = 00;
         opj_image_comp_t * l_img_comp_dest = 00;
@@ -8000,7 +8199,7 @@ OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_im
                 /* Allocate output component buffer if necessary */
                 if (!l_img_comp_dest->data) {
 
-                        l_img_comp_dest->data = (OPJ_INT32*) opj_calloc(l_img_comp_dest->w * l_img_comp_dest->h, sizeof(OPJ_INT32));
+                        l_img_comp_dest->data = (OPJ_INT32*) opj_calloc((OPJ_SIZE_T)l_img_comp_dest->w * (OPJ_SIZE_T)l_img_comp_dest->h, sizeof(OPJ_INT32));
                         if (! l_img_comp_dest->data) {
                                 return OPJ_FALSE;
                         }
@@ -8034,9 +8233,9 @@ OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_im
                 l_height_src = (OPJ_UINT32)(l_res->y1 - l_res->y0);
 
                 /* Border of the current output component*/
-                l_x0_dest = (OPJ_UINT32)opj_int_ceildivpow2((OPJ_INT32)l_img_comp_dest->x0, (OPJ_INT32)l_img_comp_dest->factor);
-                l_y0_dest = (OPJ_UINT32)opj_int_ceildivpow2((OPJ_INT32)l_img_comp_dest->y0, (OPJ_INT32)l_img_comp_dest->factor);
-                l_x1_dest = l_x0_dest + l_img_comp_dest->w;
+                l_x0_dest = opj_uint_ceildivpow2(l_img_comp_dest->x0, l_img_comp_dest->factor);
+                l_y0_dest = opj_uint_ceildivpow2(l_img_comp_dest->y0, l_img_comp_dest->factor);
+                l_x1_dest = l_x0_dest + l_img_comp_dest->w; /* can't overflow given that image->x1 is uint32 */
                 l_y1_dest = l_y0_dest + l_img_comp_dest->h;
 
                 /*if (i == 0) {
@@ -8067,7 +8266,7 @@ OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_im
                         }
                 }
                 else {
-                        l_start_x_dest = 0 ;
+                        l_start_x_dest = 0U;
                         l_offset_x0_src = (OPJ_INT32)l_x0_dest - l_res->x0;
 
                         if ( l_x1_dest >= (OPJ_UINT32)l_res->x1 ) {
@@ -8094,7 +8293,7 @@ OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_im
                         }
                 }
                 else {
-                        l_start_y_dest = 0 ;
+                        l_start_y_dest = 0U;
                         l_offset_y0_src = (OPJ_INT32)l_y0_dest - l_res->y0;
 
                         if ( l_y1_dest >= (OPJ_UINT32)l_res->y1 ) {
@@ -8117,13 +8316,13 @@ OPJ_BOOL opj_j2k_update_image_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data, opj_im
                 /*-----*/
 
                 /* Compute the input buffer offset */
-                l_start_offset_src = l_offset_x0_src + l_offset_y0_src * (OPJ_INT32)l_width_src;
-                l_line_offset_src = l_offset_x1_src + l_offset_x0_src;
-                l_end_offset_src = l_offset_y1_src * (OPJ_INT32)l_width_src - l_offset_x0_src;
+                l_start_offset_src = (OPJ_SIZE_T)l_offset_x0_src + (OPJ_SIZE_T)l_offset_y0_src * (OPJ_SIZE_T)l_width_src;
+                l_line_offset_src  = (OPJ_SIZE_T)l_offset_x1_src + (OPJ_SIZE_T)l_offset_x0_src;
+                l_end_offset_src   = (OPJ_SIZE_T)l_offset_y1_src * (OPJ_SIZE_T)l_width_src - (OPJ_SIZE_T)l_offset_x0_src;
 
                 /* Compute the output buffer offset */
-                l_start_offset_dest = (OPJ_INT32)(l_start_x_dest + l_start_y_dest * l_img_comp_dest->w);
-                l_line_offset_dest = (OPJ_INT32)(l_img_comp_dest->w - l_width_dest);
+                l_start_offset_dest = (OPJ_SIZE_T)l_start_x_dest + (OPJ_SIZE_T)l_start_y_dest * (OPJ_SIZE_T)l_img_comp_dest->w;
+                l_line_offset_dest  = (OPJ_SIZE_T)l_img_comp_dest->w - (OPJ_SIZE_T)l_width_dest;
 
                 /* Move the output buffer to the first place where we will write*/
                 l_dest_ptr = l_img_comp_dest->data + l_start_offset_dest;
@@ -8397,6 +8596,10 @@ opj_j2k_t* opj_j2k_create_decompress(void)
         l_j2k->m_is_decoder = 1;
         l_j2k->m_cp.m_is_decoder = 1;
 
+#ifdef OPJ_DISABLE_TPSOT_FIX
+        l_j2k->m_specific_param.m_decoder.m_nb_tile_parts_correction_checked = 1;
+#endif
+
         l_j2k->m_specific_param.m_decoder.m_default_tcp = (opj_tcp_t*) opj_calloc(1,sizeof(opj_tcp_t));
         if (!l_j2k->m_specific_param.m_decoder.m_default_tcp) {
                 opj_j2k_destroy(l_j2k);
@@ -8611,6 +8814,12 @@ OPJ_BOOL opj_j2k_read_SPCod_SPCoc(  opj_j2k_t *p_j2k,
         ++l_current_ptr;
         l_tccp->cblkh += 2;
 
+        if ((l_tccp->cblkw > 10) || (l_tccp->cblkh > 10) || ((l_tccp->cblkw + l_tccp->cblkh) > 12)) {
+                opj_event_msg(p_manager, EVT_ERROR, "Error reading SPCod SPCoc element, Invalid cblkw/cblkh combination\n");
+                return OPJ_FALSE;
+        }
+       
+
         opj_read_bytes(l_current_ptr,&l_tccp->cblksty ,1);              /* SPcoc (G) */
         ++l_current_ptr;
 
@@ -9607,7 +9816,7 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
 
         if (!p_image)
                 return OPJ_FALSE;
-
+       
         p_j2k->m_output_image = opj_image_create0();
         if (! (p_j2k->m_output_image)) {
                 return OPJ_FALSE;
@@ -9806,7 +10015,6 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
                                                                                                                }
                                                                                                                return OPJ_FALSE;
                                                                                                        }
-                                                                                                       opj_alloc_tile_component_data(l_tilec);
                         }
                 }
                 l_current_tile_size = opj_tcd_get_encoded_tile_size(p_j2k->m_tcd);
@@ -9836,7 +10044,7 @@ OPJ_BOOL opj_j2k_encode(opj_j2k_t * p_j2k,
                         }
                 }
 
-                if (! opj_j2k_post_write_tile (p_j2k,l_current_data,l_current_tile_size,p_stream,p_manager)) {
+                if (! opj_j2k_post_write_tile (p_j2k,p_stream,p_manager)) {
                         return OPJ_FALSE;
                 }
         }
@@ -10060,12 +10268,9 @@ void opj_j2k_get_tile_data (opj_tcd_t * p_tcd, OPJ_BYTE * p_data)
 }
 
 OPJ_BOOL opj_j2k_post_write_tile (      opj_j2k_t * p_j2k,
-                                                                OPJ_BYTE * p_data,
-                                                                OPJ_UINT32 p_data_size,
                                                                 opj_stream_private_t *p_stream,
                                                                 opj_event_mgr_t * p_manager )
 {
-        opj_tcd_t * l_tcd = 00;
         OPJ_UINT32 l_nb_bytes_written;
         OPJ_BYTE * l_current_data = 00;
         OPJ_UINT32 l_tile_size = 0;
@@ -10074,8 +10279,6 @@ OPJ_BOOL opj_j2k_post_write_tile (      opj_j2k_t * p_j2k,
         /* preconditions */
         assert(p_j2k->m_specific_param.m_encoder.m_encoded_tile_data);
 
-        l_tcd = p_j2k->m_tcd;
-
         l_tile_size = p_j2k->m_specific_param.m_encoder.m_encoded_tile_size;
         l_available_data = l_tile_size;
         l_current_data = p_j2k->m_specific_param.m_encoder.m_encoded_tile_data;
@@ -10566,7 +10769,7 @@ OPJ_BOOL opj_j2k_write_tile (opj_j2k_t * p_j2k,
                         opj_event_msg(p_manager, EVT_ERROR, "Size mismatch between tile data and sent data." );
                         return OPJ_FALSE;
                 }
-                if (! opj_j2k_post_write_tile(p_j2k,p_data,p_data_size,p_stream,p_manager)) {
+                if (! opj_j2k_post_write_tile(p_j2k,p_stream,p_manager)) {
                         opj_event_msg(p_manager, EVT_ERROR, "Error while opj_j2k_post_write_tile with tile index = %d\n", p_tile_index);
                         return OPJ_FALSE;
                 }