Support files with very large data size

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 #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 #432 is disabled.

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

Update also some comments in the test suite.

Signed-off-by: Stefan Weil <sw@weilnetz.de>
This commit is contained in:
Stefan Weil 2016-03-28 11:15:43 +02:00
parent bc71bd1219
commit 381f9676b3
4 changed files with 27 additions and 24 deletions

View File

@ -738,7 +738,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]);
@ -795,21 +795,21 @@ 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 = (size_t)(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 -
((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);
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;
@ -824,15 +824,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);
} else if (l_data_size > l_tilec->resolutions_size) {
@ -846,7 +845,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;
@ -1187,14 +1186,14 @@ static OPJ_BOOL opj_tcd_code_block_enc_allocate(opj_tcd_cblk_enc_t *
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;
/* +1 is needed for https://github.com/uclouvain/openjpeg/issues/835 */
/* and actually +2 required for https://github.com/uclouvain/openjpeg/issues/982 */
/* TODO: is there a theoretical upper-bound for the compressed code */
/* block size ? */
l_data_size = 2 + (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 = 2 + ((size_t)(p_code_block->x1 - p_code_block->x0) *
(size_t)(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) {
@ -1604,13 +1603,13 @@ OPJ_BOOL opj_tcd_update_tile_data(opj_tcd_t *p_tcd,
static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
{
OPJ_UINT32 compno, resno, bandno, precno;
OPJ_UINT32 compno, bandno, precno;
opj_tcd_tile_t *l_tile = 00;
opj_tcd_tilecomp_t *l_tile_comp = 00;
opj_tcd_resolution_t *l_res = 00;
opj_tcd_band_t *l_band = 00;
opj_tcd_precinct_t *l_precinct = 00;
OPJ_UINT32 l_nb_resolutions, l_nb_precincts;
OPJ_UINT32 l_nb_precincts;
void (* l_tcd_code_block_deallocate)(opj_tcd_precinct_t *) = 00;
if (! p_tcd) {
@ -1637,8 +1636,8 @@ static void opj_tcd_free_tile(opj_tcd_t *p_tcd)
for (compno = 0; compno < l_tile->numcomps; ++compno) {
l_res = l_tile_comp->resolutions;
if (l_res) {
l_nb_resolutions = l_tile_comp->resolutions_size / sizeof(opj_tcd_resolution_t);
size_t resno;
size_t l_nb_resolutions = l_tile_comp->resolutions_size / sizeof(opj_tcd_resolution_t);
for (resno = 0; resno < l_nb_resolutions; ++resno) {
l_band = l_res->bands;
for (bandno = 0; bandno < 3; ++bandno) {

View File

@ -82,7 +82,7 @@ typedef struct opj_tcd_cblk_enc {
y1; /* dimension of the code-blocks : left upper corner (x0, y0) right low corner (x1,y1) */
OPJ_UINT32 numbps;
OPJ_UINT32 numlenbits;
OPJ_UINT32 data_size; /* Size of allocated data buffer */
size_t data_size; /* Size of allocated data buffer */
OPJ_UINT32
numpasses; /* number of pass already done for the code-blocks */
OPJ_UINT32 numpassesinlayers; /* number of passes in the layer */
@ -190,15 +190,15 @@ typedef struct opj_tcd_tilecomp {
/* resolutions information */
opj_tcd_resolution_t *resolutions;
/* size of data for resolutions (in bytes) */
OPJ_UINT32 resolutions_size;
size_t resolutions_size;
/* data of the component */
OPJ_INT32 *data;
/* if true, then need to free after usage, otherwise do not free */
OPJ_BOOL ownsData;
/* we may either need to allocate this amount of data, or re-use image data and ignore this value */
OPJ_UINT32 data_size_needed;
size_t data_size_needed;
/* size of the data of the component */
OPJ_UINT32 data_size;
size_t data_size;
/* add fixed_quality */
OPJ_INT32 numpix;
} opj_tcd_tilecomp_t;

View File

@ -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

View File

@ -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
@ -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
@ -350,7 +350,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