Merge pull request #975 from szukw000/changes-for-afl-tests
[openjpeg.git] / src / lib / openjp2 / j2k.c
index 5f1c557547a8ffc7b0aad696d5f31a9734f015fb..5a169e1809edc97106888716e370e96b3ee5a3f9 100644 (file)
@@ -2054,6 +2054,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
     OPJ_UINT32 l_remaining_size;
     OPJ_UINT32 l_nb_tiles;
     OPJ_UINT32 l_tmp, l_tx1, l_ty1;
+    OPJ_UINT32 l_prec0, l_sgnd0;
     opj_image_t *l_image = 00;
     opj_cp_t *l_cp = 00;
     opj_image_comp_t * l_img_comp = 00;
@@ -2156,7 +2157,20 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                       "Error with SIZ marker: illegal tile offset\n");
         return OPJ_FALSE;
     }
+    if (!p_j2k->dump_state) {
+        OPJ_UINT32 siz_w, siz_h;
 
+        siz_w = l_image->x1 - l_image->x0;
+        siz_h = l_image->y1 - l_image->y0;
+
+        if (p_j2k->ihdr_w > 0 && p_j2k->ihdr_h > 0
+                && (p_j2k->ihdr_w != siz_w || p_j2k->ihdr_h != siz_h)) {
+            opj_event_msg(p_manager, EVT_ERROR,
+                          "Error with SIZ marker: IHDR w(%u) h(%u) vs. SIZ w(%u) h(%u)\n", p_j2k->ihdr_w,
+                          p_j2k->ihdr_h, siz_w, siz_h);
+            return OPJ_FALSE;
+        }
+    }
 #ifdef USE_JPWL
     if (l_cp->correct) {
         /* if JPWL is on, we check whether TX errors have damaged
@@ -2211,6 +2225,8 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
 
     l_img_comp = l_image->comps;
 
+    l_prec0 = 0;
+    l_sgnd0 = 0;
     /* Read the component information */
     for (i = 0; i < l_image->numcomps; ++i) {
         OPJ_UINT32 tmp;
@@ -2218,6 +2234,20 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         ++p_header_data;
         l_img_comp->prec = (tmp & 0x7f) + 1;
         l_img_comp->sgnd = tmp >> 7;
+
+        if (p_j2k->dump_state == 0) {
+            if (i == 0) {
+                l_prec0 = l_img_comp->prec;
+                l_sgnd0 = l_img_comp->sgnd;
+            } else if (l_cp->bpc_is_255 == 0
+                       && (l_img_comp->prec != l_prec0 || l_img_comp->sgnd != l_sgnd0)) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "Invalid precision and/or sgnd values for comp[%d]:\n"
+                              "        [0] prec(%d) sgnd(%d) [%d] prec(%d) sgnd(%d)\n", i, l_prec0, l_sgnd0,
+                              i, l_img_comp->prec, l_img_comp->sgnd);
+                return OPJ_FALSE;
+            }
+        }
         opj_read_bytes(p_header_data, &tmp, 1); /* XRsiz_i */
         ++p_header_data;
         l_img_comp->dx = (OPJ_UINT32)tmp; /* should be between 1 and 255 */
@@ -2240,7 +2270,6 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
                           i, l_img_comp->prec);
             return OPJ_FALSE;
         }
-
 #ifdef USE_JPWL
         if (l_cp->correct) {
             /* if JPWL is on, we check whether TX errors have damaged
@@ -2277,6 +2306,10 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         ++l_img_comp;
     }
 
+    if (l_cp->tdx == 0 || l_cp->tdy == 0) {
+        return OPJ_FALSE;
+    }
+
     /* Compute the number of tiles */
     l_cp->tw = (OPJ_UINT32)opj_int_ceildiv((OPJ_INT32)(l_image->x1 - l_cp->tx0),
                                            (OPJ_INT32)l_cp->tdx);
@@ -2431,8 +2464,7 @@ static OPJ_BOOL opj_j2k_read_siz(opj_j2k_t *p_j2k,
         ++l_current_tile_param;
     }
 
-    p_j2k->m_specific_param.m_decoder.m_state =
-        J2K_STATE_MH; /* FIXME J2K_DEC_STATE_MH; */
+    p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_MH;
     opj_image_comp_header_update(l_image, l_cp);
 
     return OPJ_TRUE;
@@ -2890,7 +2922,7 @@ static OPJ_BOOL opj_j2k_read_coc(opj_j2k_t *p_j2k,
 
     l_cp = &(p_j2k->m_cp);
     l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH)
-            ?  /*FIXME J2K_DEC_STATE_TPH*/
+            ?
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
     l_image = p_j2k->m_private_image;
@@ -4379,6 +4411,16 @@ static OPJ_BOOL opj_j2k_read_sot(opj_j2k_t *p_j2k,
         p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1;
     }
 
+    if (l_tcp->m_nb_tile_parts != 0 && l_current_part >= l_tcp->m_nb_tile_parts) {
+        /* Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2851 */
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "In SOT marker, TPSot (%d) is not valid regards to the previous "
+                      "number of tile-part (%d), giving up\n", l_current_part,
+                      l_tcp->m_nb_tile_parts);
+        p_j2k->m_specific_param.m_decoder.m_last_tile_part = 1;
+        return OPJ_FALSE;
+    }
+
     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;
@@ -4675,15 +4717,35 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
                           "Tile part length size inconsistent with stream length\n");
             return OPJ_FALSE;
         }
+        if (p_j2k->m_specific_param.m_decoder.m_sot_length >
+                UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA) {
+            opj_event_msg(p_manager, EVT_ERROR,
+                          "p_j2k->m_specific_param.m_decoder.m_sot_length > "
+                          "UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA");
+            return OPJ_FALSE;
+        }
+        /* Add a margin of OPJ_COMMON_CBLK_DATA_EXTRA to the allocation we */
+        /* do so that opj_mqc_init_dec_common() can safely add a synthetic */
+        /* 0xFFFF marker. */
         if (! *l_current_data) {
             /* LH: oddly enough, in this path, l_tile_len!=0.
              * TODO: If this was consistent, we could simplify the code to only use realloc(), as realloc(0,...) default to malloc(0,...).
              */
             *l_current_data = (OPJ_BYTE*) opj_malloc(
-                                  p_j2k->m_specific_param.m_decoder.m_sot_length);
+                                  p_j2k->m_specific_param.m_decoder.m_sot_length + OPJ_COMMON_CBLK_DATA_EXTRA);
         } else {
-            OPJ_BYTE *l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data,
-                                           *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length);
+            OPJ_BYTE *l_new_current_data;
+            if (*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA -
+                    p_j2k->m_specific_param.m_decoder.m_sot_length) {
+                opj_event_msg(p_manager, EVT_ERROR,
+                              "*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA - "
+                              "p_j2k->m_specific_param.m_decoder.m_sot_length");
+                return OPJ_FALSE;
+            }
+
+            l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data,
+                                 *l_tile_len + p_j2k->m_specific_param.m_decoder.m_sot_length +
+                                 OPJ_COMMON_CBLK_DATA_EXTRA);
             if (! l_new_current_data) {
                 opj_free(*l_current_data);
                 /*nothing more is done as l_current_data will be set to null, and just
@@ -5549,6 +5611,28 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k,
                 opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to read MCT marker\n");
                 return OPJ_FALSE;
             }
+
+            /* Update m_mcc_records[].m_offset_array and m_decorrelation_array
+             * to point to the new addresses */
+            if (new_mct_records != l_tcp->m_mct_records) {
+                for (i = 0; i < l_tcp->m_nb_mcc_records; ++i) {
+                    opj_simple_mcc_decorrelation_data_t* l_mcc_record =
+                        &(l_tcp->m_mcc_records[i]);
+                    if (l_mcc_record->m_decorrelation_array) {
+                        l_mcc_record->m_decorrelation_array =
+                            new_mct_records +
+                            (l_mcc_record->m_decorrelation_array -
+                             l_tcp->m_mct_records);
+                    }
+                    if (l_mcc_record->m_offset_array) {
+                        l_mcc_record->m_offset_array =
+                            new_mct_records +
+                            (l_mcc_record->m_offset_array -
+                             l_tcp->m_mct_records);
+                    }
+                }
+            }
+
             l_tcp->m_mct_records = new_mct_records;
             l_mct_data = l_tcp->m_mct_records + l_tcp->m_nb_mct_records;
             memset(l_mct_data, 0, (l_tcp->m_nb_max_mct_records - l_tcp->m_nb_mct_records) *
@@ -5562,6 +5646,7 @@ static OPJ_BOOL opj_j2k_read_mct(opj_j2k_t *p_j2k,
     if (l_mct_data->m_data) {
         opj_free(l_mct_data->m_data);
         l_mct_data->m_data = 00;
+        l_mct_data->m_data_size = 0;
     }
 
     l_mct_data->m_index = l_indix;
@@ -6293,6 +6378,7 @@ void opj_j2k_setup_decoder(opj_j2k_t *j2k, opj_dparameters_t *parameters)
         j2k->m_cp.m_specific_param.m_dec.m_layer = parameters->cp_layer;
         j2k->m_cp.m_specific_param.m_dec.m_reduce = parameters->cp_reduce;
 
+        j2k->dump_state = (parameters->flags & OPJ_DPARAMETERS_DUMP_FLAG);
 #ifdef USE_JPWL
         j2k->m_cp.correct = parameters->jpwl_correct;
         j2k->m_cp.exp_comps = parameters->jpwl_exp_comps;
@@ -8595,10 +8681,7 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
 
     /* Current marker is the EOC marker ?*/
     if (l_current_marker == J2K_MS_EOC) {
-        if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) {
-            p_j2k->m_current_tile_number = 0;
-            p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
-        }
+        p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
     }
 
     /* FIXME DOC ???*/
@@ -8635,14 +8718,16 @@ OPJ_BOOL opj_j2k_read_tile_header(opj_j2k_t * p_j2k,
     *p_tile_index = p_j2k->m_current_tile_number;
     *p_go_on = OPJ_TRUE;
     *p_data_size = opj_tcd_get_decoded_tile_size(p_j2k->m_tcd);
+    if (*p_data_size == UINT_MAX) {
+        return OPJ_FALSE;
+    }
     *p_tile_x0 = p_j2k->m_tcd->tcd_image->tiles->x0;
     *p_tile_y0 = p_j2k->m_tcd->tcd_image->tiles->y0;
     *p_tile_x1 = p_j2k->m_tcd->tcd_image->tiles->x1;
     *p_tile_y1 = p_j2k->m_tcd->tcd_image->tiles->y1;
     *p_nb_comps = p_j2k->m_tcd->tcd_image->tiles->numcomps;
 
-    p_j2k->m_specific_param.m_decoder.m_state |=
-        0x0080;/* FIXME J2K_DEC_STATE_DATA;*/
+    p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_DATA;
 
     return OPJ_TRUE;
 }
@@ -8663,8 +8748,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
     assert(p_j2k != 00);
     assert(p_manager != 00);
 
-    if (!(p_j2k->m_specific_param.m_decoder.m_state &
-            0x0080/*FIXME J2K_DEC_STATE_DATA*/)
+    if (!(p_j2k->m_specific_param.m_decoder.m_state & J2K_STATE_DATA)
             || (p_tile_index != p_j2k->m_current_tile_number)) {
         return OPJ_FALSE;
     }
@@ -8681,32 +8765,36 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
                               p_tile_index,
                               p_j2k->cstr_index, p_manager)) {
         opj_j2k_tcp_destroy(l_tcp);
-        p_j2k->m_specific_param.m_decoder.m_state |= 0x8000;/*FIXME J2K_DEC_STATE_ERR;*/
+        p_j2k->m_specific_param.m_decoder.m_state |= J2K_STATE_ERR;
         opj_event_msg(p_manager, EVT_ERROR, "Failed to decode.\n");
         return OPJ_FALSE;
     }
+    p_j2k->m_tcd->enumcs = p_j2k->enumcs;
 
-    if (! opj_tcd_update_tile_data(p_j2k->m_tcd, p_data, p_data_size)) {
-        return OPJ_FALSE;
-    }
+    /* p_data can be set to NULL when the call will take care of using */
+    /* itself the TCD data. This is typically the case for whole single */
+    /* tile decoding optimization. */
+    if (p_data != NULL) {
+        if (! opj_tcd_update_tile_data(p_j2k->m_tcd, p_data, p_data_size)) {
+            return OPJ_FALSE;
+        }
 
-    /* To avoid to destroy the tcp which can be useful when we try to decode a tile decoded before (cf j2k_random_tile_access)
-     * we destroy just the data which will be re-read in read_tile_header*/
-    /*opj_j2k_tcp_destroy(l_tcp);
-    p_j2k->m_tcd->tcp = 0;*/
-    opj_j2k_tcp_data_destroy(l_tcp);
+        /* To avoid to destroy the tcp which can be useful when we try to decode a tile decoded before (cf j2k_random_tile_access)
+        * we destroy just the data which will be re-read in read_tile_header*/
+        /*opj_j2k_tcp_destroy(l_tcp);
+        p_j2k->m_tcd->tcp = 0;*/
+        opj_j2k_tcp_data_destroy(l_tcp);
+    }
 
     p_j2k->m_specific_param.m_decoder.m_can_decode = 0;
-    p_j2k->m_specific_param.m_decoder.m_state &= (~
-            (0x0080u)); /* FIXME J2K_DEC_STATE_DATA);*/
+    p_j2k->m_specific_param.m_decoder.m_state &= (~(OPJ_UINT32)J2K_STATE_DATA);
 
     if (opj_stream_get_number_byte_left(p_stream) == 0
             && p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_NEOC) {
         return OPJ_TRUE;
     }
 
-    if (p_j2k->m_specific_param.m_decoder.m_state !=
-            0x0100) { /*FIXME J2K_DEC_STATE_EOC)*/
+    if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_EOC) {
         if (opj_stream_read_data(p_stream, l_data, 2, p_manager) != 2) {
             opj_event_msg(p_manager, EVT_ERROR, "Stream too short\n");
             return OPJ_FALSE;
@@ -8716,7 +8804,7 @@ OPJ_BOOL opj_j2k_decode_tile(opj_j2k_t * p_j2k,
 
         if (l_current_marker == J2K_MS_EOC) {
             p_j2k->m_current_tile_number = 0;
-            p_j2k->m_specific_param.m_decoder.m_state =  0x0100;/*FIXME J2K_DEC_STATE_EOC;*/
+            p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_EOC;
         } else if (l_current_marker != J2K_MS_SOT) {
             if (opj_stream_get_number_byte_left(p_stream) == 0) {
                 p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC;
@@ -8765,15 +8853,18 @@ static OPJ_BOOL opj_j2k_update_image_data(opj_tcd_t * p_tcd, OPJ_BYTE * p_data,
             OPJ_SIZE_T l_width = l_img_comp_dest->w;
             OPJ_SIZE_T l_height = l_img_comp_dest->h;
 
-            if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height))) {
+            if ((l_height == 0U) || (l_width > (SIZE_MAX / l_height)) ||
+                    l_width * l_height > SIZE_MAX / sizeof(OPJ_INT32)) {
                 /* would overflow */
                 return OPJ_FALSE;
             }
-            l_img_comp_dest->data = (OPJ_INT32*) opj_calloc(l_width * l_height,
+            l_img_comp_dest->data = (OPJ_INT32*) opj_image_data_alloc(l_width * l_height *
                                     sizeof(OPJ_INT32));
             if (! l_img_comp_dest->data) {
                 return OPJ_FALSE;
             }
+            /* Do we really need this memset ? */
+            memset(l_img_comp_dest->data, 0, l_width * l_height * sizeof(OPJ_INT32));
         }
 
         /* Copy info from decoded comp image to output image */
@@ -9016,8 +9107,7 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     opj_image_comp_t* l_img_comp = NULL;
 
     /* Check if we are read the main header */
-    if (p_j2k->m_specific_param.m_decoder.m_state !=
-            J2K_STATE_TPHSOT) { /* FIXME J2K_DEC_STATE_TPHSOT)*/
+    if (p_j2k->m_specific_param.m_decoder.m_state != J2K_STATE_TPHSOT) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Need to decode the main header before begin to decode the remaining codestream");
         return OPJ_FALSE;
@@ -9039,10 +9129,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     /* Check if the positions provided by the user are correct */
 
     /* Left */
-    assert(p_start_x >= 0);
-    assert(p_start_y >= 0);
-
-    if ((OPJ_UINT32)p_start_x > l_image->x1) {
+    if (p_start_x < 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Left position of the decoded area (region_x0=%d) should be >= 0.\n",
+                      p_start_x);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_start_x > l_image->x1) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Left position of the decoded area (region_x0=%d) is outside the image area (Xsiz=%d).\n",
                       p_start_x, l_image->x1);
@@ -9060,7 +9152,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     }
 
     /* Up */
-    if ((OPJ_UINT32)p_start_y > l_image->y1) {
+    if (p_start_x < 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Up position of the decoded area (region_y0=%d) should be >= 0.\n",
+                      p_start_y);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_start_y > l_image->y1) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Up position of the decoded area (region_y0=%d) is outside the image area (Ysiz=%d).\n",
                       p_start_y, l_image->y1);
@@ -9078,9 +9175,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     }
 
     /* Right */
-    assert((OPJ_UINT32)p_end_x > 0);
-    assert((OPJ_UINT32)p_end_y > 0);
-    if ((OPJ_UINT32)p_end_x < l_image->x0) {
+    if (p_end_x <= 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Right position of the decoded area (region_x1=%d) should be > 0.\n",
+                      p_end_x);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_end_x < l_image->x0) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Right position of the decoded area (region_x1=%d) is outside the image area (XOsiz=%d).\n",
                       p_end_x, l_image->x0);
@@ -9098,7 +9198,12 @@ OPJ_BOOL opj_j2k_set_decode_area(opj_j2k_t *p_j2k,
     }
 
     /* Bottom */
-    if ((OPJ_UINT32)p_end_y < l_image->y0) {
+    if (p_end_y <= 0) {
+        opj_event_msg(p_manager, EVT_ERROR,
+                      "Bottom position of the decoded area (region_y1=%d) should be > 0.\n",
+                      p_end_y);
+        return OPJ_FALSE;
+    } else if ((OPJ_UINT32)p_end_y < l_image->y0) {
         opj_event_msg(p_manager, EVT_ERROR,
                       "Bottom position of the decoded area (region_y1=%d) is outside the image area (YOsiz=%d).\n",
                       p_end_y, l_image->y0);
@@ -9545,7 +9650,7 @@ static void opj_j2k_copy_tile_component_parameters(opj_j2k_t *p_j2k)
 
     l_cp = &(p_j2k->m_cp);
     l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH)
-            ? /* FIXME J2K_DEC_STATE_TPH*/
+            ?
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
 
@@ -9742,7 +9847,7 @@ static OPJ_BOOL opj_j2k_read_SQcd_SQcc(opj_j2k_t *p_j2k,
     l_cp = &(p_j2k->m_cp);
     /* come from tile part header or main header ?*/
     l_tcp = (p_j2k->m_specific_param.m_decoder.m_state == J2K_STATE_TPH)
-            ? /*FIXME J2K_DEC_STATE_TPH*/
+            ?
             &l_cp->tcps[p_j2k->m_current_tile_number] :
             p_j2k->m_specific_param.m_decoder.m_default_tcp;
 
@@ -10339,6 +10444,47 @@ static OPJ_BOOL opj_j2k_decode_tiles(opj_j2k_t *p_j2k,
     OPJ_BYTE * l_current_data;
     OPJ_UINT32 nr_tiles = 0;
 
+    /* Particular case for whole single tile decoding */
+    /* We can avoid allocating intermediate tile buffers */
+    if (p_j2k->m_cp.tw == 1 && p_j2k->m_cp.th == 1 &&
+            p_j2k->m_cp.tx0 == 0 && p_j2k->m_cp.ty0 == 0 &&
+            p_j2k->m_output_image->x0 == 0 &&
+            p_j2k->m_output_image->y0 == 0 &&
+            p_j2k->m_output_image->x1 == p_j2k->m_cp.tdx &&
+            p_j2k->m_output_image->y1 == p_j2k->m_cp.tdy &&
+            p_j2k->m_output_image->comps[0].factor == 0) {
+        OPJ_UINT32 i;
+        if (! opj_j2k_read_tile_header(p_j2k,
+                                       &l_current_tile_no,
+                                       &l_data_size,
+                                       &l_tile_x0, &l_tile_y0,
+                                       &l_tile_x1, &l_tile_y1,
+                                       &l_nb_comps,
+                                       &l_go_on,
+                                       p_stream,
+                                       p_manager)) {
+            return OPJ_FALSE;
+        }
+
+        if (! opj_j2k_decode_tile(p_j2k, l_current_tile_no, NULL, 0,
+                                  p_stream, p_manager)) {
+            opj_event_msg(p_manager, EVT_ERROR, "Failed to decode tile 1/1\n");
+            return OPJ_FALSE;
+        }
+
+        /* Transfer TCD data to output image data */
+        for (i = 0; i < p_j2k->m_output_image->numcomps; i++) {
+            opj_image_data_free(p_j2k->m_output_image->comps[i].data);
+            p_j2k->m_output_image->comps[i].data =
+                p_j2k->m_tcd->tcd_image->tiles->comps[i].data;
+            p_j2k->m_output_image->comps[i].resno_decoded =
+                p_j2k->m_tcd->image->comps[i].resno_decoded;
+            p_j2k->m_tcd->tcd_image->tiles->comps[i].data = NULL;
+        }
+
+        return OPJ_TRUE;
+    }
+
     l_current_data = (OPJ_BYTE*)opj_malloc(1000);
     if (! l_current_data) {
         opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to decode tiles\n");
@@ -10604,7 +10750,9 @@ OPJ_BOOL opj_j2k_decode(opj_j2k_t * p_j2k,
     opj_copy_image_header(p_image, p_j2k->m_output_image);
 
     /* customization of the decoding */
-    opj_j2k_setup_decoding(p_j2k, p_manager);
+    if (!opj_j2k_setup_decoding(p_j2k, p_manager)) {
+        return OPJ_FALSE;
+    }
 
     /* Decode the codestream */
     if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) {
@@ -10714,7 +10862,9 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
     p_j2k->m_specific_param.m_decoder.m_tile_ind_to_dec = (OPJ_INT32)tile_index;
 
     /* customization of the decoding */
-    opj_j2k_setup_decoding_tile(p_j2k, p_manager);
+    if (!opj_j2k_setup_decoding_tile(p_j2k, p_manager)) {
+        return OPJ_FALSE;
+    }
 
     /* Decode the codestream */
     if (! opj_j2k_exec(p_j2k, p_j2k->m_procedure_list, p_stream, p_manager)) {
@@ -10729,7 +10879,7 @@ OPJ_BOOL opj_j2k_get_tile(opj_j2k_t *p_j2k,
             p_j2k->m_output_image->comps[compno].resno_decoded;
 
         if (p_image->comps[compno].data) {
-            opj_free(p_image->comps[compno].data);
+            opj_image_data_free(p_image->comps[compno].data);
         }
 
         p_image->comps[compno].data = p_j2k->m_output_image->comps[compno].data;