ITK: Crash when use ImageFileReader read jpeg

Description

If compile with release version. When I use ImageFileReader read some broke jpeg image, it’s crash in Update function. I expected throw an exception. But success in Debug.

Steps to Reproduce

Build With Release. https://gist.github.com/Hconk/5b1bed75ebb3c62757277a1367d61edb

Expected behavior

If image broke, expect throw an exception.

Actual behavior

Crash at update.

image

image

Reproducibility

Release Version.

Versions

c4960ee19c

Environment

  • CMake: 3.21.1
  • OS: Centos 7.3 / Windows 10
  • ITK Version: 5.2.1 / master branch
  • compile: gcc10.2 / gcc 4.8 / vs2017

Additional Information

Test data. Google Drive

211869_09365_55_55

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 19 (13 by maintainers)

Commits related to this issue

Most upvoted comments

@dzenanz @issakomi I found some specially constructed png image also cause crash. When I use PNGImageIO read it ,will got some libpng error infomation libpng error: PNG unsigned integer out of range then crash. I think it’s need throw exception. Although it is not generated in a real scene, may also need to be fixed. (Maybe need open a new issue.)

Example test data: https://drive.google.com/file/d/1wRMTQlz31lwccha9hdPb-uTwNXD77nZv/view?usp=sharing image sha256: f82d996c02975eecbdf0823bad5047124d3d146a0fb8804e377c35838ed264b8 Good image:

λ Desktop itk_demo → cat ./good.png | xxd -u
00000000: 8950 4E47 0D0A 1A0A 0000 000D 4948 4452  .PNG........IHDR
00000010: 0000 0001 0000 0001 0100 0000 0037 6EF9  .............7n.
00000020: 2400 0000 1049 4441 5478 9C62 6001 0000  $....IDATx.b`...
00000030: 00FF FF03 0000 0600 0557 BFAB D400 0000  .........W......
00000040: 0049 454E 44AE 4260 82                   .IEND.B`.

Broken png image hex:

λ Desktop itk_demo → cat ./corrupted.png | xxd -u
00000000: 8950 4E47 0D0A 1A0A 0000 000D 4948 4452  .PNG........IHDR
00000010: 0000 0001 0000 0001 0100 0000 0037 6EF9  .............7n.
00000020: 24FF 0000 1049 4441 5478 9C62 6001 0000  $....IDATx.b`...
00000030: 00FF FF03 0000 0600 0557 BFAB D400 0000  .........W......
00000040: 0049 454E 44AE 4260 82                   .IEND.B`.

The difference between the two pictures is at the 0x21st byte.

@issakomi Thanks, I validate your patch code, It’s work for me, This problem has bothered me for a long time.

Probably i have done a temporary fixed… The error happens in jpeg_destroy_decompress(&cinfo); I have re-written several times the Read function to find it out and tested additionally with version 4.12 with system JPEG (also crashed, BTW). So finally i looked inside Gimp code (Gimp doesn’t fail on the file). The minimal solution is to add if (setjmp (jerr.setjmp_buffer)) block at the beginning of the while loop

  // read the bulk data
  unsigned int remainingRows;
  while (cinfo.output_scanline < cinfo.output_height)
  {
////////////////////////////////
    if (setjmp (jerr.setjmp_buffer))
    {
      std::cout << "goto quit:" << std::endl;
      goto quit;
    }
////////////////////////////////
    remainingRows = cinfo.output_height - cinfo.output_scanline;
    jpeg_read_scanlines(&cinfo, &row_pointers[cinfo.output_scanline], remainingRows);
  }

and quit: before jpeg_destroy_decompress at the end of Read function, to skip jpeg_finish_decompress call in case of an error.

quit:             // <-------------------
  // destroy the decompression object
  jpeg_destroy_decompress(&cinfo);

  delete[] row_pointers;
}

@Hconk Maybe you could validate?

P.S. Please don’t write me that “goto” is bad. It is not the final solution, it is minimal working for now.