imread crashing process (Bug #2602)


Added by Darko Maksimovic over 12 years ago. Updated about 12 years ago.


Status:Done Start date:2012-12-06
Priority:Normal Due date:
Assignee:Andrey Kamaev % Done:

0%

Category:highgui-images
Target version:2.4.3.2
Affected version: Operating System:
Difficulty: HW Platform:
Pull request:https://github.com/Itseez/opencv/pull/212

Description

Hi,

In short, I recommend changing grfmt_jpeg.cpp#JpegDecoder::readHeader line

jpeg_read_header( &state->cinfo, TRUE );

into:

if (state->cinfo.src != 0)
  jpeg_read_header( &state->cinfo, TRUE );

Namely, if a file is deleted right after loadsave.cpp → imread_ → findDecoder finishes, then on line libjpeg → jdapimin.c → jpeg_consume_input → [cinfo->src->init_source] we'll get a crash.

In long
We're having crashes in the aforementioned place in code when using opencv within our software, although I will need more time to conclude why it's happening exactly, since we have >20 reports and it's impossible that the customers were actually deleting their files in exact moments in time. We're probably having Unicode filenames problems as well, because you use fopen and that's bad with Windows. But this one is a bug anyway, so here it is.

The stack I'm talking about is:

3rdparty / jdapimin.c / jpeg_consume_input
3rdparty / jpeglib.h / jpeg_read_header
highgui / grfmt_jpeg.cpp / JpegDecoder::readHeader
highgui / loadsave.cpp / static void* imread_
highgui / loadsave.cpp / Mat imread( const string& filename, int flags )

In imread, checking if decoder is empty equals checking if the file exists and is readable. The important thing is, this is the last place where this condition will produce null as result of the function. I'll explain.

    ImageDecoder decoder = findDecoder(filename);
    if( decoder.empty() )
        return 0;

Imagine the file exists and is readable and findDecoder::fopen succeeds. Now imagine the file is deleted immediately after this check. imread will continue:

if( !decoder->readHeader() ) ...
...which yields to:
JpegDecoder::readHeader()
{
  ...
  else
  {
    m_f = fopen( m_filename.c_str(), "rb" );
    if( m_f )
      jpeg_stdio_src( &state->cinfo, m_f );
  }
  jpeg_read_header( &state->cinfo, TRUE );
  ...
}

Please note that now fopen will produce null, and the if (m_f) condition will fail. Therefore jpeg_stdio_src shall not be called and state->cinfo->src will still be null. However, in jpeg_read_header which follows unconditionally, jpeg_consume_input is called, and that one uses cinfo->src without checking against null:

jpeg_consume_input (j_decompress_ptr cinfo)
{
  ...
  case DSTATE_START:
    ...
        (*cinfo->src->init_source) (cinfo)  <-- src is null and segmentation fault will follow
}

Regards
Darko Maksimovic


Associated revisions

Revision 1821d21f
Added by Andrey Kamaev over 12 years ago

Prevent imread from illegal memory access (Bug #2602)

The change is based on pull request #211.

Revision 60ad505a
Added by Andrey Kamaev about 12 years ago

Merge pull request #212 from taka-no-me/fix_2602

Prevent imread from illegal memory access (Bug #2602)

History

Updated by Anna Kogan over 12 years ago

Hello Darko,

Thank you for reporting the issue! If you could fix the issue on your side, a patch or pull request there: http://opencv.org/opencv-pull-requests-test-results.html would be very appreciated!

  • Target version set to 3.0

Updated by Darko Maksimovic over 12 years ago

Hi Anna,

I created a pull request at https://github.com/Itseez/opencv/pull/209

Thanks
Darko

Anna Kogan wrote:

Hello Darko,

Thank you for reporting the issue! If you could fix the issue on your side, a patch or pull request there: http://opencv.org/opencv-pull-requests-test-results.html would be very appreciated!

Updated by Anna Kogan over 12 years ago

Hello Darko,

Big thanks for your pull request!

Updated by Anna Kogan over 12 years ago

  • Pull request set to https://github.com/Itseez/opencv/pull/212

Updated by Andrey Kamaev about 12 years ago

The fix is pushed to 2.4 branch.

  • Status changed from Open to Done
  • Assignee changed from Vadim Pisarevsky to Andrey Kamaev
  • Target version changed from 3.0 to 2.4.4

Updated by Andrey Kamaev about 12 years ago

  • Target version changed from 2.4.4 to 2.4.3.2

Also available in: Atom PDF