efl - jp2k loader - guard against openjpeg bug tha causes an abort

so... if you load a non-jp2k file using openjpeg, you can get an abort
deep inside the openjpeg library that we can't do anything about. we
set all error handlers but literally the openjpeg code has ab assert
there that causes this bug. it shouldn't and newer opengjpeg libs have
it removed, but 1.5.2 has it and this causes an untrappable crash.
this is simply bad behavior in openjpeg not allowing it to be used
safely to loade image files. the relevant backtrace:

    w=w@entry=0x7fffffffb548, h=h@entry=0x7fffffffb54c,
    alpha=alpha@entry=0x7fffffffb556 "", map=map@entry=0x7fff29ac2000,
    length=<optimized out>, error=error@entry=0x7fffffffb5bc,
    opts=<optimized out>)
    at modules/evas/image_loaders/jp2k/evas_image_load_jp2k.c:111

the relevant code in openjpeg:

int cio_numbytesleft(opj_cio_t *cio) {
  assert((cio->end - cio->bp) >= 0);
        return cio->end - cio->bp;
}

so that assert is triggered. and nothing can be done about it which is
pretty poor.

so an upgrade of openjpeg should fix this as in newer versions have
dropped the assert line in that function, but until poeople have that from
their distro, this adds magic number checks for file headers that avoids
using openjpeg if it's not "apparently" a jp2k file. this does not
stop a corrupt file or a maliciously designed file still causing this
problem, but it does just result in an abort() and isnn't seemingly an
overflow isse that can be exploted, so if you still suffer, find a way to
upgrade openjpeg to 2.x. until then... this reduces inadvertent damage.

@fix
This commit is contained in:
Carsten Haitzler 2015-08-24 11:39:12 +09:00
parent b6d2dc2cdf
commit bdebfe7962
1 changed files with 14 additions and 8 deletions

View File

@ -68,6 +68,10 @@ evas_image_load_file_head_jp2k_internal(unsigned int *w, unsigned int *h,
opj_image_t *image;
int format;
int k;
const unsigned char sig_j2k[2] =
{ 0xff, 0x4f };
const unsigned char sig_jp2[10] =
{ 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a };
if (length < 2)
{
@ -75,10 +79,9 @@ evas_image_load_file_head_jp2k_internal(unsigned int *w, unsigned int *h,
return EINA_FALSE;
}
if (((unsigned char *)map)[0] == 0xFF && ((unsigned char *)map)[1] == 0x4F)
format = CODEC_J2K;
else
format = CODEC_JP2;
if ((length >= 2) && (!memcmp(map, sig_j2k, 2))) format = CODEC_J2K;
else if ((length >= 10) && (!memcmp(map, sig_jp2, 10))) format = CODEC_JP2;
else return EINA_FALSE;
memset(&event_mgr, 0, sizeof(event_mgr));
event_mgr.error_handler = _jp2k_error_cb;
@ -153,11 +156,14 @@ evas_image_load_file_data_jp2k_internal(Evas_Image_Load_Opts *opts EINA_UNUSED,
unsigned int *iter;
int format;
int idx;
const unsigned char sig_j2k[2] =
{ 0xff, 0x4f };
const unsigned char sig_jp2[10] =
{ 0x00, 0x00, 0x00, 0x0c, 0x6a, 0x50, 0x20, 0x20, 0x0d, 0x0a };
if (((unsigned char *)map)[0] == 0xFF && ((unsigned char *)map)[1] == 0x4F)
format = CODEC_J2K;
else
format = CODEC_JP2;
if ((length >= 2) && (!memcmp(map, sig_j2k, 2))) format = CODEC_J2K;
else if ((length >= 10) && (!memcmp(map, sig_jp2, 10))) format = CODEC_JP2;
else return EINA_FALSE;
opj_set_default_decoder_parameters(&params);
info = opj_create_decompress(format);