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