From e23e0c94d0eb30623bc67be19c38c22ee5378344 Mon Sep 17 00:00:00 2001 From: Even Rouault Date: Sun, 30 Jul 2017 16:48:15 +0200 Subject: [PATCH] Avoid p_stream->m_user_data_length >= (OPJ_UINT64)p_stream->m_byte_offset assertion in opj_stream_get_number_byte_left(). Fixes https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=2786. Credit to OSS Fuzz --- src/lib/openjp2/cio.c | 20 ++++++++++++++++++++ src/lib/openjp2/jp2.c | 17 +++++++++++++---- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/lib/openjp2/cio.c b/src/lib/openjp2/cio.c index 224fdbe2..4fde9fe2 100644 --- a/src/lib/openjp2/cio.c +++ b/src/lib/openjp2/cio.c @@ -496,6 +496,26 @@ OPJ_OFF_T opj_stream_read_skip(opj_stream_private_t * p_stream, } while (p_size > 0) { + /* Check if we are going beyond the end of file. Most skip_fn do not */ + /* check that, but we must be careful not to advance m_byte_offset */ + /* beyond m_user_data_length, otherwise */ + /* opj_stream_get_number_byte_left() will assert. */ + if ((OPJ_UINT64)(p_stream->m_byte_offset + l_skip_nb_bytes + p_size) > + p_stream->m_user_data_length) { + opj_event_msg(p_event_mgr, EVT_INFO, "Stream reached its end !\n"); + + p_stream->m_byte_offset += l_skip_nb_bytes; + l_skip_nb_bytes = (OPJ_OFF_T)(p_stream->m_user_data_length - + (OPJ_UINT64)p_stream->m_byte_offset); + + opj_stream_read_seek(p_stream, (OPJ_OFF_T)p_stream->m_user_data_length, + p_event_mgr); + p_stream->m_status |= OPJ_STREAM_STATUS_END; + + /* end if stream */ + return l_skip_nb_bytes ? l_skip_nb_bytes : (OPJ_OFF_T) - 1; + } + /* we should do an actual skip on the media */ l_current_skip_nb_bytes = p_stream->m_skip_fn(p_size, p_stream->m_user_data); if (l_current_skip_nb_bytes == (OPJ_OFF_T) - 1) { diff --git a/src/lib/openjp2/jp2.c b/src/lib/openjp2/jp2.c index 904265da..66e058a2 100644 --- a/src/lib/openjp2/jp2.c +++ b/src/lib/openjp2/jp2.c @@ -2367,10 +2367,19 @@ static OPJ_BOOL opj_jp2_read_header_procedure(opj_jp2_t *jp2, jp2->jp2_state |= JP2_STATE_UNKNOWN; if (opj_stream_skip(stream, l_current_data_size, p_manager) != l_current_data_size) { - opj_event_msg(p_manager, EVT_ERROR, - "Problem with skipping JPEG2000 box, stream error\n"); - opj_free(l_current_data); - return OPJ_FALSE; + if (jp2->jp2_state & JP2_STATE_CODESTREAM) { + /* If we already read the codestream, do not error out */ + /* Needed for data/input/nonregression/issue254.jp2 */ + opj_event_msg(p_manager, EVT_WARNING, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_TRUE; + } else { + opj_event_msg(p_manager, EVT_ERROR, + "Problem with skipping JPEG2000 box, stream error\n"); + opj_free(l_current_data); + return OPJ_FALSE; + } } } }