Jump to content



Strange libpng/zlib crash

  • You cannot reply to this topic
3 replies to this topic

#1 Daggerbot   Members   -  Reputation: 127

Like
0Likes
Like

Posted 09 February 2012 - 11:00 AM

I've used libpng for loading images many times before, but I'm getting a crash that I've never seen before. I tried two different versions of libpng with the same results, so the problem appears to be with zlib. Here's the code for my PNG loader:

bool base::Image::load_png (IODevice &in)
{
  png_byte                       signature [PNG_SIG_SIZE] = {0};
  PNGReader                      png;
  PixelFormat                    format;
  boost::scoped_array rows;

  try
  {
	// Check signature
	in.read(signature, PNG_SIG_SIZE);

	if (png_sig_cmp(signature, 0, PNG_SIG_SIZE) != 0)
	{
	  throw std::logic_error("Stream is not a PNG image");
	}

	// Setup input
	png_set_read_fn(png.readp, &in, &on_png_read);
	png_set_sig_bytes(png.readp, PNG_SIG_SIZE);

	// Get info and allocate image
	png_read_info(png.readp, png.infop);

	switch (png_get_color_type(png.readp, png.infop))
	{
	  case PNG_COLOR_TYPE_GRAY:
		format = LUM_8;
		break;

	  case PNG_COLOR_TYPE_GRAY_ALPHA:
		format = LUM_ALPHA_8;
		break;

	  case PNG_COLOR_TYPE_PALETTE:
	  case PNG_COLOR_TYPE_RGB:
		format = RGB_8;
		break;

	  case PNG_COLOR_TYPE_RGB_ALPHA:
		format = RGB_ALPHA_8;
		break;

	  default:
		throw std::invalid_argument("Invalid PNG color type");
	}

	reset(Vec2u(png_get_image_width(png.readp, png.infop), png_get_image_height(png.readp, png.infop)), format, NULL, 0);

	// Setup transformations
	png_set_expand(png.readp);
	png_set_strip_16(png.readp);
	png_set_packing(png.readp);

	// Read data
	rows.reset(new png_bytep [size.y]);

	for (unsigned int y = 0; y < size.y; y++)
	{
	  rows[y] = &data.get()[y * pitch];
	}

	png_read_image(png.readp, rows.get());

	// Finish
	return true;
  }
  catch (const std::exception &e)
  {
	destroy();
	error_string = e.what();
	return false;
  }
}

PNGReader is just a basic structure that creates and destroys the PNG structs in a way that takes advantage of RAII.

struct PNGReader
{
  png_structp readp;
  png_infop infop;

  // Constructor
  PNGReader ()
	: readp(NULL), infop(NULL)
  {
	readp = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, &on_png_error, &on_png_warning);

	if (!readp)
	{
	  throw std::runtime_error("png_create_read_struct failed");
	}

	infop = png_create_info_struct(readp);

	if (!infop)
	{
	  throw std::runtime_error("png_create_info_struct failed");
	}
  }

  // Destructor
  ~PNGReader ()
  {
	if (infop)
	{
	  png_destroy_read_struct(&readp, &infop, NULL);
	}
	else if (readp)
	{
	  png_destroy_read_struct(&readp, NULL, NULL);
	}
  }
};

I can't find any problems in my code that would cause zlib to crash. I even replaced the PNGReader struct with manual calls and got the same results. Here's the stack trace:

#0 0x00007ffff6676975 in raise () from /lib/libc.so.6
#1 0x00007ffff6677deb in abort () from /lib/libc.so.6
#2 0x00007ffff66b36ae in __libc_message () from /lib/libc.so.6
#3 0x00007ffff66b9326 in malloc_printerr () from /lib/libc.so.6
#4 0x00007ffff4b8fb5a in inflateEnd () from /usr/lib/libz.so.1
#5 0x00007ffff7749707 in ?? () from /usr/lib/libpng15.so.15
#6 0x00007ffff774997a in png_destroy_read_struct () from /usr/lib/libpng15.so.15
#7 0x000000000040e8c7 in PNGReader::~PNGReader (this=0x7fffffffe410, __in_chrg=<optimized out="">) at src/base/image_png.cpp:78
#8 0x000000000040e507 in base::Image::load_png (this=0x7fffffffe4f0, in=...) at src/base/image_png.cpp:166
#9 0x0000000000406244 in get_texture (path=...) at src/resource.cpp:94
#10 0x000000000040b307 in vd_main (args=...) at src/main.cpp:36
#11 0x000000000040b523 in main (argc=1, argv=0x7fffffffe7f8) at src/main.cpp:75

Has anyone had a similar error when using libpng or zlib? Any help is appreciated.</optimized></png_bytep>

Ad:

#2 Adam_42   Members   -  Reputation: 1030

Like
0Likes
Like

Posted 09 February 2012 - 12:06 PM

Based on that call stack I'd say something has probably trashed memory. Try using Valgrind or another memory checking tool.

#3 Krohm   Members   -  Reputation: 560

Like
0Likes
Like

Posted 09 February 2012 - 11:50 PM

I had a problem with it some time ago on Visual C++ 2008. I'm afraid it might not be your problem as I don't know your platform.

It turns out zlib has been linked vs the wrong runtime library. This caused a collision; the "internet solution" was to use /NODEFAULTLIB.
Now the linker would happily not complain about the error: it would just carry along with the wrong links. So it appears that somehow zlib used release free instead of debug. This wreaked memory big way.

#4 edd²   Members   -  Reputation: 1170

Like
0Likes
Like

Posted 10 February 2012 - 02:09 PM

Have you stepped through the code to check that libpng isn't failing and calling longjmp() to report the error? I don't see any setjmp calls anywhere to "catch" these errors.






We are working on generating results for this topic
PARTNERS