[Insight-users] Very strange crashing bug with JPEG input
Zachary Pincus
zpincus at stanford.edu
Tue, 17 Feb 2004 22:00:33 -0800
Hello all,
After a lot of debugging, I think I have isolated a crashing bug in
ITK's JPEG reader.
SUMARRY: If you try create a new ImageFileReader and use the new reader
to read in a JPEG more than 84 times, the program crashes. The specific
file being read doesn't matter -- what's important is that the
ImageFileReader is created, passed a jpeg file name, Update()'d and
deleted more than 84 times.
Interestingly, if the program that does this is run within GDB, there
is no error until after 3411 repeats of the same.
This points to a subtle buffer overflow in some shared memory region.
When GDB is running, memory is laid out differently, so it takes longer
for some overflows to manifest themselves (I think).
DETAILS: I'm using a CVS checkout of ITK from Sunday. There weren't any
major purify errors that day, that I noticed. I'm running on OS X
10.3.2.
Included is some simple test code that creates new FileReader objects
each loop and opens the file passed in as an argument. The program will
do fine on my machine with any file type except jpegs, with which the
afformentioned crash happens. Any jpeg will elicit this behavior. The
size of the image is immaterial to this crash. The templated pixel type
doesn't matter either.
If you modify the test code to alternate between two different files
(e.g. fileReader->SetFileName(argv[1 + i % 2])) , it will still crash
after the 84th loop, provided both files are jpegs. If one isn't a
jpeg, it crashes after 168th loop. If you create two file readers each
loop, it crashes after the 42nd loop. Ditto even if the file readers
are reading different jpeg files. If one of the two file readers isn't
reading a jpeg, it takes 84 loops to crash again.
Again, this points to an overflow in some shared buffer that is
accessed by JPEG readers.
If Update() is not called each loop, there is no crash. If the
ImageFileReader::Pointer is created outside of the loop's scope (so the
reader isn't destructed every loop) there is no crash.
If the program is run from within GDB, it takes 3411 loops for the
crash to occur. The GDB backtrace of the core dump of a crash after 84
loops outside of GDB and of a crash after 3411 loops within GDB are
substantially different. I have also attached these backtraces to this
message, in case anyone can make use of them.
Any thoughts?
Zach Pincus
Department of Biochemistry and Program in Biomedical Informatics
Stanford University School of Medicine
TEST CODE:
//-----------------------------
#include "itkImage.h"
#include "itkImageFileReader.h"
int main(int argc, char **argv){
for(int i = 0; i < 4000; i++) {
typedef unsigned char PixelType;
const unsigned int Dimension = 2;
typedef itk::Image<PixelType, Dimension> ImageType;
typedef itk::ImageFileReader<ImageType> ReaderType;
ReaderType::Pointer fileReader = ReaderType::New();
fileReader->SetFileName(argv[1]);
fileReader->Update();
std::cout << i << std::endl;
}
}
//---------------------------------
GDB backtrace of this code run within GDB (crashes after 3411 loops)
------------------------------------
Program received signal EXC_BAD_ACCESS, Could not access memory.
0x9001c878 in fclose ()
(gdb) bt
#0 0x9001c878 in fclose ()
#1 0x010bfb70 in itk::JPEGFileWrapper::~JPEGFileWrapper() ()
#2 0x010bfa28 in itk::JPEGFileWrapper::~JPEGFileWrapper() ()
#3 0x0101bf68 in itk::JPEGImageIO::CanReadFile(char const*) ()
#4 0x01029004 in itk::ImageIOFactory::CreateImageIO(char const*,
itk::ImageIOFactory::FileModeType) ()
#5 0x000501d4 in itk::ImageFileReader<itk::Image<unsigned char, 2>,
itk::DefaultConvertPixelTraits<unsigned char>
>::GenerateOutputInformation() ()
#6 0x0047c264 in itk::ProcessObject::UpdateOutputInformation() ()
#7 0x00052618 in itk::ImageBase<2>::UpdateOutputInformation() ()
#8 0x0046a17c in itk::DataObject::Update() ()
#9 0x0047be50 in itk::ProcessObject::Update() ()
#10 0x00002a54 in main ()
#11 0x000026d0 in _start (argc=2, argv=0xbffffa60, envp=0xbffffa6c) at
/SourceCache/Csu/Csu-46/crt.c:267
#12 0x00002544 in start ()
GDB backtrace of a core dump generated by this code run outside GDB
(crashes after 84 loops)
------------------------------------
#0 0x90042aac in kill ()
#1 0x9009ec5c in abort ()
#2 0x012df9b8 in ?? ()
#3 0x012df9fc in ?? ()
#4 0x9009ec34 in abort ()
#5 0x0127e498 in ?? ()
#6 0x000503e8 in std::vector<std::string, std::allocator<std::string>
>::~vector() ()
#7 0x0101e264 in ?? ()
#8 0x00052618 in std::invalid_argument::~invalid_argument() ()
#9 0x0100c17c in ?? ()
#10 0x0101de50 in ?? ()
#11 0x00002a54 in
itk::InvalidRequestedRegionError::InvalidRequestedRegionError(std::
string const&, unsigned) ()
#12 0x000026d0 in itk::DataObjectError::GetDataObject() () at
/SourceCache/Csu/Csu-46/crt.c:267
#13 0x00002544 in itk::DataObjectError::DataObjectError(std::string
const&, unsigned) ()