1  /* Integration test to ensure we issue FILE * leak diagnostics for
       2     this particular non-trivial case.
       3     Adapted from zlib/contrib/minizip/mztools.c, with all #includes
       4     removed.  */
       5  
       6  /* { dg-do "compile" } */
       7  /* { dg-additional-options "-fsigned-char" } */
       8  
       9  /* Minimal replacement of system headers.  */
      10  
      11  typedef __SIZE_TYPE__ size_t;
      12  #define NULL ((void *) 0)
      13  
      14  typedef struct _IO_FILE FILE;
      15  extern FILE *fopen(const char *__restrict __filename,
      16  		   const char *__restrict __modes);
      17  extern size_t fread (void *__restrict __ptr, size_t __size,
      18  		     size_t __n, FILE *__restrict __stream);
      19  extern size_t fwrite (const void *__restrict __ptr, size_t __size,
      20  		      size_t __n, FILE *__restrict __s);
      21  extern int fclose (FILE *__stream);
      22  extern int remove (const char *__filename)
      23    __attribute__ ((__nothrow__ , __leaf__));
      24  
      25  extern void *malloc (size_t __size)
      26    __attribute__ ((__nothrow__ , __leaf__))
      27    __attribute__ ((__malloc__));
      28  extern void free (void *__ptr)
      29    __attribute__ ((__nothrow__ , __leaf__));
      30  
      31  extern size_t strlen (const char *__s)
      32    __attribute__ ((__nothrow__ , __leaf__))
      33    __attribute__ ((__pure__))
      34    __attribute__ ((__nonnull__ (1)));
      35  
      36  /* Minimal replacement of zlib headers.  */
      37  
      38  #define ZEXPORT
      39  typedef unsigned long  uLong; /* 32 bits or more */
      40  #define Z_OK            0
      41  #define Z_ERRNO        (-1)
      42  #define Z_STREAM_ERROR (-2)
      43  #define Z_MEM_ERROR    (-4)
      44  
      45  /*
      46    Additional tools for Minizip
      47    Code: Xavier Roche '2004
      48    License: Same as ZLIB (www.gzip.org)
      49  */
      50  
      51  /* Code */
      52  
      53  #define READ_8(adr)  ((unsigned char)*(adr))
      54  #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
      55  #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
      56  
      57  #define WRITE_8(buff, n) do { \
      58    *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
      59  } while(0)
      60  #define WRITE_16(buff, n) do { \
      61    WRITE_8((unsigned char*)(buff), n); \
      62    WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
      63  } while(0)
      64  #define WRITE_32(buff, n) do { \
      65    WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
      66    WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
      67  } while(0)
      68  
      69  extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
      70  const char* file;
      71  const char* fileOut;
      72  const char* fileOutTmp;
      73  uLong* nRecovered;
      74  uLong* bytesRecovered;
      75  {
      76    int err = Z_OK;
      77    FILE* fpZip = fopen(file, "rb");
      78    FILE* fpOut = fopen(fileOut, "wb");
      79    FILE* fpOutCD = fopen(fileOutTmp, "wb");
      80    if (fpZip != NULL && fpOut != NULL) {
      81      int entries = 0;
      82      uLong totalBytes = 0;
      83      char header[30];
      84      char filename[1024];
      85      char extra[1024];
      86      int offset = 0;
      87      int offsetCD = 0;
      88      while ( fread(header, 1, 30, fpZip) == 30 ) {
      89        int currentOffset = offset;
      90  
      91        /* File entry */
      92        if (READ_32(header) == 0x04034b50) {
      93          unsigned int version = READ_16(header + 4);
      94          unsigned int gpflag = READ_16(header + 6);
      95          unsigned int method = READ_16(header + 8);
      96          unsigned int filetime = READ_16(header + 10);
      97          unsigned int filedate = READ_16(header + 12);
      98          unsigned int crc = READ_32(header + 14); /* crc */
      99          unsigned int cpsize = READ_32(header + 18); /* compressed size */
     100          unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
     101          unsigned int fnsize = READ_16(header + 26); /* file name length */
     102          unsigned int extsize = READ_16(header + 28); /* extra field length */
     103          filename[0] = extra[0] = '\0';
     104  
     105          /* Header */
     106          if (fwrite(header, 1, 30, fpOut) == 30) {
     107            offset += 30;
     108          } else {
     109            err = Z_ERRNO;
     110            break;
     111          }
     112  
     113          /* Filename */
     114          if (fnsize > 0) {
     115            if (fnsize < sizeof(filename)) {
     116              if (fread(filename, 1, fnsize, fpZip) == fnsize) {
     117                  if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
     118                  offset += fnsize;
     119                } else {
     120                  err = Z_ERRNO;
     121                  break;
     122                }
     123              } else {
     124                err = Z_ERRNO;
     125                break;
     126              }
     127            } else {
     128              err = Z_ERRNO;
     129              break;
     130            }
     131          } else {
     132            err = Z_STREAM_ERROR;
     133            break;
     134          }
     135  
     136          /* Extra field */
     137          if (extsize > 0) {
     138            if (extsize < sizeof(extra)) {
     139              if (fread(extra, 1, extsize, fpZip) == extsize) {
     140                if (fwrite(extra, 1, extsize, fpOut) == extsize) {
     141                  offset += extsize;
     142                  } else {
     143                  err = Z_ERRNO;
     144                  break;
     145                }
     146              } else {
     147                err = Z_ERRNO;
     148                break;
     149              }
     150            } else {
     151              err = Z_ERRNO;
     152              break;
     153            }
     154          }
     155  
     156          /* Data */
     157          {
     158            int dataSize = cpsize;
     159            if (dataSize == 0) {
     160              dataSize = uncpsize;
     161            }
     162            if (dataSize > 0) {
     163              char* data = malloc(dataSize);
     164              if (data != NULL) {
     165                if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
     166                  if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
     167                    offset += dataSize;
     168                    totalBytes += dataSize;
     169                  } else {
     170                    err = Z_ERRNO;
     171                  }
     172                } else {
     173                  err = Z_ERRNO;
     174                }
     175                free(data);
     176                if (err != Z_OK) {
     177                  break;
     178                }
     179              } else {
     180                err = Z_MEM_ERROR;
     181                break;
     182              }
     183            }
     184          }
     185  
     186          /* Central directory entry */
     187          {
     188            char header[46];
     189            char* comment = "";
     190            int comsize = (int) strlen(comment);
     191            WRITE_32(header, 0x02014b50);
     192            WRITE_16(header + 4, version);
     193            WRITE_16(header + 6, version);
     194            WRITE_16(header + 8, gpflag);
     195            WRITE_16(header + 10, method);
     196            WRITE_16(header + 12, filetime);
     197            WRITE_16(header + 14, filedate);
     198            WRITE_32(header + 16, crc);
     199            WRITE_32(header + 20, cpsize);
     200            WRITE_32(header + 24, uncpsize);
     201            WRITE_16(header + 28, fnsize);
     202            WRITE_16(header + 30, extsize);
     203            WRITE_16(header + 32, comsize);
     204            WRITE_16(header + 34, 0);     /* disk # */
     205            WRITE_16(header + 36, 0);     /* int attrb */
     206            WRITE_32(header + 38, 0);     /* ext attrb */
     207            WRITE_32(header + 42, currentOffset);
     208            /* Header */
     209            if (fwrite(header, 1, 46, fpOutCD) == 46) {
     210              offsetCD += 46;
     211  
     212              /* Filename */
     213              if (fnsize > 0) {
     214                if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
     215                  offsetCD += fnsize;
     216                } else {
     217                  err = Z_ERRNO;
     218                  break;
     219                }
     220              } else {
     221                err = Z_STREAM_ERROR;
     222                break;
     223              }
     224  
     225              /* Extra field */
     226              if (extsize > 0) {
     227                if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
     228                  offsetCD += extsize;
     229                } else {
     230                  err = Z_ERRNO;
     231                  break;
     232                }
     233              }
     234  
     235              /* Comment field */
     236              if (comsize > 0) {
     237                if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
     238                  offsetCD += comsize;
     239                } else {
     240                  err = Z_ERRNO;
     241                  break;
     242                }
     243              }
     244  
     245  
     246            } else {
     247              err = Z_ERRNO;
     248              break;
     249            }
     250          }
     251  
     252          /* Success */
     253          entries++;
     254  
     255        } else {
     256          break;
     257        }
     258      }
     259  
     260      /* Final central directory  */
     261      {
     262        int entriesZip = entries;
     263        char header[22];
     264        char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
     265        int comsize = (int) strlen(comment);
     266        if (entriesZip > 0xffff) {
     267          entriesZip = 0xffff;
     268        }
     269        WRITE_32(header, 0x06054b50);
     270        WRITE_16(header + 4, 0);    /* disk # */
     271        WRITE_16(header + 6, 0);    /* disk # */
     272        WRITE_16(header + 8, entriesZip);   /* hack */
     273        WRITE_16(header + 10, entriesZip);  /* hack */
     274        WRITE_32(header + 12, offsetCD);    /* size of CD */
     275        WRITE_32(header + 16, offset);      /* offset to CD */
     276        WRITE_16(header + 20, comsize);     /* comment */
     277  
     278        /* Header */
     279        if (fwrite(header, 1, 22, fpOutCD) == 22) {
     280  
     281          /* Comment field */
     282          if (comsize > 0) {
     283            if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
     284              err = Z_ERRNO;
     285            }
     286          }
     287  
     288        } else {
     289          err = Z_ERRNO;
     290        }
     291      }
     292  
     293      /* Final merge (file + central directory) */
     294      fclose(fpOutCD);
     295      if (err == Z_OK) {
     296        fpOutCD = fopen(fileOutTmp, "rb");
     297        if (fpOutCD != NULL) {
     298          int nRead;
     299          char buffer[8192];
     300          while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
     301            if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
     302              err = Z_ERRNO;
     303              break;
     304            }
     305          }
     306          fclose(fpOutCD);
     307        }
     308      }
     309  
     310      /* Close */
     311      fclose(fpZip);
     312      fclose(fpOut);
     313  
     314      /* Wipe temporary file */
     315      (void)remove(fileOutTmp);
     316  
     317      /* Number of recovered entries */
     318      if (err == Z_OK) {
     319        if (nRecovered != NULL) {
     320          *nRecovered = entries;
     321        }
     322        if (bytesRecovered != NULL) {
     323          *bytesRecovered = totalBytes;
     324        }
     325      }
     326    } else {
     327      err = Z_STREAM_ERROR;
     328    }
     329    return err; /* { dg-warning "leak of FILE 'fpZip'" "leak of fpZip" } */
     330    /* { dg-warning "leak of FILE 'fpOut'" "leak of fpOut" { target *-*-* } .-1 } */
     331    /* { dg-warning "leak of FILE 'fpOutCD'" "leak of fpOutCD" { target *-*-* } .-2 } */
     332  }