Pl_DCT::finish()
{
    this->buf.finish();

    // Using a PointerHolder<Buffer> here and passing it into compress
    // and decompress causes a memory leak with setjmp/longjmp. Just
    // use a pointer and delete it.
    Buffer* b = this->buf.getBuffer();
    if (b->getSize() == 0)
    {
        // Special case: empty data will never succeed and probably
        // means we're calling finish a second time from an exception
        // handler.
        delete b;
        this->getNext()->finish();
        return;
    }

    struct jpeg_compress_struct cinfo_compress;
    struct jpeg_decompress_struct cinfo_decompress;
    struct qpdf_jpeg_error_mgr jerr;

    cinfo_compress.err = jpeg_std_error(&(jerr.pub));
    cinfo_decompress.err = jpeg_std_error(&(jerr.pub));
    jerr.pub.error_exit = error_handler;

    bool error = false;
    // The jpeg library is a "C" library, so we use setjmp and longjmp
    // for exception handling.
    if (setjmp(jerr.jmpbuf) == 0)
    {
        try
        {
            if (this->action == a_compress)
            {
                compress(reinterpret_cast<void*>(&cinfo_compress), b);
            }
            else
            {
                decompress(reinterpret_cast<void*>(&cinfo_decompress), b);
            }
        }
        catch (std::exception& e)
        {
            // Convert an exception back to a longjmp so we can ensure
            // that the right cleanup happens. This will get converted
            // back to an exception.
            jerr.msg = e.what();
            longjmp(jerr.jmpbuf, 1);
        }
    }
    else
    {
        error = true;
    }
    delete b;

    if (this->action == a_compress)
    {
        jpeg_destroy_compress(&cinfo_compress);
    }
    if (this->action == a_decompress)
    {
        jpeg_destroy_decompress(&cinfo_decompress);
    }
    if (error)
    {
        throw std::runtime_error(jerr.msg);
    }
}
Pl_DCT::finish()
{
    this->buf.finish();

     
     
     
    Buffer* b = this->buf.getBuffer();
    if (b->getSize() == 0)
    {
         
         
         
        delete b;
        this->getNext()->finish();
        return;
    }

    struct jpeg_compress_struct cinfo_compress;
    struct jpeg_decompress_struct cinfo_decompress;
    struct qpdf_jpeg_error_mgr jerr;

    cinfo_compress.err = jpeg_std_error(&(jerr.pub));
    cinfo_decompress.err = jpeg_std_error(&(jerr.pub));
    jerr.pub.error_exit = error_handler;

    bool error = false;
     
     
    if (setjmp(jerr.jmpbuf) == 0)
    {
        try
        {
            if (this->action == a_compress)
            {
                compress(reinterpret_cast<void*>(&cinfo_compress), b);
            }
            else
            {
                decompress(reinterpret_cast<void*>(&cinfo_decompress), b);
            }
        }
        catch (std::exception& e)
        {
             
             
             
            jerr.msg = e.what();
            longjmp(jerr.jmpbuf, 1);
        }
    }
    else
    {
        error = true;
    }
    delete b;

    if (this->action == a_compress)
    {
        jpeg_destroy_compress(&cinfo_compress);
    }
    if (this->action == a_decompress)
    {
        jpeg_destroy_decompress(&cinfo_decompress);
    }
    if (error)
    {
        throw std::runtime_error(jerr.msg);
    }
}