static void opj_jp2_setup_header_reading (opj_jp2_t *jp2);
/* ----------------------------------------------------------------------- */
-
OPJ_BOOL opj_jp2_read_boxhdr(opj_jp2_box_t *box,
- OPJ_UINT32 * p_number_bytes_read,
- opj_stream_private_t *cio,
- opj_event_mgr_t * p_manager
- )
+ OPJ_UINT32 * p_number_bytes_read,
+ opj_stream_private_t *cio,
+ opj_event_mgr_t * p_manager )
{
/* read header from file */
OPJ_BYTE l_data_header [8];
/* process read data */
opj_read_bytes(l_data_header,&(box->length), 4);
opj_read_bytes(l_data_header+4,&(box->type), 4);
+
+ if(box->length == 0)/* last box */
+ {
+ box->length = opj_stream_get_number_byte_left(cio);
+ return OPJ_TRUE;
+ }
/* do we have a "special very large box ?" */
/* read then the XLBox */
return OPJ_FALSE;
}
+ *p_number_bytes_read = 16;
opj_read_bytes(l_data_header,&l_xl_part_size, 4);
if (l_xl_part_size != 0) {
opj_event_msg(p_manager, EVT_ERROR, "Cannot handle box sizes higher than 2^32\n");
return OPJ_FALSE;
}
- opj_read_bytes(l_data_header,&(box->length), 4);
+ opj_read_bytes(l_data_header+4,&(box->length), 4);
}
- return OPJ_TRUE;
+ return OPJ_TRUE;
}
#if 0
/* preconditions */
assert(jp2 != 00);
assert(p_nb_bytes_written != 00);
+ assert(jp2->meth == 1 || jp2->meth == 2);
- switch (jp2->meth) {
+ switch (jp2->meth) {
case 1 :
- l_colr_size += 4;
+ l_colr_size += 4; /* EnumCS */
break;
case 2 :
- ++l_colr_size;
+ assert(jp2->color.icc_profile_len); /* ICC profile */
+ l_colr_size += jp2->color.icc_profile_len;
break;
default :
return 00;
opj_write_bytes(l_current_colr_ptr, jp2->approx,1); /* APPROX */
++l_current_colr_ptr;
- if (jp2->meth == 1) {
- opj_write_bytes(l_current_colr_ptr, jp2->enumcs,4); /* EnumCS */
- }
- else {
- opj_write_bytes(l_current_colr_ptr, 0, 1); /* PROFILE (??) */
+ if (jp2->meth == 1) { /* Meth value is restricted to 1 or 2 (Table I.9 of part 1) */
+ opj_write_bytes(l_current_colr_ptr, jp2->enumcs,4); } /* EnumCS */
+ else {
+ if (jp2->meth == 2) { /* ICC profile */
+ OPJ_UINT32 i;
+ for(i = 0; i < jp2->color.icc_profile_len; ++i) {
+ opj_write_bytes(l_current_colr_ptr, jp2->color.icc_profile_buf[i], 1);
+ ++l_current_colr_ptr;
+ }
+ }
}
*p_nb_bytes_written = l_colr_size;
opj_free(color->jp2_pclr); color->jp2_pclr = NULL;
}
+static OPJ_BOOL opj_jp2_check_color(opj_image_t *image, opj_jp2_color_t *color, opj_event_mgr_t *p_manager)
+{
+ OPJ_UINT16 i;
+
+ /* testcase 4149.pdf.SIGSEGV.cf7.3501 */
+ if (color->jp2_cdef) {
+ opj_jp2_cdef_info_t *info = color->jp2_cdef->info;
+ OPJ_UINT16 n = color->jp2_cdef->n;
+
+ for (i = 0; i < n; i++) {
+ if (info[i].cn >= image->numcomps) {
+ opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].cn, image->numcomps);
+ return OPJ_FALSE;
+ }
+ if (info[i].asoc > 0 && (OPJ_UINT32)(info[i].asoc - 1) >= image->numcomps) {
+ opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", info[i].asoc - 1, image->numcomps);
+ return OPJ_FALSE;
+ }
+ }
+ }
+
+ /* testcases 451.pdf.SIGSEGV.f4c.3723, 451.pdf.SIGSEGV.5b5.3723 and
+ 66ea31acbb0f23a2bbc91f64d69a03f5_signal_sigsegv_13937c0_7030_5725.pdf */
+ if (color->jp2_pclr && color->jp2_pclr->cmap) {
+ OPJ_UINT16 nr_channels = color->jp2_pclr->nr_channels;
+ opj_jp2_cmap_comp_t *cmap = color->jp2_pclr->cmap;
+ OPJ_BOOL *pcol_usage, is_sane = OPJ_TRUE;
+
+ /* verify that all original components match an existing one */
+ for (i = 0; i < nr_channels; i++) {
+ if (cmap[i].cmp >= image->numcomps) {
+ opj_event_msg(p_manager, EVT_ERROR, "Invalid component index %d (>= %d).\n", cmap[i].cmp, image->numcomps);
+ is_sane = OPJ_FALSE;
+ }
+ }
+
+ pcol_usage = opj_calloc(nr_channels, sizeof(OPJ_BOOL));
+ if (!pcol_usage) {
+ opj_event_msg(p_manager, EVT_ERROR, "Unexpected OOM.\n");
+ return OPJ_FALSE;
+ }
+ /* verify that no component is targeted more than once */
+ for (i = 0; i < nr_channels; i++) {
+ OPJ_UINT16 pcol = cmap[i].pcol;
+ if (pcol >= nr_channels) {
+ opj_event_msg(p_manager, EVT_ERROR, "Invalid component/palette index for direct mapping %d.\n", pcol);
+ is_sane = OPJ_FALSE;
+ }
+ else if (pcol_usage[pcol]) {
+ opj_event_msg(p_manager, EVT_ERROR, "Component %d is mapped twice.\n", pcol);
+ is_sane = OPJ_FALSE;
+ }
+ else
+ pcol_usage[pcol] = OPJ_TRUE;
+ }
+ /* verify that all components are targeted at least once */
+ for (i = 0; i < nr_channels; i++) {
+ if (!pcol_usage[i]) {
+ opj_event_msg(p_manager, EVT_ERROR, "Component %d doesn't have a mapping.\n", i);
+ is_sane = OPJ_FALSE;
+ }
+ }
+ opj_free(pcol_usage);
+ if (!is_sane) {
+ return OPJ_FALSE;
+ }
+ }
+
+ return OPJ_TRUE;
+}
+
void opj_jp2_apply_pclr(opj_image_t *image, opj_jp2_color_t *color)
{
opj_image_comp_t *old_comps, *new_comps;
OPJ_UINT16 nr_entries,nr_channels;
OPJ_UINT16 i, j;
OPJ_UINT32 l_value;
+ OPJ_BYTE *orig_header_data = p_pclr_header_data;
/* preconditions */
assert(p_pclr_header_data != 00);
if(jp2->color.jp2_pclr)
return OPJ_FALSE;
+ if (p_pclr_header_size < 3)
+ return OPJ_FALSE;
+
opj_read_bytes(p_pclr_header_data, &l_value , 2); /* NE */
p_pclr_header_data += 2;
nr_entries = (OPJ_UINT16) l_value;
++p_pclr_header_data;
nr_channels = (OPJ_UINT16) l_value;
+ if (p_pclr_header_size < 3 + (OPJ_UINT32)nr_channels || nr_channels == 0 || nr_entries >= (OPJ_UINT32)-1 / nr_channels)
+ return OPJ_FALSE;
+
entries = (OPJ_UINT32*) opj_malloc(nr_channels * nr_entries * sizeof(OPJ_UINT32));
if (!entries)
return OPJ_FALSE;
for(i = 0; i < nr_channels; ++i) {
OPJ_INT32 bytes_to_read = (channel_size[i]+7)>>3;
+ if (bytes_to_read > sizeof(OPJ_UINT32))
+ bytes_to_read = sizeof(OPJ_UINT32);
+ if ((ptrdiff_t)p_pclr_header_size < p_pclr_header_data - orig_header_data + bytes_to_read)
+ return OPJ_FALSE;
+
+ if (bytes_to_read > sizeof(OPJ_UINT32))
+ bytes_to_read = sizeof(OPJ_UINT32);
+ if ((ptrdiff_t)p_pclr_header_size < p_pclr_header_data - orig_header_data + bytes_to_read)
+ return OPJ_FALSE;
+
opj_read_bytes(p_pclr_header_data, &l_value , bytes_to_read); /* Cji */
p_pclr_header_data += bytes_to_read;
*entries = (OPJ_UINT32) l_value;
}
nr_channels = jp2->color.jp2_pclr->nr_channels;
+ if (p_cmap_header_size < (OPJ_UINT32)nr_channels * 4) {
+ opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CMAP box.\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_cmap_header_size < (OPJ_UINT32)nr_channels * 4) {
+ opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CMAP box.\n");
+ return OPJ_FALSE;
+ }
+
cmap = (opj_jp2_cmap_comp_t*) opj_malloc(nr_channels * sizeof(opj_jp2_cmap_comp_t));
if (!cmap)
return OPJ_FALSE;
for(i = 0; i < n; ++i)
{
/* WATCH: acn = asoc - 1 ! */
- if((asoc = info[i].asoc) == 0) continue;
+ if((asoc = info[i].asoc) == 0)
+ {
+ if (i < image->numcomps)
+ image->comps[i].alpha = info[i].typ;
+ continue;
+ }
cn = info[i].cn;
acn = asoc - 1;
info[i].asoc = cn + 1;
info[acn].asoc = info[acn].cn + 1;
}
+
+ image->comps[cn].alpha = info[i].typ;
}
if(color->jp2_cdef->info) opj_free(color->jp2_cdef->info);
* inside a JP2 Header box.'*/
if(jp2->color.jp2_cdef) return OPJ_FALSE;
+ if (p_cdef_header_size < 2) {
+ opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_cdef_header_size < 2) {
+ opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n");
+ return OPJ_FALSE;
+ }
+
opj_read_bytes(p_cdef_header_data,&l_value ,2); /* N */
p_cdef_header_data+= 2;
return OPJ_FALSE;
}
+ if (p_cdef_header_size < 2 + (OPJ_UINT32)(OPJ_UINT16)l_value * 6) {
+ opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n");
+ return OPJ_FALSE;
+ }
+
+ if (p_cdef_header_size < 2 + (OPJ_UINT32)(OPJ_UINT16)l_value * 6) {
+ opj_event_msg(p_manager, EVT_ERROR, "Insufficient data for CDEF box.\n");
+ return OPJ_FALSE;
+ }
+
cdef_info = (opj_jp2_cdef_info_t*) opj_malloc(l_value * sizeof(opj_jp2_cdef_info_t));
if (!cdef_info)
return OPJ_FALSE;
++p_colr_header_data;
if (jp2->meth == 1) {
- if (p_colr_header_size != 7) {
- opj_event_msg(p_manager, EVT_ERROR, "Bad BPCC header box (bad size)\n");
+ if (p_colr_header_size < 7) {
+ opj_event_msg(p_manager, EVT_ERROR, "Bad COLR header box (bad size: %d)\n", p_colr_header_size);
return OPJ_FALSE;
}
+ if (p_colr_header_size > 7) {
+ /* testcase Altona_Technical_v20_x4.pdf */
+ opj_event_msg(p_manager, EVT_WARNING, "Bad COLR header box (bad size: %d)\n", p_colr_header_size);
+ }
opj_read_bytes(p_colr_header_data,&jp2->enumcs ,4); /* EnumCS */
+
+ jp2->color.jp2_has_colr = 1;
}
else if (jp2->meth == 2) {
/* ICC profile */
++p_colr_header_data;
jp2->color.icc_profile_buf[it_icc_value] = (OPJ_BYTE) l_value;
}
-
+
+ jp2->color.jp2_has_colr = 1;
}
- else
- opj_event_msg(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), so we will skip the fields following the approx field.\n", jp2->meth);
-
- jp2->color.jp2_has_colr = 1;
-
- return OPJ_TRUE;
+ else if (jp2->meth > 2)
+ {
+ /* ISO/IEC 15444-1:2004 (E), Table I.9 � Legal METH values:
+ conforming JP2 reader shall ignore the entire Colour Specification box.*/
+ opj_event_msg(p_manager, EVT_INFO, "COLR BOX meth value is not a regular value (%d), "
+ "so we will ignore the entire Colour Specification box. \n", jp2->meth);
+ }
+ return OPJ_TRUE;
}
OPJ_BOOL opj_jp2_decode(opj_jp2_t *jp2,
}
if (!jp2->ignore_pclr_cmap_cdef){
+ if (!opj_jp2_check_color(p_image, &(jp2->color), p_manager)) {
+ return OPJ_FALSE;
+ }
/* Set Image Color Space */
if (jp2->enumcs == 16)
}
/* Colour Specification box */
- if ((image->numcomps == 1 || image->numcomps == 3) && (jp2->bpc != 255)) {
- jp2->meth = 1; /* METH: Enumerated colourspace */
- } else {
- jp2->meth = 2; /* METH: Restricted ICC profile */
- }
- if (jp2->meth == 1) {
- if (image->color_space == 1)
- jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */
- else if (image->color_space == 2)
- jp2->enumcs = 17; /* greyscale */
- else if (image->color_space == 3)
- jp2->enumcs = 18; /* YUV */
- } else {
- jp2->enumcs = 0; /* PROFILE (??) */
- }
+ if(image->icc_profile_len) {
+ jp2->meth = 2;
+ jp2->enumcs = 0;
+ }
+ else {
+ jp2->meth = 1;
+ if (image->color_space == 1)
+ jp2->enumcs = 16; /* sRGB as defined by IEC 61966-2-1 */
+ else if (image->color_space == 2)
+ jp2->enumcs = 17; /* greyscale */
+ else if (image->color_space == 3)
+ jp2->enumcs = 18; /* YUV */
+ }
+
+
jp2->precedence = 0; /* PRECEDENCE */
jp2->approx = 0; /* APPROX */
if (l_current_handler != 00) {
if (l_current_data_size > l_last_data_size) {
OPJ_BYTE* new_current_data = (OPJ_BYTE*)opj_realloc(l_current_data,l_current_data_size);
- if (!l_current_data){
+ if (!new_current_data) {
opj_free(l_current_data);
opj_event_msg(p_manager, EVT_ERROR, "Not enough memory to handle jpeg2000 box\n");
return OPJ_FALSE;
return OPJ_FALSE;
}
+ if (!opj_jp2_check_color(p_image, &(p_jp2->color), p_manager)) {
+ return OPJ_FALSE;
+ }
+
/* Set Image Color Space */
if (p_jp2->enumcs == 16)
p_image->color_space = OPJ_CLRSPC_SRGB;