# qcad (libpng) segfaulting on start-up



## ericx (Feb 19, 2014)

This is a new installation of 10.0-RELEASE. I had `qcad` working nicely and then I upgraded png to 1.5.18 (I reinstalled, tweaked and poked a LOT of things; so this might be a red herring). After the upgrade `qcad` segfaults just as it opens the main window. I've recompiled both `qcad` and png with: 

```
# qcad is segfault'ing. No clue...
.if ${.CURDIR:M*/cad/qcad}
WITH_DEBUG=yes
.endif 

# qcad is segfault'ing somewhere in libpng..
.if ${.CURDIR:M*/graphics/png}
WITH_DEBUG=yes
.endif
```
in /etc/make.conf. `gdb` makes it pretty clear that the actual segment fault is occurring in /lib/libz.so.6 when called from png. Here's the `gdb`:

```
** ericx@milicent ** ~ ** Wed Feb 19 16:05:31
$ gdb /usr/local/bin/qcad
GNU gdb (GDB) 7.6.2 [GDB v7.6.2 for FreeBSD]
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-portbld-freebsd10.0".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /usr/local/bin/qcad-bin...done.
(gdb) r
Starting program: /usr/local/bin/qcad 
[New LWP 101001]
[New Thread 812406400 (LWP 101001)]
Debug:    RDxfPlugin::init 
Debug:    RExamplePlugin::init 
Debug:    TransactionListenerPlugin::init 
Debug:    TIMER:  90 ms -  "loading add-ons" 
Debug:    TIMER:  839 ms -  "initializing add-ons" 

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 812406400 (LWP 101001)]
0x0000000803a91824 in ?? () from /lib/libz.so.6
(gdb) back
#0  0x0000000803a91824 in ?? () from /lib/libz.so.6
#1  0x0000000803a90549 in deflate () from /lib/libz.so.6
#2  0x000000080fd6a835 in png_write_filtered_row (png_ptr=0x8210ee500, 
    filtered_row=0x862bb4b00 "\002", avail=0)
    at /usr/ports/graphics/png/work/libpng-1.5.18/pngwutil.c:3219
#3  0x000000080fd6a6dc in png_write_find_filter (png_ptr=0x8210ee500, 
    row_info=0x7fffffff7168)
    at /usr/ports/graphics/png/work/libpng-1.5.18/pngwutil.c:3156
#4  0x000000080fd60e85 in png_write_row (png_ptr=0x8210ee500, 
    row=0x86363c600 "")
    at /usr/ports/graphics/png/work/libpng-1.5.18/pngwrite.c:825
#5  0x000000080fd609b1 in png_write_rows (png_ptr=0x8210ee500, 
    row=0x7fffffff7288, num_rows=1)
    at /usr/ports/graphics/png/work/libpng-1.5.18/pngwrite.c:585
#6  0x00000008085dd0f5 in ?? () from /usr/local/lib/qt4/libQtGui.so.4
#7  0x00000008085dd957 in ?? () from /usr/local/lib/qt4/libQtGui.so.4
#8  0x00000008085ae0bc in QImageWriter::write(QImage const&) ()
   from /usr/local/lib/qt4/libQtGui.so.4
#9  0x000000080859e08e in operator<<(QDataStream&, QImage const&) ()
   from /usr/local/lib/qt4/libQtGui.so.4
#10 0x00000008085bac8f in operator<<(QDataStream&, QPixmap const&) ()
   from /usr/local/lib/qt4/libQtGui.so.4
---Type <return> to continue, or q <return> to quit---q
Quit
(gdb) frame 2
#2  0x000000080fd6a835 in png_write_filtered_row (png_ptr=0x8210ee500, 
    filtered_row=0x862bb4b00 "\002", avail=0)
    at /usr/ports/graphics/png/work/libpng-1.5.18/pngwutil.c:3219
3219	in /usr/ports/graphics/png/work/libpng-1.5.18/pngwutil.c
(gdb) print &png_ptr
$1 = (png_structp *) 0x7fffffff6e48
(gdb) print &png_ptr->zstream
$2 = (z_stream *) 0x8210ee5c0
(gdb)
```
My `gdb` skills are pretty much limited to recognizing that the params should not be -0- and the `zstream` value looks like a reasonable address to me.
Line 3219 in pngwutil.c is:

```
ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
```
The entire `png_write_filtered_row` function is:

```
/* Do the actual writing of a previously filtered row. */
static void
png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
   png_size_t avail/*includes filter byte*/)
{
   png_debug(1, "in png_write_filtered_row");

   png_debug1(2, "filter = %d", filtered_row[0]);
   /* Set up the zlib input buffer */

   png_ptr->zstream.next_in = filtered_row;
   png_ptr->zstream.avail_in = 0;
   /* Repeat until we have compressed all the data */
   do
   {
      int ret; /* Return of zlib */

      /* Record the number of bytes available - zlib supports at least 65535
       * bytes at one step, depending on the size of the zlib type 'uInt', the
       * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
       * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
       * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
       * uInt.  ZLIB_IO_MAX can be safely reduced to cause zlib to be called
       * with smaller chunks of data.
       */
      if (png_ptr->zstream.avail_in == 0)
      {
         if (avail > ZLIB_IO_MAX)
         {
            png_ptr->zstream.avail_in  = ZLIB_IO_MAX;
            avail -= ZLIB_IO_MAX;
         }

         else
         {
            /* So this will fit in the available uInt space: */
            png_ptr->zstream.avail_in = (uInt)avail;
            avail = 0;
         }
      }

      /* Compress the data */
      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);

      /* Check for compression errors */
      if (ret != Z_OK)
      {
         if (png_ptr->zstream.msg != NULL)
            png_error(png_ptr, png_ptr->zstream.msg);

         else
            png_error(png_ptr, "zlib error");
      }

      /* See if it is time to write another IDAT */
      if (!(png_ptr->zstream.avail_out))
      {
         /* Write the IDAT and reset the zlib output buffer */
         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
      }
   /* Repeat until all data has been compressed */
   } while (avail > 0 || png_ptr->zstream.avail_in > 0);

   /* Swap the current and previous rows */
   if (png_ptr->prev_row != NULL)
   {
      png_bytep tptr;

      tptr = png_ptr->prev_row;
      png_ptr->prev_row = png_ptr->row_buf;
      png_ptr->row_buf = tptr;
   }

   /* Finish row - updates counters and flushes zlib if last row */
   png_write_finish_row(png_ptr);

#ifdef PNG_WRITE_FLUSH_SUPPORTED
   png_ptr->flush_rows++;

   if (png_ptr->flush_dist > 0 &&
       png_ptr->flush_rows >= png_ptr->flush_dist)
   {
      png_write_flush(png_ptr);
   }
#endif
}
```
I'm going to try to rev back png. Can someone with superior `gdb` foo suggest how else I might dissect this?

```
FreeBSD 10.0-RELEASE amd64
qcad 3.4.5.0
png 1.5.18
```

Thank you for your time.


----------

