I'm using libpng to read png files in Visual C++. The program works fine when reading image with dimensions 195x195px or less but crashes for higher dimensions.
This is the error message:
First-chance exception at 0x77662D37 (ntdll.dll) in myprog.exe: 0xC0000005: Access violation reading location 0xB4BFDDFF. Unhandled exception at 0x77662D37 (ntdll.dll) in myprog.exe: 0xC0000005: Access violation reading location 0xB4BFDDFF.
and here this the code:
bool PngImage::load(void)
{
png_structp pngPtr(NULL);
png_infop infoPtr(NULL);
FILE* fp(NULL);
png_uint_32 w = 0, h = 0;
int bit_depth, color_type, interlace_type;
fp = fopen(fileName_.c_str(), "rb");
if (!fp)
return false;
pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
if (!pngPtr)
{
fclose(fp);
return false;
}
infoPtr = png_create_info_struct(pngPtr);
if (!infoPtr)
{
fclose(fp);
png_destroy_read_struct(&pngPtr, png_infopp_NULL, png_infopp_NULL);
return false;
}
if (setjmp(png_jmpbuf(pngPtr)))
{
png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
fclose(fp);
return false;
}
png_init_io(pngPtr, fp);
if (setjmp(png_jmpbuf(pngPtr)))
{
png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
fclose(fp);
return false;
}
png_read_info(pngPtr, infoPtr);
png_get_IHDR(pngPtr, infoPtr, &w, &h,
&bit_depth, &color_type, &interlace_type,
int_p_NULL, int_p_NULL);
if (setjmp(png_jmpbuf(pngPtr)))
{
png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
fclose(fp);
return false;
}
width_ = static_cast<size_t>(w);
height_ = static_cast<size_t>(h);
data_ = new png_bytep[height_];
for (size_t i = 0; i < height_; ++i)
data_[i] = new png_byte[width_ * BYTE_PER_PIXEL];
png_read_image(pngPtr, data_);
if (setjmp(png_jmpbuf(pngPtr)))
{
png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
fclose(fp);
for (size_t i = 0; i < height_; ++i)
delete[] data_[i];
delete[] data_;
data_ = NULL;
width_ = height_ = 0;
return false;
}
png_read_end(pngPtr, infoPtr);
png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL);
fclose(fp);
return true;
}
value of the constants:
const size_t BYTE_PER_PIXEL = 3;
const size_t RED_OFFSET = 0;
const size_t GREEN_OFFSET = 1;
const size_t BLUE_OFFSET = 2;
const png_byte BIT_DEPTH = 8;
The code seem to stop at png_destroy_read_struct(&pngPtr, &infoPtr, png_infopp_NULL); before fclose(fp).
What could be the reason why I am getting an Unhandled exception? Hope you can help with this. Thank you in advance.
PS: I am not that familiar with libpng
Hypothesis: This code assumes that every image is in 24-bit/pixel RGB format.
If you read a 32-bit/pixel RGBA image or a 48-bit/pixel RGB image, then the allocation
data_[i] = new png_byte[width_ * BYTE_PER_PIXEL];
will not allocate enough bytes for each scan line.
C++ being the unsafe language that it is, the buffer overrun when reading into these too-short arrays will trash the heap data structures, which may not trigger a symptom until you try to free something.
Also, it looks like this code forgets to free the arrays in the successful case, or is data_
an instance variable intended to hold the image in memory?