Skip to content

Commit

Permalink
Support files with very large data size
Browse files Browse the repository at this point in the history
The maximum supported data size is a limiting factor for the maximum
size of allowed images. As it is possible to allocate size_t bytes,
this data type must also be used for the data size.

This modification also fixes issue uclouvain#432. That file is now decoded on
64 bit hosts with enough RAM, so the regression test had to be fixed.
Until it is possible to use different test cases for 32 and 64 bit hosts,
the test for issue uclouvain#432 is disabled.

Handle also a potential division by zero when l_data_size is 0.
This fixes issue uclouvain#733.

Update also some comments in the test suite.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
  • Loading branch information
stweil committed May 3, 2017
1 parent 20291aa commit 7fb831e
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 17 deletions.
24 changes: 12 additions & 12 deletions src/lib/openjp2/tcd.c
Expand Up @@ -680,7 +680,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
/* room needed to store l_nb_code_blocks code blocks for a precinct*/
OPJ_UINT32 l_nb_code_blocks_size;
/* size of data for a tile */
OPJ_UINT32 l_data_size;
size_t l_data_size;

l_cp = p_tcd->cp;
l_tcp = &(l_cp->tcps[p_tile_no]);
Expand Down Expand Up @@ -732,19 +732,19 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
/*fprintf(stderr, "\tTile compo border = %d,%d,%d,%d\n", l_tilec->x0, l_tilec->y0,l_tilec->x1,l_tilec->y1);*/

/* compute l_data_size with overflow check */
l_data_size = (OPJ_UINT32)(l_tilec->x1 - l_tilec->x0);
l_data_size = l_tilec->x1 - l_tilec->x0;
/* issue 733, l_data_size == 0U, probably something wrong should be checked before getting here */
if ((l_data_size > 0U) && ((((OPJ_UINT32)-1) / l_data_size) < (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0))) {
if ((l_data_size > 0U) && ((SIZE_MAX / l_data_size) < (size_t)(l_tilec->y1 - l_tilec->y0))) {
opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
return OPJ_FALSE;
}
l_data_size = l_data_size * (OPJ_UINT32)(l_tilec->y1 - l_tilec->y0);
l_data_size = l_data_size * (l_tilec->y1 - l_tilec->y0);

if ((((OPJ_UINT32)-1) / (OPJ_UINT32)sizeof(OPJ_UINT32)) < l_data_size) {
opj_event_msg(manager, EVT_ERROR, "Not enough memory for tile data\n");
if ((SIZE_MAX / sizeof(OPJ_UINT32)) < l_data_size) {
opj_event_msg(manager, EVT_ERROR, "Size of tile data exceeds system limits\n");
return OPJ_FALSE;
}
l_data_size = l_data_size * (OPJ_UINT32)sizeof(OPJ_UINT32);
l_data_size = l_data_size * sizeof(OPJ_UINT32);
l_tilec->numresolutions = l_tccp->numresolutions;
if (l_tccp->numresolutions < l_cp->m_specific_param.m_dec.m_reduce) {
l_tilec->minimum_num_resolutions = 1;
Expand All @@ -759,14 +759,14 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
return OPJ_FALSE;
}

l_data_size = l_tilec->numresolutions * (OPJ_UINT32)sizeof(opj_tcd_resolution_t);
l_data_size = l_tilec->numresolutions * sizeof(opj_tcd_resolution_t);

if (l_tilec->resolutions == 00) {
l_tilec->resolutions = (opj_tcd_resolution_t *) opj_malloc(l_data_size);
if (! l_tilec->resolutions ) {
return OPJ_FALSE;
}
/*fprintf(stderr, "\tAllocate resolutions of tilec (opj_tcd_resolution_t): %d\n",l_data_size);*/
/*fprintf(stderr, "\tAllocate resolutions of tilec (opj_tcd_resolution_t): %tu\n", l_data_size);*/
l_tilec->resolutions_size = l_data_size;
memset(l_tilec->resolutions,0,l_data_size);
}
Expand All @@ -780,7 +780,7 @@ static INLINE OPJ_BOOL opj_tcd_init_tile(opj_tcd_t *p_tcd, OPJ_UINT32 p_tile_no,
return OPJ_FALSE;
}
l_tilec->resolutions = new_resolutions;
/*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %d x OPJ_UINT32\n", l_tilec->resolutions_size, l_data_size);*/
/*fprintf(stderr, "\tReallocate data of tilec (int): from %d to %tu x OPJ_UINT32\n", l_tilec->resolutions_size, l_data_size);*/
memset(((OPJ_BYTE*) l_tilec->resolutions)+l_tilec->resolutions_size,0,l_data_size - l_tilec->resolutions_size);
l_tilec->resolutions_size = l_data_size;
}
Expand Down Expand Up @@ -1078,9 +1078,9 @@ static OPJ_BOOL opj_tcd_code_block_enc_allocate (opj_tcd_cblk_enc_t * p_code_blo
*/
static OPJ_BOOL opj_tcd_code_block_enc_allocate_data (opj_tcd_cblk_enc_t * p_code_block)
{
OPJ_UINT32 l_data_size;
size_t l_data_size;

l_data_size = (OPJ_UINT32)((p_code_block->x1 - p_code_block->x0) * (p_code_block->y1 - p_code_block->y0) * (OPJ_INT32)sizeof(OPJ_UINT32));
l_data_size = (size_t)((p_code_block->x1 - p_code_block->x0) * (p_code_block->y1 - p_code_block->y0) * sizeof(OPJ_UINT32));

if (l_data_size > p_code_block->data_size) {
if (p_code_block->data) {
Expand Down
4 changes: 2 additions & 2 deletions src/lib/openjp2/tcd.h
Expand Up @@ -164,8 +164,8 @@ typedef struct opj_tcd_tilecomp
OPJ_UINT32 resolutions_size; /* size of data for resolutions (in bytes) */
OPJ_INT32 *data; /* data of the component */
OPJ_BOOL ownsData; /* if true, then need to free after usage, otherwise do not free */
OPJ_UINT32 data_size_needed; /* we may either need to allocate this amount of data, or re-use image data and ignore this value */
OPJ_UINT32 data_size; /* size of the data of the component */
size_t data_size_needed; /* we may either need to allocate this amount of data, or re-use image data and ignore this value */
size_t data_size; /* size of the data of the component */
OPJ_INT32 numpix; /* add fixed_quality */
} opj_tcd_tilecomp_t;

Expand Down
1 change: 1 addition & 0 deletions tests/nonregression/md5refs.txt
Expand Up @@ -173,6 +173,7 @@ d5ecef537edf294af83826763c0cf860 issue411-ycc422.jp2_1.pgx
07480962d25b3d8cce18096648963c8a issue411-ycc420.jp2_0.pgx
149a69831b42401f20b8f7492ef99d97 issue411-ycc420.jp2_1.pgx
ec8d1c99db9763a8ba489df4f41dda53 issue411-ycc420.jp2_2.pgx
895b5a311e96f458e3c058f2f50f4fa3 issue432.jp2_0.pgx
3c7ff2e4bdae849167be36589f32bcd5 issue458.jp2_0.pgx
f004b48eafb2e52529cc9c7b6a3ff5d2 issue458.jp2_1.pgx
3127bd0a591d113c3c2428c8d2c14ec8 issue458.jp2_2.pgx
Expand Down
9 changes: 6 additions & 3 deletions tests/nonregression/test_suite.ctest.in
@@ -1,4 +1,4 @@
# This file list all the input commands of the tests run by the ctest command which
# This file lists all the input commands of the tests run by the ctest command which
# are not related to the conformance files.
#
# For each line of this file (except line which begin with #) an opj_compress test or a
Expand All @@ -9,7 +9,7 @@
# + For decoder related tests = dump, compare dump to base, (TODO: compare outpout decoding
# image to base)
#
# Line begin with ! should failed (should be used for bad jpeg2000 file which should be
# Lines beginning with ! should fail (should be used for bad jpeg2000 file which should be
# gracefully rejected). Please add a short resume about why this file should be rejected.
#
# You can use @INPUT_NR_PATH@ and @TEMP_PATH@ cmake variable which refers to OPJ_DATA_ROOT
Expand Down Expand Up @@ -328,7 +328,10 @@ opj_decompress -i @INPUT_NR_PATH@/issue411-ycc420.jp2 -o @TEMP_PATH@/issue411-yc
# issue 429 (from pdfium fuzz engine) 0 entries in PCLR box.
!opj_decompress -i @INPUT_NR_PATH@/issue429.jp2 -o @TEMP_PATH@/issue429.jp2.pgx
# issue 432 (from pdfium fuzz engine) Overflow in tcd tilec data size computation.
!opj_decompress -i @INPUT_NR_PATH@/issue432.jp2 -o @TEMP_PATH@/issue432.jp2.pgx
# On hosts with 64 bit size_t, opj_decompress now works.
# On hosts with 32 bit size_t, opj_decompress cannot handle this file.
# TODO: We need different test cases for both kinds of hosts. Don't run test until this works.
## opj_decompress -i @INPUT_NR_PATH@/issue432.jp2 -o @TEMP_PATH@/issue432.jp2.pgx
# issue 427 image width is 0
!opj_decompress -i @INPUT_NR_PATH@/issue427-null-image-size.jp2 -o @TEMP_PATH@/issue427-null-image-size.jp2.pgx
# issue 427 illegal tile offset
Expand Down

0 comments on commit 7fb831e

Please sign in to comment.