Depuración del programa PNG (el programa está usando zlib). ¿Por qué se bloquea al desinflar ()?

0

Desenchufar un programa que lee un PNG ... parece estar usando la biblioteca zlib.

Aquí está la salida cuando la ejecuto con una entrada dañada (imagen):

Reading 'crash.png'...
ptr:0x1b9e2c0
rowbytes:3
zbuf1:0x1b9b480
zbuf_size:11
zbuf2:0x1b9b4a0
zbuf_size:11
ret1:0
ret2:0
extracting frame 0 of 0
zstream1.buf:x+�?%
zstream1.count_out:11
Z_FINISH:4
ret5:-2
zstream1.buf:x+�?%
zstream1.count_out:11
zstream2.buf:x+�?%
zstream2.count_out:11
Z_FINISH:4
Segmentation fault

Es gracioso que la falla de Seg, no siempre sucede.

Aquí cómo se busca un PNG válido (1 píxel negro):

Reading 'input.png'...
ptr:0x17fb2c0
rowbytes:3
zbuf1:0x17f8480
zbuf_size:17
zbuf2:0x17f84a0
zbuf_size:17
ret1:0
ret2:0
extracting frame 0 of 0
ret3:0
ret4:0
zstream1.buf:���
zstream1.count_out:15
Z_FINISH:4
ret5:1
zstream1.buf:�
zstream1.count_out:5
zstream2.buf:���
zstream2.count_out:15
Z_FINISH:4
zstream2.buf:�
zstream2.count_out:5
ret6:1
ret7:0
ret8:0
ret9:0
ret10:0
all done

¿Alguien puede mirar el código a continuación y decirme por qué falla? Aquí:

ret = deflate (& zstream2, Z_FINISH);

Código completo:

void SavePNG(char * szPath, unsigned char * pdata, unsigned short * delays, unsigned int w, unsigned int h, unsigned int first, unsigned int last, unsigned int bpp, unsigned char coltype)
    {
      struct IHDR 
      {
        unsigned int    mWidth;
        unsigned int    mHeight;
        unsigned char   mDepth;
        unsigned char   mColorType;
        unsigned char   mCompression;
        unsigned char   mFilterMethod;
        unsigned char   mInterlaceMethod;
      } ihdr = { swap32(w), swap32(h), 8, coltype, 0, 0, 0 };

      char            szOut[256];

      z_stream        zstream1;
      z_stream        zstream2;
      FILE          * f;
      unsigned int    i, j, n, len;

      unsigned int rowbytes  = w * bpp;
      unsigned int idat_size = (rowbytes + 1) * h;
      unsigned int zbuf_size = idat_size + ((idat_size + 7) >> 3) + ((idat_size + 63) >> 6) + 11;


      unsigned char * row_buf   = (unsigned char *)malloc(rowbytes + 1);
      printf("ptr:%p\n",row_buf);
      printf("rowbytes:%i\n",rowbytes);

      unsigned char * sub_row   = (unsigned char *)malloc(rowbytes + 1);
      unsigned char * up_row    = (unsigned char *)malloc(rowbytes + 1);
      unsigned char * avg_row   = (unsigned char *)malloc(rowbytes + 1);
      unsigned char * paeth_row = (unsigned char *)malloc(rowbytes + 1);
      unsigned char * zbuf1     = (unsigned char *)malloc(zbuf_size);
      printf("zbuf1:%p\n",zbuf1);
      printf("zbuf_size:%i\n",zbuf_size);

      unsigned char * zbuf2     = (unsigned char *)malloc(zbuf_size);
       printf("zbuf2:%p\n",zbuf2);
      printf("zbuf_size:%i\n",zbuf_size);


      if (!row_buf || !sub_row || !up_row || !avg_row || !paeth_row || !zbuf1 || !zbuf2)
        return;

      row_buf[0]   = 0;
      sub_row[0]   = 1;
      up_row[0]    = 2;
      avg_row[0]   = 3;
      paeth_row[0] = 4;

      zstream1.data_type = Z_BINARY;
      zstream1.zalloc    = Z_NULL;
      zstream1.zfree     = Z_NULL;
      zstream1.opaque    = Z_NULL;
      int ret;
      ret=deflateInit2(&zstream1, Z_BEST_COMPRESSION, 8, 15, 8, Z_DEFAULT_STRATEGY);
      printf("ret1:%i\n",ret);

      zstream2.data_type = Z_BINARY;
      zstream2.zalloc    = Z_NULL;
      zstream2.zfree     = Z_NULL;
      zstream2.opaque    = Z_NULL;
      ret=deflateInit2(&zstream2, Z_BEST_COMPRESSION, 8, 15, 8, Z_FILTERED);
      printf("ret2:%i\n",ret);


      len = sprintf(szOut, "%d", last);

      for (n=first; n<=last; n++)
      {
        printf("extracting frame %d of %d\n", n, last);

        if (n > 0)
        {
          sprintf(szOut, "%s%.*d.txt", szPath, len, n);
          if ((f = fopen(szOut, "wt")) != 0)
          {
            fprintf(f, "delay=%d/%d\n", delays[n*2], delays[n*2+1]);
            fclose(f);
          }
        }

        sprintf(szOut, "%s%.*d.png", szPath, len, n);
        if ((f = fopen(szOut, "wb")) != 0)
        {
          int a, b, c, pa, pb, pc, p, v;
          unsigned char * prev;
          unsigned char * row;

          fwrite(png_sign, 1, 8, f);
          write_chunk(f, "IHDR", (unsigned char *)(&ihdr), 13);

          if (palsize > 0)
            write_chunk(f, "PLTE", (unsigned char *)(&pal), palsize*3);

          if (trnssize > 0)
            write_chunk(f, "tRNS", trns, trnssize);

          zstream1.next_out  = zbuf1;
          zstream1.avail_out = zbuf_size;
          zstream2.next_out  = zbuf2;
          zstream2.avail_out = zbuf_size;

          prev = NULL;
          row  = pdata + n*h*rowbytes;

          for (j=0; j<h; j++)
          {
            unsigned char * out;
            unsigned int    sum = 0;
            unsigned char * best_row = row_buf;
            unsigned int    mins = ((unsigned int)(-1)) >> 1;

            out = row_buf+1;
            for (i=0; i<rowbytes; i++)
            {
              v = out[i] = row[i];
              sum += (v < 128) ? v : 256 - v;
            }
            mins = sum;

            sum = 0;
            out = sub_row+1;
            for (i=0; i<bpp; i++)
            {
              v = out[i] = row[i];
              sum += (v < 128) ? v : 256 - v;
            }
            for (i=bpp; i<rowbytes; i++)
            {
              v = out[i] = row[i] - row[i-bpp];
              sum += (v < 128) ? v : 256 - v;
              if (sum > mins) break;
            }
            if (sum < mins)
            {
              mins = sum;
              best_row = sub_row;
            }

            if (prev)
            {
              sum = 0;
              out = up_row+1;
              for (i=0; i<rowbytes; i++)
              {
                v = out[i] = row[i] - prev[i];
                sum += (v < 128) ? v : 256 - v;
                if (sum > mins) break;
              }
              if (sum < mins)
              {
                mins = sum;
                best_row = up_row;
              }

              sum = 0;
              out = avg_row+1;
              for (i=0; i<bpp; i++)
              {
                v = out[i] = row[i] - prev[i]/2;
                sum += (v < 128) ? v : 256 - v;
              }
              for (i=bpp; i<rowbytes; i++)
              {
                v = out[i] = row[i] - (prev[i] + row[i-bpp])/2;
                sum += (v < 128) ? v : 256 - v;
                if (sum > mins) break;
              }
              if (sum < mins)
              { 
                mins = sum;
                best_row = avg_row;
              }

              sum = 0;
              out = paeth_row+1;
              for (i=0; i<bpp; i++)
              {
                v = out[i] = row[i] - prev[i];
                sum += (v < 128) ? v : 256 - v;
              }
              for (i=bpp; i<rowbytes; i++)
              {
                a = row[i-bpp];
                b = prev[i];
                c = prev[i-bpp];
                p = b - c;
                pc = a - c;
                pa = abs(p);
                pb = abs(pc);
                pc = abs(p + pc);
                p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
                v = out[i] = row[i] - p;
                sum += (v < 128) ? v : 256 - v;
                if (sum > mins) break;
              }
              if (sum < mins)
              {
                best_row = paeth_row;
              }
            }
            zstream1.next_in = row_buf;
            zstream1.avail_in = rowbytes + 1;

            ret=deflate(&zstream1, Z_NO_FLUSH);
            printf("ret3:%i\n",ret);

            zstream2.next_in = best_row;
            zstream2.avail_in = rowbytes + 1;
            ret=deflate(&zstream2, Z_NO_FLUSH);
            printf("ret4:%i\n",ret);

            prev = row;
            row += rowbytes;
          }
          printf("zstream1.buf:%s\n",zstream1.next_out);
          printf("zstream1.count_out:%i\n",zstream1.avail_out);
          printf("Z_FINISH:%i\n",Z_FINISH);
          ret=deflate(&zstream1, Z_FINISH);
          printf("ret5:%i\n",ret);
          printf("zstream1.buf:%s\n",zstream1.next_out);
          printf("zstream1.count_out:%i\n",zstream1.avail_out);

          printf("zstream2.buf:%s\n",zstream2.next_out);
          printf("zstream2.count_out:%i\n",zstream2.avail_out);
          printf("Z_FINISH:%i\n",Z_FINISH);

          ret=deflate(&zstream2, Z_FINISH);
          printf("zstream2.buf:%s\n",zstream2.next_out);
          printf("zstream2.count_out:%i\n",zstream2.avail_out);


          printf("ret6:%i\n",ret);



          if (zstream1.total_out <= zstream2.total_out)
            write_IDATs(f, zbuf1, zstream1.total_out, idat_size);
          else
            write_IDATs(f, zbuf2, zstream2.total_out, idat_size);

          ret=deflateReset(&zstream1);
          printf("ret7:%i\n",ret);

          zstream1.data_type = Z_BINARY;
          ret=deflateReset(&zstream2);
          printf("ret8:%i\n",ret);

          zstream2.data_type = Z_BINARY;

          write_chunk(f, "IEND", 0, 0);
          fclose(f);
        }
        else
          printf("Error: can't open the file '%s'\n", szOut);
      }

      ret=deflateEnd(&zstream1);
      printf("ret9:%i\n",ret);

      ret=deflateEnd(&zstream2);
      printf("ret10:%i\n",ret);

      free(zbuf1);
      free(zbuf2);
      free(row_buf);
      free(sub_row);
      free(up_row);
      free(avg_row);
      free(paeth_row);
    }

ACTUALIZACIÓN 1:

OK .... modificó el código:

void SavePNG(char * szPath, unsigned char * pdata, unsigned short * delays, unsigned int w, unsigned int h, unsigned int first, unsigned int last, unsigned int bpp, unsigned char coltype)
{
  struct IHDR 
  {
    unsigned int    mWidth;
    unsigned int    mHeight;
    unsigned char   mDepth;
    unsigned char   mColorType;
    unsigned char   mCompression;
    unsigned char   mFilterMethod;
    unsigned char   mInterlaceMethod;
  } ihdr = { swap32(w), swap32(h), 8, coltype, 0, 0, 0 };

  char            szOut[256];

  z_stream        zstream1;
  z_stream        zstream2;
  FILE          * f;
  unsigned int    i, j, n, len;

  unsigned int rowbytes  = w * bpp;
  unsigned int idat_size = (rowbytes + 1) * h;
  unsigned int zbuf_size = idat_size + ((idat_size + 7) >> 3) + ((idat_size + 63) >> 6) + 11;


  unsigned char * row_buf   = (unsigned char *)malloc(rowbytes + 1);
  printf("ptr:%p\n",row_buf);
  printf("rowbytes:%i\n",rowbytes);

  unsigned char * sub_row   = (unsigned char *)malloc(rowbytes + 1);
  unsigned char * up_row    = (unsigned char *)malloc(rowbytes + 1);
  unsigned char * avg_row   = (unsigned char *)malloc(rowbytes + 1);
  unsigned char * paeth_row = (unsigned char *)malloc(rowbytes + 1);
  unsigned char * zbuf1     = (unsigned char *)malloc(zbuf_size);
  printf("zbuf1:%p\n",zbuf1);
  printf("zbuf_size:%i\n",zbuf_size);

  unsigned char * zbuf2     = (unsigned char *)malloc(zbuf_size);
   printf("zbuf2:%p\n",zbuf2);
  printf("zbuf_size:%i\n",zbuf_size);


  if (!row_buf || !sub_row || !up_row || !avg_row || !paeth_row || !zbuf1 || !zbuf2)
    return;

  row_buf[0]   = 0;
  sub_row[0]   = 1;
  up_row[0]    = 2;
  avg_row[0]   = 3;
  paeth_row[0] = 4;

  zstream1.data_type = Z_BINARY;
  zstream1.zalloc    = Z_NULL;
  zstream1.zfree     = Z_NULL;
  zstream1.opaque    = Z_NULL;
  int ret;
  ret=deflateInit2(&zstream1, Z_BEST_COMPRESSION, 8, 15, 8, Z_DEFAULT_STRATEGY);
  printf("ret1:%i\n",ret);

  zstream2.data_type = Z_BINARY;
  zstream2.zalloc    = Z_NULL;
  zstream2.zfree     = Z_NULL;
  zstream2.opaque    = Z_NULL;
  ret=deflateInit2(&zstream2, Z_BEST_COMPRESSION, 8, 15, 8, Z_FILTERED);
  printf("ret2:%i\n",ret);


  len = sprintf(szOut, "%d", last);

  for (n=first; n<=last; n++)
  {
    printf("extracting frame %d of %d\n", n, last);

    if (n > 0)
    {
      sprintf(szOut, "%s%.*d.txt", szPath, len, n);
      if ((f = fopen(szOut, "wt")) != 0)
      {
        fprintf(f, "delay=%d/%d\n", delays[n*2], delays[n*2+1]);
        fclose(f);
      }
    }

    sprintf(szOut, "%s%.*d.png", szPath, len, n);
    if ((f = fopen(szOut, "wb")) != 0)
    {
      int a, b, c, pa, pb, pc, p, v;
      unsigned char * prev;
      unsigned char * row;

      fwrite(png_sign, 1, 8, f);
      write_chunk(f, "IHDR", (unsigned char *)(&ihdr), 13);

      if (palsize > 0)
        write_chunk(f, "PLTE", (unsigned char *)(&pal), palsize*3);

      if (trnssize > 0)
        write_chunk(f, "tRNS", trns, trnssize);

      zstream1.next_out  = zbuf1;
      zstream1.avail_out = zbuf_size;
      zstream2.next_out  = zbuf2;
      zstream2.avail_out = zbuf_size;

      prev = NULL;
      row  = pdata + n*h*rowbytes;

      for (j=0; j<h; j++)
      {
        unsigned char * out;
        unsigned int    sum = 0;
        unsigned char * best_row = row_buf;
        unsigned int    mins = ((unsigned int)(-1)) >> 1;

        out = row_buf+1;
        for (i=0; i<rowbytes; i++)
        {
          v = out[i] = row[i];
          sum += (v < 128) ? v : 256 - v;
        }
        mins = sum;

        sum = 0;
        out = sub_row+1;
        for (i=0; i<bpp; i++)
        {
          v = out[i] = row[i];
          sum += (v < 128) ? v : 256 - v;
        }
        for (i=bpp; i<rowbytes; i++)
        {
          v = out[i] = row[i] - row[i-bpp];
          sum += (v < 128) ? v : 256 - v;
          if (sum > mins) break;
        }
        if (sum < mins)
        {
          mins = sum;
          best_row = sub_row;
        }

        if (prev)
        {
          sum = 0;
          out = up_row+1;
          for (i=0; i<rowbytes; i++)
          {
            v = out[i] = row[i] - prev[i];
            sum += (v < 128) ? v : 256 - v;
            if (sum > mins) break;
          }
          if (sum < mins)
          {
            mins = sum;
            best_row = up_row;
          }

          sum = 0;
          out = avg_row+1;
          for (i=0; i<bpp; i++)
          {
            v = out[i] = row[i] - prev[i]/2;
            sum += (v < 128) ? v : 256 - v;
          }
          for (i=bpp; i<rowbytes; i++)
          {
            v = out[i] = row[i] - (prev[i] + row[i-bpp])/2;
            sum += (v < 128) ? v : 256 - v;
            if (sum > mins) break;
          }
          if (sum < mins)
          { 
            mins = sum;
            best_row = avg_row;
          }

          sum = 0;
          out = paeth_row+1;
          for (i=0; i<bpp; i++)
          {
            v = out[i] = row[i] - prev[i];
            sum += (v < 128) ? v : 256 - v;
          }
          for (i=bpp; i<rowbytes; i++)
          {
            a = row[i-bpp];
            b = prev[i];
            c = prev[i-bpp];
            p = b - c;
            pc = a - c;
            pa = abs(p);
            pb = abs(pc);
            pc = abs(p + pc);
            p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
            v = out[i] = row[i] - p;
            sum += (v < 128) ? v : 256 - v;
            if (sum > mins) break;
          }
          if (sum < mins)
          {
            best_row = paeth_row;
          }
        }
        zstream1.next_in = row_buf;
        zstream1.avail_in = rowbytes + 1;

        ret=deflate(&zstream1, Z_NO_FLUSH);
        printf("ret3:%i\n",ret);

        zstream2.next_in = best_row;
        zstream2.avail_in = rowbytes + 1;
        ret=deflate(&zstream2, Z_NO_FLUSH);
        printf("ret4:%i\n",ret);

        prev = row;
        row += rowbytes;
      }
      printf("zstream1.buf:%s\n",zstream1.next_out);
      printf("zstream1.count_out:%i\n",zstream1.avail_out);
      printf("Z_FINISH:%i\n",Z_FINISH);
      ret=deflate(&zstream1, Z_FINISH);
      printf("ret5:%i\n",ret);
      printf("zstream1.buf:%s\n",zstream1.next_out);
      printf("zstream1.count_out:%i\n",zstream1.avail_out);

      printf("zstream2.buf:%s\n",zstream2.next_out);
      printf("zstream2.count_out:%i\n",zstream2.avail_out);
      printf("Z_FINISH:%i\n",Z_FINISH);
      printf("zstream2.bufin:%s\n",zstream2.next_in);
      printf("zstream2.count_in:%i\n",zstream2.avail_in);
      printf("Z_FINISH:%i\n",Z_FINISH);

      ret=deflate(&zstream2, Z_FINISH);
      printf("zstream2.buf:%s\n",zstream2.next_out);
      printf("zstream2.count_out:%i\n",zstream2.avail_out);


      printf("ret6:%i\n",ret);



      if (zstream1.total_out <= zstream2.total_out)
        write_IDATs(f, zbuf1, zstream1.total_out, idat_size);
      else
        write_IDATs(f, zbuf2, zstream2.total_out, idat_size);

      ret=deflateReset(&zstream1);
      printf("ret7:%i\n",ret);

      zstream1.data_type = Z_BINARY;
      ret=deflateReset(&zstream2);
      printf("ret8:%i\n",ret);

      zstream2.data_type = Z_BINARY;

      write_chunk(f, "IEND", 0, 0);
      fclose(f);
    }
    else
      printf("Error: can't open the file '%s'\n", szOut);
  }

  ret=deflateEnd(&zstream1);
  printf("ret9:%i\n",ret);

  ret=deflateEnd(&zstream2);
  printf("ret10:%i\n",ret);

  free(zbuf1);
  free(zbuf2);
  free(row_buf);
  free(sub_row);
  free(up_row);
  free(avg_row);
  free(paeth_row);
}

Ahora veo por qué se bloquea ....

pero ¿por qué

zstream2.next_in

zstream2.avail_in

¿Tiene tales valores aleatorios?

Reading 'crash.png'...
ptr:0x14c32c0
rowbytes:3
zbuf1:0x14c0480
zbuf_size:11
zbuf2:0x14c04a0
zbuf_size:11
ret1:0
ret2:0
extracting frame 0 of 0
zstream1.buf:x+��y
zstream1.count_out:11
Z_FINISH:4
ret5:-2
zstream1.buf:x+��y
zstream1.count_out:11
zstream2.buf:x+��y
zstream2.count_out:11
Z_FINISH:4
zstream2.bufin:
zstream2.count_in:-1681299629
Z_FINISH:4
Segmentation fault


Reading 'crash.png'...
ptr:0x8c22c0
rowbytes:3
zbuf1:0x8bf480
zbuf_size:11
zbuf2:0x8bf4a0
zbuf_size:11
ret1:0
ret2:0
extracting frame 0 of 0
zstream1.buf:x+\�*
zstream1.count_out:11
Z_FINISH:4
ret5:-2
zstream1.buf:x+\�*
zstream1.count_out:11
zstream2.buf:x+\�*
zstream2.count_out:11
Z_FINISH:4
zstream2.bufin:
zstream2.count_in:-1920964781
Z_FINISH:4
Segmentation fault
    
pregunta android_dev 08.02.2017 - 00:29
fuente

0 respuestas

Lea otras preguntas en las etiquetas