Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Small changes to j2k.c and t2.c that enable decoding of truncated jp2 files #1219

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
34 changes: 25 additions & 9 deletions src/lib/openjp2/j2k.c
Original file line number Diff line number Diff line change
Expand Up @@ -4695,7 +4695,7 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
opj_tcp_t * l_tcp = 00;
OPJ_UINT32 * l_tile_len = 00;
OPJ_BOOL l_sot_length_pb_detected = OPJ_FALSE;

int truncate = 0;
/* preconditions */
assert(p_j2k != 00);
assert(p_manager != 00);
Expand Down Expand Up @@ -4728,9 +4728,10 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
/* Check enough bytes left in stream before allocation */
if ((OPJ_OFF_T)p_j2k->m_specific_param.m_decoder.m_sot_length >
opj_stream_get_number_byte_left(p_stream)) {
opj_event_msg(p_manager, EVT_ERROR,
"Tile part length size inconsistent with stream length\n");
return OPJ_FALSE;
truncate = 1;
// opj_event_msg(p_manager, EVT_ERROR,
// "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) {
Expand All @@ -4746,8 +4747,15 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
/* 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 + OPJ_COMMON_CBLK_DATA_EXTRA);
if (!truncate)
{
*l_current_data = (OPJ_BYTE*) opj_malloc(
p_j2k->m_specific_param.m_decoder.m_sot_length + OPJ_COMMON_CBLK_DATA_EXTRA);
}
else
{
*l_current_data = (OPJ_BYTE*) opj_malloc(opj_stream_get_number_byte_left(p_stream) + OPJ_COMMON_CBLK_DATA_EXTRA);
}
} else {
OPJ_BYTE *l_new_current_data;
if (*l_tile_len > UINT_MAX - OPJ_COMMON_CBLK_DATA_EXTRA -
Expand All @@ -4757,10 +4765,18 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
"p_j2k->m_specific_param.m_decoder.m_sot_length");
return OPJ_FALSE;
}

if (!truncate)
{
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);
}
else
{
l_new_current_data = (OPJ_BYTE *) opj_realloc(*l_current_data,
*l_tile_len + opj_stream_get_number_byte_left(p_stream) +
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
Expand Down Expand Up @@ -4804,7 +4820,7 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,

/*l_cstr_index->packno = 0;*/
}

/* Patch to support new PHR data */
if (!l_sot_length_pb_detected) {
l_current_read_size = opj_stream_read_data(
Expand All @@ -4816,7 +4832,7 @@ static OPJ_BOOL opj_j2k_read_sod(opj_j2k_t *p_j2k,
l_current_read_size = 0;
}

if (l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) {
if ((l_current_read_size != p_j2k->m_specific_param.m_decoder.m_sot_length) || (truncate > 0) ) {
p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_NEOC;
} else {
p_j2k->m_specific_param.m_decoder.m_state = J2K_STATE_TPHSOT;
Expand Down
50 changes: 32 additions & 18 deletions src/lib/openjp2/t2.c
Original file line number Diff line number Diff line change
Expand Up @@ -1305,6 +1305,7 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
{
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
int truncate;
OPJ_BYTE *l_current_data = p_src_data;
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
Expand All @@ -1313,6 +1314,7 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,

OPJ_ARG_NOT_USED(p_t2);
OPJ_ARG_NOT_USED(pack_info);


l_band = l_res->bands;
for (bandno = 0; bandno < l_res->numbands; ++bandno) {
Expand Down Expand Up @@ -1346,18 +1348,26 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
++l_cblk->numsegs;
}
}

truncate = 0;
do {
/* Check possible overflow (on l_current_data only, assumes input args already checked) then size */
if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) <
(OPJ_SIZE_T)l_current_data) ||
(l_current_data + l_seg->newlen > p_src_data + p_max_length)) {
opj_event_msg(p_manager, EVT_ERROR,
"read: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
return OPJ_FALSE;
}
if ((((OPJ_SIZE_T)l_current_data + (OPJ_SIZE_T)l_seg->newlen) <
(OPJ_SIZE_T)l_current_data) ||
(l_current_data + l_seg->newlen > p_src_data + p_max_length)) {

//opj_event_msg(p_manager, EVT_WARNING,
// "read: segment too long (%d) current data (%d) p_src_data (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
// l_seg->newlen, l_current_data, p_src_data, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
// p_pi->compno);
truncate = 1;
l_seg->newlen = (OPJ_SIZE_T)(p_src_data + p_max_length - l_current_data);

//opj_event_msg(p_manager, EVT_ERROR,
// "read: segment too long (%d) current data (%d) p_src_data (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
// l_seg->newlen, l_current_data, p_src_data, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
// p_pi->compno);
//return OPJ_FALSE;
}

#ifdef USE_JPWL
/* we need here a j2k handle to verify if making a check to
Expand Down Expand Up @@ -1409,7 +1419,7 @@ static OPJ_BOOL opj_t2_read_packet_data(opj_t2_t* p_t2,
++l_seg;
++l_cblk->numsegs;
}
} while (l_cblk->numnewpasses > 0);
} while (l_cblk->numnewpasses > 0 && !truncate);

l_cblk->real_num_segs = l_cblk->numsegs;
++l_cblk;
Expand All @@ -1434,6 +1444,7 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
{
OPJ_UINT32 bandno, cblkno;
OPJ_UINT32 l_nb_code_blocks;
int truncate;
opj_tcd_band_t *l_band = 00;
opj_tcd_cblk_dec_t* l_cblk = 00;
opj_tcd_resolution_t* l_res =
Expand Down Expand Up @@ -1476,16 +1487,19 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
++l_cblk->numsegs;
}
}

truncate = 0;
do {
/* Check possible overflow then size */
if (((*p_data_read + l_seg->newlen) < (*p_data_read)) ||
((*p_data_read + l_seg->newlen) > p_max_length)) {
opj_event_msg(p_manager, EVT_ERROR,
"skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
p_pi->compno);
return OPJ_FALSE;
//opj_event_msg(p_manager, EVT_ERROR,
// "skip: segment too long (%d) with max (%d) for codeblock %d (p=%d, b=%d, r=%d, c=%d)\n",
// l_seg->newlen, p_max_length, cblkno, p_pi->precno, bandno, p_pi->resno,
// p_pi->compno);
truncate = 1;
l_seg->newlen = (OPJ_SIZE_T)(p_max_length - *p_data_read);

// return OPJ_FALSE;
}

#ifdef USE_JPWL
Expand Down Expand Up @@ -1518,7 +1532,7 @@ static OPJ_BOOL opj_t2_skip_packet_data(opj_t2_t* p_t2,
++l_seg;
++l_cblk->numsegs;
}
} while (l_cblk->numnewpasses > 0);
} while (l_cblk->numnewpasses > 0 && !truncate);

++l_cblk;
}
Expand Down