[trunk] Prevent a leak when reading PPT markers
[openjpeg.git] / src / lib / openjp2 / j2k.c
index a9b42697b1c671feef4fd9461bc9c467353043a5..93d9999c606c6d2cead303310beecf0996763438 100644 (file)
@@ -3175,6 +3175,8 @@ static OPJ_BOOL opj_j2k_read_poc (  opj_j2k_t *p_j2k,
                 opj_read_bytes(p_header_data,&(l_current_poc->compno0),l_comp_room);    /* CSpoc_i */
                 p_header_data+=l_comp_room;
                 opj_read_bytes(p_header_data,&(l_current_poc->layno1),2);                               /* LYEpoc_i */
+                /* make sure layer end is in acceptable bounds */
+                l_current_poc->layno1 = opj_uint_min(l_current_poc->layno1, l_tcp->numlayers);
                 p_header_data+=2;
                 opj_read_bytes(p_header_data,&(l_current_poc->resno1),1);                               /* REpoc_i */
                 ++p_header_data;
@@ -3553,6 +3555,17 @@ OPJ_BOOL j2k_read_ppm_v3 (
                 p_header_data+=4;
                 p_header_size-=4;
 
+                /* sanity check: how much bytes is left for Ippm */
+                if( p_header_size < l_N_ppm )
+                  {
+                  opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes (%u) to hold Ippm series (%u), Index (%d)\n", p_header_size, l_N_ppm, l_Z_ppm );
+                  opj_free(l_cp->ppm_data);
+                  l_cp->ppm_data = NULL;
+                  l_cp->ppm_buffer = NULL;
+                  l_cp->ppm = 0; /* do not use PPM */
+                  return OPJ_TRUE;
+                  }
+
                 /* First PPM marker: Initialization */
                 l_cp->ppm_len = l_N_ppm;
                 l_cp->ppm_data_read = 0;
@@ -3587,6 +3600,16 @@ OPJ_BOOL j2k_read_ppm_v3 (
                                 p_header_data+=4;
                                 p_header_size-=4;
 
+                                /* sanity check: how much bytes is left for Ippm */
+                                if( p_header_size < l_N_ppm )
+                                  {
+                                  opj_event_msg(p_manager, EVT_ERROR, "Not enough bytes (%u) to hold Ippm series (%u), Index (%d)\n", p_header_size, l_N_ppm, l_Z_ppm );
+                                  opj_free(l_cp->ppm_data);
+                                  l_cp->ppm_data = NULL;
+                                  l_cp->ppm_buffer = NULL;
+                                  l_cp->ppm = 0; /* do not use PPM */
+                                  return OPJ_TRUE;
+                                  }
                                 /* Increase the size of ppm_data to add the new Ippm series*/
                                 assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
                                 new_ppm_data = (OPJ_BYTE *) opj_realloc(l_cp->ppm_data, l_cp->ppm_len + l_N_ppm);
@@ -3632,7 +3655,7 @@ OPJ_BOOL j2k_read_ppm_v3 (
                 l_remaining_data = p_header_size;
 
                 /* Next Ippm series is a complete series ?*/
-                if (l_remaining_data > l_N_ppm) {
+                if (l_remaining_data >= l_N_ppm) {
                         OPJ_BYTE *new_ppm_data;
                         /* Increase the size of ppm_data to add the new Ippm series*/
                         assert(l_cp->ppm_data == l_cp->ppm_buffer && "We need ppm_data and ppm_buffer to be the same when reallocating");
@@ -3780,6 +3803,7 @@ static OPJ_BOOL opj_j2k_read_ppt (  opj_j2k_t *p_j2k,
                 l_tcp->ppt_data_size = 0;
                 l_tcp->ppt_len = p_header_size;
 
+                opj_free(l_tcp->ppt_buffer);
                 l_tcp->ppt_buffer = (OPJ_BYTE *) opj_calloc(l_tcp->ppt_len, sizeof(OPJ_BYTE) );
                 if (l_tcp->ppt_buffer == 00) {
                         opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read PPT marker\n");
@@ -7619,6 +7643,7 @@ OPJ_BOOL opj_j2k_decode_tile (  opj_j2k_t * p_j2k,
                                                                 p_j2k->cstr_index) ) {
                 opj_j2k_tcp_destroy(l_tcp);
                 p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/
+                opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n");
                 return OPJ_FALSE;
         }
 
@@ -9120,6 +9145,7 @@ OPJ_BOOL opj_j2k_decode_tiles ( opj_j2k_t *p_j2k,
 
                 if (! opj_j2k_decode_tile(p_j2k,l_current_tile_no,l_current_data,l_data_size,p_stream,p_manager)) {
                         opj_free(l_current_data);
+                        opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile %d/%d\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
                         return OPJ_FALSE;
                 }
                 opj_event_msg(p_manager, EVT_INFO, "Tile %d/%d has been decoded.\n", l_current_tile_no +1, p_j2k->m_cp.th * p_j2k->m_cp.tw);
@@ -9318,6 +9344,13 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
         for (compno = 0; compno < p_image->numcomps; compno++) {
                 p_image->comps[compno].resno_decoded = p_j2k->m_output_image->comps[compno].resno_decoded;
                 p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;
+#if 0
+                char fn[256];
+                sprintf( fn, "/tmp/%d.raw", compno );
+                FILE *debug = fopen( fn, "wb" );
+                fwrite( p_image->comps[compno].data, sizeof(OPJ_INT32), p_image->comps[compno].w * p_image->comps[compno].h, debug );
+                fclose( debug );
+#endif
                 p_j2k->m_output_image->comps[compno].data = NULL;
         }