diff --git a/src/coders/png.cpp b/src/coders/png.cpp index a6c3f9e6..7c469e32 100644 --- a/src/coders/png.cpp +++ b/src/coders/png.cpp @@ -164,12 +164,22 @@ static void read_in_memory(png_structp pngPtr, png_bytep dst, png_size_t toread) reader.offset += toread; } +void png_error_handler(png_structp pngPtr, png_const_charp errorMessage) { + logger.error() << "libpng error: " << errorMessage; + if (pngPtr) { + longjmp(png_jmpbuf(pngPtr), 1); + } + abort(); // Should not be reached if longjmp works +} + std::unique_ptr png::load_image(const ubyte* bytes, size_t size) { if (size < 8 || !png_check_sig(bytes, 8)) { throw std::runtime_error("invalid png signature"); } png_structp pngPtr = nullptr; - pngPtr = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr); + pngPtr = png_create_read_struct( + PNG_LIBPNG_VER_STRING, nullptr, png_error_handler, nullptr + ); if (pngPtr == nullptr) { throw std::runtime_error("failed png_create_read_struct"); } @@ -180,6 +190,11 @@ std::unique_ptr png::load_image(const ubyte* bytes, size_t size) { throw std::runtime_error("failed png_create_info_struct"); } + if (setjmp(png_jmpbuf(pngPtr))) { + png_destroy_read_struct(&pngPtr, &infoPtr, nullptr); + throw std::runtime_error("failed to decode png"); + } + InMemoryReader reader {bytes, size, 0}; png_set_read_fn(pngPtr, &reader, read_in_memory);