Browse code

Reformats unzip.c to make it easier to upgrade with the unzip improvements added in 0.102.

Micah Snyder authored on 2019/10/29 23:01:54
Showing 1 changed files
... ...
@@ -56,129 +56,132 @@
56 56
 
57 57
 #define ZIP_MAX_NUM_OVERLAPPING_FILES 5
58 58
 
59
-#define ZIP_CRC32(r,c,b,l)			\
60
-    do {					\
61
-	r = crc32(~c,b,l);			\
62
-	r = ~r;					\
63
-    } while(0)
59
+#define ZIP_CRC32(r, c, b, l) \
60
+    do {                      \
61
+        r = crc32(~c, b, l);  \
62
+        r = ~r;               \
63
+    } while (0)
64 64
 
65
-
66
-static int wrap_inflateinit2(void *a, int b) {
67
-  return inflateInit2(a, b);
65
+static int wrap_inflateinit2(void *a, int b)
66
+{
67
+    return inflateInit2(a, b);
68 68
 }
69 69
 
70
-static int unz(const uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd, zip_cb zcb) {
71
-  char name[1024], obuf[BUFSIZ];
72
-  char *tempfile = name;
73
-  int of, ret=CL_CLEAN;
74
-  unsigned int res=1, written=0;
75
-
76
-  if(tmpd) {
77
-    snprintf(name, sizeof(name), "%s"PATHSEP"zip.%03u", tmpd, *fu);
78
-    name[sizeof(name)-1]='\0';
79
-  } else {
80
-    if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
81
-  }
82
-  if((of = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR))==-1) {
83
-    cli_warnmsg("cli_unzip: failed to create temporary file %s\n", tempfile);
84
-    if(!tmpd) free(tempfile);
85
-    return CL_ETMPFILE;
86
-  }
87
-  switch (method) {
88
-  case ALG_STORED:
89
-    if(csize<usize) {
90
-      unsigned int fake = *fu + 1;
91
-      cli_dbgmsg("cli_unzip: attempting to inflate stored file with inconsistent size\n");
92
-      if ((ret=unz(src, csize, usize, ALG_DEFLATE, 0, &fake, ctx, tmpd, zcb))==CL_CLEAN) {
93
-	(*fu)++;
94
-	res=fake-(*fu);
95
-      }
96
-      else break;
97
-    }
98
-    if(res==1) {
99
-      if(ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) {
100
-	cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int) ctx->engine->maxfilesize);
101
-	csize = ctx->engine->maxfilesize;
102
-      }
103
-      if(cli_writen(of, src, csize)!=(int)csize) ret = CL_EWRITE;
104
-      else res=0;
105
-    }
106
-    break;
107
-
108
-  case ALG_DEFLATE:
109
-  case ALG_DEFLATE64: {
110
-    union {
111
-      z_stream64 strm64;
112
-      z_stream strm;
113
-    } strm;
114
-    typedef int (*unz_init_) (void *, int);
115
-    typedef int (*unz_unz_) (void *, int);
116
-    typedef int (*unz_end_) (void *);
117
-    unz_init_ unz_init;
118
-    unz_unz_ unz_unz;
119
-    unz_end_ unz_end;
120
-    int wbits;
121
-    void **next_in;
122
-    void **next_out;
123
-    unsigned int *avail_in;
124
-    unsigned int *avail_out;
125
-
126
-    if(method == ALG_DEFLATE64) {
127
-      unz_init = (unz_init_)inflate64Init2;
128
-      unz_unz = (unz_unz_)inflate64;
129
-      unz_end = (unz_end_)inflate64End;
130
-      next_in = (void *)&strm.strm64.next_in;
131
-      next_out = (void *)&strm.strm64.next_out;
132
-      avail_in = &strm.strm64.avail_in;
133
-      avail_out = &strm.strm64.avail_out;
134
-      wbits=MAX_WBITS64;
70
+static int unz(const uint8_t *src, uint32_t csize, uint32_t usize, uint16_t method, uint16_t flags, unsigned int *fu, cli_ctx *ctx, char *tmpd, zip_cb zcb)
71
+{
72
+    char name[1024], obuf[BUFSIZ];
73
+    char *tempfile = name;
74
+    int of, ret = CL_CLEAN;
75
+    unsigned int res = 1, written = 0;
76
+
77
+    if (tmpd) {
78
+        snprintf(name, sizeof(name), "%s" PATHSEP "zip.%03u", tmpd, *fu);
79
+        name[sizeof(name) - 1] = '\0';
135 80
     } else {
136
-      unz_init = (unz_init_)wrap_inflateinit2;
137
-      unz_unz = (unz_unz_)inflate;
138
-      unz_end = (unz_end_)inflateEnd;
139
-      next_in = (void *)&strm.strm.next_in;
140
-      next_out = (void *)&strm.strm.next_out;
141
-      avail_in = &strm.strm.avail_in;
142
-      avail_out = &strm.strm.avail_out;
143
-      wbits=MAX_WBITS;
144
-    }
145
-
146
-    memset(&strm, 0, sizeof(strm));
147
-
148
-    *next_in = (void*) src;
149
-    *next_out = obuf;
150
-    *avail_in = csize;
151
-    *avail_out = sizeof(obuf);
152
-    if (unz_init(&strm, -wbits)!=Z_OK) {
153
-      cli_dbgmsg("cli_unzip: zinit failed\n");
154
-      break;
155
-    }
156
-    while(1) {
157
-      while((res = unz_unz(&strm, Z_NO_FLUSH))==Z_OK) {};
158
-      if(*avail_out!=sizeof(obuf)) {
159
-	written+=sizeof(obuf)-(*avail_out);
160
-	if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
161
-	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int) ctx->engine->maxfilesize);
162
-	  res = Z_STREAM_END;
163
-	  break;
164
-	}
165
-	if(cli_writen(of, obuf, sizeof(obuf)-(*avail_out)) != (int)(sizeof(obuf)-(*avail_out))) {
166
-            cli_warnmsg("cli_unzip: falied to write %lu inflated bytes\n", (unsigned long int)sizeof(obuf)-(*avail_out));
167
-	  ret = CL_EWRITE;
168
-	  res = 100;
169
-	  break;
170
-	}
171
-	*next_out = obuf;
172
-	*avail_out = sizeof(obuf);
173
-	continue;
174
-      }
175
-      break;
176
-    }
177
-    unz_end(&strm);
178
-    if ((res == Z_STREAM_END) | (res == Z_BUF_ERROR)) res=0;
179
-    break;
180
-  }
81
+        if (!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
82
+    }
83
+    if ((of = open(tempfile, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) == -1) {
84
+        cli_warnmsg("cli_unzip: failed to create temporary file %s\n", tempfile);
85
+        if (!tmpd) free(tempfile);
86
+        return CL_ETMPFILE;
87
+    }
88
+    switch (method) {
89
+        case ALG_STORED:
90
+            if (csize < usize) {
91
+                unsigned int fake = *fu + 1;
92
+                cli_dbgmsg("cli_unzip: attempting to inflate stored file with inconsistent size\n");
93
+                if ((ret = unz(src, csize, usize, ALG_DEFLATE, 0, &fake, ctx, tmpd, zcb)) == CL_CLEAN) {
94
+                    (*fu)++;
95
+                    res = fake - (*fu);
96
+                } else
97
+                    break;
98
+            }
99
+            if (res == 1) {
100
+                if (ctx->engine->maxfilesize && csize > ctx->engine->maxfilesize) {
101
+                    cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int)ctx->engine->maxfilesize);
102
+                    csize = ctx->engine->maxfilesize;
103
+                }
104
+                if (cli_writen(of, src, csize) != (int)csize)
105
+                    ret = CL_EWRITE;
106
+                else
107
+                    res = 0;
108
+            }
109
+            break;
181 110
 
111
+        case ALG_DEFLATE:
112
+        case ALG_DEFLATE64: {
113
+            union {
114
+                z_stream64 strm64;
115
+                z_stream strm;
116
+            } strm;
117
+            typedef int (*unz_init_)(void *, int);
118
+            typedef int (*unz_unz_)(void *, int);
119
+            typedef int (*unz_end_)(void *);
120
+            unz_init_ unz_init;
121
+            unz_unz_ unz_unz;
122
+            unz_end_ unz_end;
123
+            int wbits;
124
+            void **next_in;
125
+            void **next_out;
126
+            unsigned int *avail_in;
127
+            unsigned int *avail_out;
128
+
129
+            if (method == ALG_DEFLATE64) {
130
+                unz_init  = (unz_init_)inflate64Init2;
131
+                unz_unz   = (unz_unz_)inflate64;
132
+                unz_end   = (unz_end_)inflate64End;
133
+                next_in   = (void *)&strm.strm64.next_in;
134
+                next_out  = (void *)&strm.strm64.next_out;
135
+                avail_in  = &strm.strm64.avail_in;
136
+                avail_out = &strm.strm64.avail_out;
137
+                wbits     = MAX_WBITS64;
138
+            } else {
139
+                unz_init  = (unz_init_)wrap_inflateinit2;
140
+                unz_unz   = (unz_unz_)inflate;
141
+                unz_end   = (unz_end_)inflateEnd;
142
+                next_in   = (void *)&strm.strm.next_in;
143
+                next_out  = (void *)&strm.strm.next_out;
144
+                avail_in  = &strm.strm.avail_in;
145
+                avail_out = &strm.strm.avail_out;
146
+                wbits     = MAX_WBITS;
147
+            }
148
+
149
+            memset(&strm, 0, sizeof(strm));
150
+
151
+            *next_in   = (void *)src;
152
+            *next_out  = obuf;
153
+            *avail_in  = csize;
154
+            *avail_out = sizeof(obuf);
155
+            if (unz_init(&strm, -wbits) != Z_OK) {
156
+                cli_dbgmsg("cli_unzip: zinit failed\n");
157
+                break;
158
+            }
159
+            while (1) {
160
+                while ((res = unz_unz(&strm, Z_NO_FLUSH)) == Z_OK) {
161
+                };
162
+                if (*avail_out != sizeof(obuf)) {
163
+                    written += sizeof(obuf) - (*avail_out);
164
+                    if (ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
165
+                        cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (long unsigned int)ctx->engine->maxfilesize);
166
+                        res = Z_STREAM_END;
167
+                        break;
168
+                    }
169
+                    if (cli_writen(of, obuf, sizeof(obuf) - (*avail_out)) != (int)(sizeof(obuf) - (*avail_out))) {
170
+                        cli_warnmsg("cli_unzip: falied to write %lu inflated bytes\n", (unsigned long int)sizeof(obuf) - (*avail_out));
171
+                        ret = CL_EWRITE;
172
+                        res = 100;
173
+                        break;
174
+                    }
175
+                    *next_out  = obuf;
176
+                    *avail_out = sizeof(obuf);
177
+                    continue;
178
+                }
179
+                break;
180
+            }
181
+            unz_end(&strm);
182
+            if ((res == Z_STREAM_END) | (res == Z_BUF_ERROR)) res = 0;
183
+            break;
184
+        }
182 185
 
183 186
 #if HAVE_BZLIB_H
184 187
 #ifdef NOBZ2PREFIX
... ...
@@ -187,131 +190,129 @@ static int unz(const uint8_t *src, uint32_t csize, uint32_t usize, uint16_t meth
187 187
 #define BZ2_bzDecompressInit bzDecompressInit
188 188
 #endif
189 189
 
190
-  case ALG_BZIP2: {
191
-    bz_stream strm;
192
-    memset(&strm, 0, sizeof(strm));
193
-    strm.next_in = (char *)src;
194
-    strm.next_out = obuf;
195
-    strm.avail_in = csize;
196
-    strm.avail_out = sizeof(obuf);
197
-    if (BZ2_bzDecompressInit(&strm, 0, 0)!=BZ_OK) {
198
-      cli_dbgmsg("cli_unzip: bzinit failed\n");
199
-      break;
200
-    }
201
-    while((res = BZ2_bzDecompress(&strm))==BZ_OK || res==BZ_STREAM_END) {
202
-      if(strm.avail_out!=sizeof(obuf)) {
203
-	written+=sizeof(obuf)-strm.avail_out;
204
-	if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
205
-	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int) ctx->engine->maxfilesize);
206
-	  res = BZ_STREAM_END;
207
-	  break;
208
-	}
209
-	if(cli_writen(of, obuf, sizeof(obuf)-strm.avail_out) != (int)(sizeof(obuf)-strm.avail_out)) {
210
-            cli_warnmsg("cli_unzip: falied to write %lu bunzipped bytes\n", (long unsigned int)sizeof(obuf)-strm.avail_out);
211
-	  ret = CL_EWRITE;
212
-	  res = 100;
213
-	  break;
214
-	}
215
-	strm.next_out = obuf;
216
-	strm.avail_out = sizeof(obuf);
217
-	if (res == BZ_OK) continue; /* after returning BZ_STREAM_END once, decompress returns an error */
218
-      }
219
-      break;
220
-    }
221
-    BZ2_bzDecompressEnd(&strm);
222
-    if (res == BZ_STREAM_END) res=0;
223
-    break;
224
-  }
190
+        case ALG_BZIP2: {
191
+            bz_stream strm;
192
+            memset(&strm, 0, sizeof(strm));
193
+            strm.next_in   = (char *)src;
194
+            strm.next_out  = obuf;
195
+            strm.avail_in  = csize;
196
+            strm.avail_out = sizeof(obuf);
197
+            if (BZ2_bzDecompressInit(&strm, 0, 0) != BZ_OK) {
198
+                cli_dbgmsg("cli_unzip: bzinit failed\n");
199
+                break;
200
+            }
201
+            while ((res = BZ2_bzDecompress(&strm)) == BZ_OK || res == BZ_STREAM_END) {
202
+                if (strm.avail_out != sizeof(obuf)) {
203
+                    written += sizeof(obuf) - strm.avail_out;
204
+                    if (ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
205
+                        cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int)ctx->engine->maxfilesize);
206
+                        res = BZ_STREAM_END;
207
+                        break;
208
+                    }
209
+                    if (cli_writen(of, obuf, sizeof(obuf) - strm.avail_out) != (int)(sizeof(obuf) - strm.avail_out)) {
210
+                        cli_warnmsg("cli_unzip: falied to write %lu bunzipped bytes\n", (long unsigned int)sizeof(obuf) - strm.avail_out);
211
+                        ret = CL_EWRITE;
212
+                        res = 100;
213
+                        break;
214
+                    }
215
+                    strm.next_out  = obuf;
216
+                    strm.avail_out = sizeof(obuf);
217
+                    if (res == BZ_OK) continue; /* after returning BZ_STREAM_END once, decompress returns an error */
218
+                }
219
+                break;
220
+            }
221
+            BZ2_bzDecompressEnd(&strm);
222
+            if (res == BZ_STREAM_END) res = 0;
223
+            break;
224
+        }
225 225
 #endif /* HAVE_BZLIB_H */
226 226
 
227
+        case ALG_IMPLODE: {
228
+            struct xplstate strm;
229
+            strm.next_in   = (void *)src;
230
+            strm.next_out  = (uint8_t *)obuf;
231
+            strm.avail_in  = csize;
232
+            strm.avail_out = sizeof(obuf);
233
+            if (explode_init(&strm, flags) != EXPLODE_OK) {
234
+                cli_dbgmsg("cli_unzip: explode_init() failed\n");
235
+                break;
236
+            }
237
+            while ((res = explode(&strm)) == EXPLODE_OK) {
238
+                if (strm.avail_out != sizeof(obuf)) {
239
+                    written += sizeof(obuf) - strm.avail_out;
240
+                    if (ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
241
+                        cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int)ctx->engine->maxfilesize);
242
+                        res = 0;
243
+                        break;
244
+                    }
245
+                    if (cli_writen(of, obuf, sizeof(obuf) - strm.avail_out) != (int)(sizeof(obuf) - strm.avail_out)) {
246
+                        cli_warnmsg("cli_unzip: falied to write %lu exploded bytes\n", (unsigned long int)sizeof(obuf) - strm.avail_out);
247
+                        ret = CL_EWRITE;
248
+                        res = 100;
249
+                        break;
250
+                    }
251
+                    strm.next_out  = (uint8_t *)obuf;
252
+                    strm.avail_out = sizeof(obuf);
253
+                    continue;
254
+                }
255
+                break;
256
+            }
257
+            break;
258
+        }
227 259
 
228
-  case ALG_IMPLODE: {
229
-    struct xplstate strm;
230
-    strm.next_in = (void*)src;
231
-    strm.next_out = (uint8_t *)obuf;
232
-    strm.avail_in = csize;
233
-    strm.avail_out = sizeof(obuf);
234
-    if (explode_init(&strm, flags)!=EXPLODE_OK) {
235
-      cli_dbgmsg("cli_unzip: explode_init() failed\n");
236
-      break;
237
-    }
238
-    while((res = explode(&strm))==EXPLODE_OK) {
239
-      if(strm.avail_out!=sizeof(obuf)) {
240
-	written+=sizeof(obuf)-strm.avail_out;
241
-	if(ctx->engine->maxfilesize && written > ctx->engine->maxfilesize) {
242
-	  cli_dbgmsg("cli_unzip: trimming output size to maxfilesize (%lu)\n", (unsigned long int) ctx->engine->maxfilesize);
243
-	  res = 0;
244
-	  break;
245
-	}
246
-	if(cli_writen(of, obuf, sizeof(obuf)-strm.avail_out) != (int)(sizeof(obuf)-strm.avail_out)) {
247
-            cli_warnmsg("cli_unzip: falied to write %lu exploded bytes\n", (unsigned long int) sizeof(obuf)-strm.avail_out);
248
-	  ret = CL_EWRITE;
249
-	  res = 100;
250
-	  break;
251
-	}
252
-	strm.next_out = (uint8_t *)obuf;
253
-	strm.avail_out = sizeof(obuf);
254
-	continue;
255
-      }
256
-      break;
257
-    }
258
-    break;
259
-  }
260
-
261
-
262
-  case ALG_LZMA:
263
-    /* easy but there's not a single sample in the zoo */
260
+        case ALG_LZMA:
261
+            /* easy but there's not a single sample in the zoo */
264 262
 
265 263
 #if !HAVE_BZLIB_H
266
-  case ALG_BZIP2:
264
+        case ALG_BZIP2:
267 265
 #endif
268
-  case ALG_SHRUNK:
269
-  case ALG_REDUCE1:
270
-  case ALG_REDUCE2:
271
-  case ALG_REDUCE3:
272
-  case ALG_REDUCE4:
273
-  case ALG_TOKENZD:
274
-  case ALG_OLDTERSE:
275
-  case ALG_RSVD1:
276
-  case ALG_RSVD2:
277
-  case ALG_RSVD3:
278
-  case ALG_RSVD4:
279
-  case ALG_RSVD5:
280
-  case ALG_NEWTERSE:
281
-  case ALG_LZ77:
282
-  case ALG_WAVPACK:
283
-  case ALG_PPMD:
284
-    cli_dbgmsg("cli_unzip: unsupported method (%d)\n", method);
285
-    break;
286
-  default:
287
-    cli_dbgmsg("cli_unzip: unknown method (%d)\n", method);
288
-    break;
289
-  }
290
-
291
-  if(!res) {
292
-    (*fu)++;
293
-    cli_dbgmsg("cli_unzip: extracted to %s\n", tempfile);
294
-    if (lseek(of, 0, SEEK_SET) == -1) {
295
-        cli_dbgmsg("cli_unzip: call to lseek() failed\n");
296
-        if (!(tmpd))
297
-            free(tempfile);
266
+        case ALG_SHRUNK:
267
+        case ALG_REDUCE1:
268
+        case ALG_REDUCE2:
269
+        case ALG_REDUCE3:
270
+        case ALG_REDUCE4:
271
+        case ALG_TOKENZD:
272
+        case ALG_OLDTERSE:
273
+        case ALG_RSVD1:
274
+        case ALG_RSVD2:
275
+        case ALG_RSVD3:
276
+        case ALG_RSVD4:
277
+        case ALG_RSVD5:
278
+        case ALG_NEWTERSE:
279
+        case ALG_LZ77:
280
+        case ALG_WAVPACK:
281
+        case ALG_PPMD:
282
+            cli_dbgmsg("cli_unzip: unsupported method (%d)\n", method);
283
+            break;
284
+        default:
285
+            cli_dbgmsg("cli_unzip: unknown method (%d)\n", method);
286
+            break;
287
+    }
288
+
289
+    if (!res) {
290
+        (*fu)++;
291
+        cli_dbgmsg("cli_unzip: extracted to %s\n", tempfile);
292
+        if (lseek(of, 0, SEEK_SET) == -1) {
293
+            cli_dbgmsg("cli_unzip: call to lseek() failed\n");
294
+            if (!(tmpd))
295
+                free(tempfile);
296
+            close(of);
297
+            return CL_ESEEK;
298
+        }
299
+        ret = zcb(of, tempfile, ctx);
298 300
         close(of);
299
-        return CL_ESEEK;
301
+        if (!ctx->engine->keeptmp)
302
+            if (cli_unlink(tempfile)) ret = CL_EUNLINK;
303
+        if (!tmpd) free(tempfile);
304
+        return ret;
300 305
     }
301
-    ret = zcb(of, tempfile, ctx);
306
+
302 307
     close(of);
303
-    if(!ctx->engine->keeptmp)
304
-      if(cli_unlink(tempfile)) ret = CL_EUNLINK;
305
-    if(!tmpd) free(tempfile);
308
+    if (!ctx->engine->keeptmp)
309
+        if (cli_unlink(tempfile)) ret = CL_EUNLINK;
310
+    if (!tmpd) free(tempfile);
311
+    cli_dbgmsg("cli_unzip: extraction failed\n");
306 312
     return ret;
307
-  }
308
-
309
-  close(of);
310
-  if(!ctx->engine->keeptmp)
311
-    if(cli_unlink(tempfile)) ret = CL_EUNLINK;
312
-  if(!tmpd) free(tempfile);
313
-  cli_dbgmsg("cli_unzip: extraction failed\n");
314
-  return ret;
315 313
 }
316 314
 
317 315
 /* zip update keys, taken from zip specification */
... ...
@@ -342,7 +343,7 @@ static inline void zinitkey(uint32_t key[3], struct cli_pwdb *password)
342 342
 
343 343
     /* update keys with password  */
344 344
     for (i = 0; i < password->length; i++)
345
-	zupdatekey(key, password->passwd[i]);
345
+        zupdatekey(key, password->passwd[i]);
346 346
 }
347 347
 
348 348
 /* zip decrypt byte */
... ...
@@ -363,522 +364,533 @@ static inline int zdecrypt(const uint8_t *src, uint32_t csize, uint32_t usize, c
363 363
     struct cli_pwdb *password, *pass_any, *pass_zip;
364 364
 
365 365
     if (!ctx || !ctx->engine)
366
-	return CL_ENULLARG;
366
+        return CL_ENULLARG;
367 367
 
368 368
     /* dconf */
369 369
     if (ctx->dconf && !(ctx->dconf->archive & ARCH_CONF_PASSWD)) {
370
-	cli_dbgmsg("cli_unzip: decrypt - skipping encrypted file\n");
371
-	return CL_SUCCESS;
370
+        cli_dbgmsg("cli_unzip: decrypt - skipping encrypted file\n");
371
+        return CL_SUCCESS;
372 372
     }
373 373
 
374 374
     pass_any = ctx->engine->pwdbs[CLI_PWDB_ANY];
375 375
     pass_zip = ctx->engine->pwdbs[CLI_PWDB_ZIP];
376 376
 
377 377
     while (pass_any || pass_zip) {
378
-	password = pass_zip ? pass_zip : pass_any;
379
-
380
-	zinitkey(key, password);
381
-
382
-	/* decrypting the encryption header */
383
-	memcpy(eh, src, SIZEOF_EH);
384
-
385
-	for (i = 0; i < SIZEOF_EH; i++) {
386
-	    eh[i] ^= zdecryptbyte(key);
387
-	    zupdatekey(key, eh[i]);
388
-	}
389
-
390
-	/* verify that the password is correct */
391
-	if (LH_version > 20) { /* higher than 2.0 */
392
-	    uint16_t a = eh[SIZEOF_EH-1];
393
-
394
-	    if (LH_flags & F_USEDD) {
395
-		cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (moddate)\n", LH_version, a, LH_mtime);
396
-		if (a == ((LH_mtime >> 8) & 0xff))
397
-		    v = 1;
398
-	    } else {
399
-		cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (crc32)\n", LH_version, a, LH_crc32);
400
-		if (a == ((LH_crc32 >> 24) & 0xff))
401
-		    v = 1;
402
-	    }
403
-	} else {
404
-	    uint16_t a = eh[SIZEOF_EH-1], b = eh[SIZEOF_EH-2];
405
-
406
-	    if (LH_flags & F_USEDD) {
407
-		cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (moddate)\n", LH_version, a, b, LH_mtime);
408
-		if ((b | (a << 8)) == (LH_mtime & 0xffff))
409
-		    v = 1;
410
-	    } else {
411
-		cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (crc32)\n", LH_version, eh[SIZEOF_EH-1], eh[SIZEOF_EH-2], LH_crc32);
412
-		if ((b | (a << 8)) == ((LH_crc32 >> 16) & 0xffff))
413
-		    v = 1;
414
-	    }
415
-	}
416
-
417
-	if (v) {
418
-	    char name[1024], obuf[BUFSIZ];
419
-	    char *tempfile = name;
420
-	    unsigned int written = 0, total = 0;
421
-	    fmap_t *dcypt_map;
422
-	    const uint8_t *dcypt_zip;
423
-	    int of;
424
-
425
-	    cli_dbgmsg("cli_unzip: decrypt - password [%s] matches\n", password->name);
426
-
427
-	    /* output decrypted data to tempfile */
428
-	    if(tmpd) {
429
-		snprintf(name, sizeof(name), "%s"PATHSEP"zip.decrypt.%03u", tmpd, *fu);
430
-		name[sizeof(name)-1]='\0';
431
-	    } else {
432
-		if(!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
433
-	    }
434
-	    if((of = open(tempfile, O_RDWR|O_CREAT|O_TRUNC|O_BINARY, S_IRUSR|S_IWUSR))==-1) {
435
-		cli_warnmsg("cli_unzip: decrypt - failed to create temporary file %s\n", tempfile);
436
-		if(!tmpd) free(tempfile);
437
-		return CL_ETMPFILE;
438
-	    }
439
-
440
-	    for (i = 12; i < csize; i++) {
441
-		obuf[written] = src[i] ^ zdecryptbyte(key);
442
-		zupdatekey(key, obuf[written]);
443
-
444
-		written++;
445
-		if (written >= BUFSIZ) {
446
-		    if (cli_writen(of, obuf, written)!=(int)written) {
447
-			ret = CL_EWRITE;
448
-			goto zd_clean;
449
-		    }
450
-		    total += written;
451
-		    written = 0;
452
-		}
453
-	    }
454
-	    if (written) {
455
-		if (cli_writen(of, obuf, written)!=(int)written) {
456
-		    ret = CL_EWRITE;
457
-		    goto zd_clean;
458
-		}
459
-		total += written;
460
-		written = 0;
461
-	    }
462
-
463
-	    cli_dbgmsg("cli_unzip: decrypt - decrypted %u bytes to %s\n", total, tempfile);
464
-
465
-	    /* decrypt data to new fmap -> buffer */
466
-	    if (!(dcypt_map = fmap(of, 0, total))) {
467
-		cli_warnmsg("cli_unzip: decrypt - failed to create fmap on decrypted file %s\n", tempfile);
468
-		ret = CL_EMAP;
469
-		goto zd_clean;
470
-	    }
471
-
472
-	    if (!(dcypt_zip = fmap_need_off_once(dcypt_map, 0, total))) {
473
-		cli_warnmsg("cli_unzip: decrypt - failed to acquire buffer on decrypted file %s\n", tempfile);
474
-		funmap(dcypt_map);
475
-		ret = CL_EREAD;
476
-		goto zd_clean;
477
-	    }
478
-
479
-	    /* call unz on decrypted output */
480
-	    ret = unz(dcypt_zip, csize - SIZEOF_EH, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb);
481
-
482
-	    /* clean-up and return */
483
-	    funmap(dcypt_map);
484
-	zd_clean:
485
-	    close(of);
486
-	    if (!ctx->engine->keeptmp)
378
+        password = pass_zip ? pass_zip : pass_any;
379
+
380
+        zinitkey(key, password);
381
+
382
+        /* decrypting the encryption header */
383
+        memcpy(eh, src, SIZEOF_EH);
384
+
385
+        for (i = 0; i < SIZEOF_EH; i++) {
386
+            eh[i] ^= zdecryptbyte(key);
387
+            zupdatekey(key, eh[i]);
388
+        }
389
+
390
+        /* verify that the password is correct */
391
+        if (LH_version > 20) { /* higher than 2.0 */
392
+            uint16_t a = eh[SIZEOF_EH - 1];
393
+
394
+            if (LH_flags & F_USEDD) {
395
+                cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (moddate)\n", LH_version, a, LH_mtime);
396
+                if (a == ((LH_mtime >> 8) & 0xff))
397
+                    v = 1;
398
+            } else {
399
+                cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x%02x 0x%x (crc32)\n", LH_version, a, LH_crc32);
400
+                if (a == ((LH_crc32 >> 24) & 0xff))
401
+                    v = 1;
402
+            }
403
+        } else {
404
+            uint16_t a = eh[SIZEOF_EH - 1], b = eh[SIZEOF_EH - 2];
405
+
406
+            if (LH_flags & F_USEDD) {
407
+                cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (moddate)\n", LH_version, a, b, LH_mtime);
408
+                if ((b | (a << 8)) == (LH_mtime & 0xffff))
409
+                    v = 1;
410
+            } else {
411
+                cli_dbgmsg("cli_unzip: decrypt - (v%u) >> 0x0000%02x%02x 0x%x (crc32)\n", LH_version, eh[SIZEOF_EH - 1], eh[SIZEOF_EH - 2], LH_crc32);
412
+                if ((b | (a << 8)) == ((LH_crc32 >> 16) & 0xffff))
413
+                    v = 1;
414
+            }
415
+        }
416
+
417
+        if (v) {
418
+            char name[1024], obuf[BUFSIZ];
419
+            char *tempfile       = name;
420
+            unsigned int written = 0, total = 0;
421
+            fmap_t *dcypt_map;
422
+            const uint8_t *dcypt_zip;
423
+            int of;
424
+
425
+            cli_dbgmsg("cli_unzip: decrypt - password [%s] matches\n", password->name);
426
+
427
+            /* output decrypted data to tempfile */
428
+            if (tmpd) {
429
+                snprintf(name, sizeof(name), "%s" PATHSEP "zip.decrypt.%03u", tmpd, *fu);
430
+                name[sizeof(name) - 1] = '\0';
431
+            } else {
432
+                if (!(tempfile = cli_gentemp(ctx->engine->tmpdir))) return CL_EMEM;
433
+            }
434
+            if ((of = open(tempfile, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR | S_IWUSR)) == -1) {
435
+                cli_warnmsg("cli_unzip: decrypt - failed to create temporary file %s\n", tempfile);
436
+                if (!tmpd) free(tempfile);
437
+                return CL_ETMPFILE;
438
+            }
439
+
440
+            for (i = 12; i < csize; i++) {
441
+                obuf[written] = src[i] ^ zdecryptbyte(key);
442
+                zupdatekey(key, obuf[written]);
443
+
444
+                written++;
445
+                if (written >= BUFSIZ) {
446
+                    if (cli_writen(of, obuf, written) != (int)written) {
447
+                        ret = CL_EWRITE;
448
+                        goto zd_clean;
449
+                    }
450
+                    total += written;
451
+                    written = 0;
452
+                }
453
+            }
454
+            if (written) {
455
+                if (cli_writen(of, obuf, written) != (int)written) {
456
+                    ret = CL_EWRITE;
457
+                    goto zd_clean;
458
+                }
459
+                total += written;
460
+                written = 0;
461
+            }
462
+
463
+            cli_dbgmsg("cli_unzip: decrypt - decrypted %u bytes to %s\n", total, tempfile);
464
+
465
+            /* decrypt data to new fmap -> buffer */
466
+            if (!(dcypt_map = fmap(of, 0, total))) {
467
+                cli_warnmsg("cli_unzip: decrypt - failed to create fmap on decrypted file %s\n", tempfile);
468
+                ret = CL_EMAP;
469
+                goto zd_clean;
470
+            }
471
+
472
+            if (!(dcypt_zip = fmap_need_off_once(dcypt_map, 0, total))) {
473
+                cli_warnmsg("cli_unzip: decrypt - failed to acquire buffer on decrypted file %s\n", tempfile);
474
+                funmap(dcypt_map);
475
+                ret = CL_EREAD;
476
+                goto zd_clean;
477
+            }
478
+
479
+            /* call unz on decrypted output */
480
+            ret = unz(dcypt_zip, csize - SIZEOF_EH, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb);
481
+
482
+            /* clean-up and return */
483
+            funmap(dcypt_map);
484
+        zd_clean:
485
+            close(of);
486
+            if (!ctx->engine->keeptmp)
487 487
                 if (cli_unlink(tempfile)) {
488
-		    if (!tmpd) free(tempfile);
489
-		    return CL_EUNLINK;
490
-		}
488
+                    if (!tmpd) free(tempfile);
489
+                    return CL_EUNLINK;
490
+                }
491 491
             if (!tmpd) free(tempfile);
492
-	    return ret;
493
-	}
492
+            return ret;
493
+        }
494 494
 
495
-	if (pass_zip)
496
-	    pass_zip = pass_zip->next;
497
-	else
498
-	    pass_any = pass_any->next;
495
+        if (pass_zip)
496
+            pass_zip = pass_zip->next;
497
+        else
498
+            pass_any = pass_any->next;
499 499
     }
500 500
 
501 501
     cli_dbgmsg("cli_unzip: decrypt - skipping encrypted file, no valid passwords\n");
502 502
     return CL_SUCCESS;
503 503
 }
504 504
 
505
-static unsigned int lhdr(fmap_t *map, uint32_t loff,uint32_t zsize, unsigned int *fu, unsigned int fc, const uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int detect_encrypted, zip_cb zcb, uint32_t *file_local_header_size, uint32_t* file_local_data_size) {
506
-  const uint8_t *lh, *zip;
507
-  char name[256];
508
-  uint32_t csize, usize;
509
-  int virus_found = 0;
510
-
511
-  if(!(lh = fmap_need_off(map, loff, SIZEOF_LH))) {
512
-      cli_dbgmsg("cli_unzip: lh - out of file\n");
513
-      return 0;
514
-  }
515
-  if(LH_magic != 0x04034b50) {
516
-    if (!ch) cli_dbgmsg("cli_unzip: lh - wrkcomplete\n");
517
-    else cli_dbgmsg("cli_unzip: lh - bad magic\n");
518
-    fmap_unneed_off(map, loff, SIZEOF_LH);
519
-    return 0;
520
-  }
521
-
522
-  zip = lh + SIZEOF_LH;
523
-  zsize-=SIZEOF_LH;
524
-
525
-  if(zsize<=LH_flen) {
526
-    cli_dbgmsg("cli_unzip: lh - fname out of file\n");
527
-    fmap_unneed_off(map, loff, SIZEOF_LH);
528
-    return 0;
529
-  }
530
-  if(ctx->engine->cdb || cli_debug_flag) {
531
-      uint32_t nsize = (LH_flen>=sizeof(name))?sizeof(name)-1:LH_flen;
532
-      const char *src;
533
-      if(nsize && (src = fmap_need_ptr_once(map, zip, nsize))) {
534
-	  memcpy(name, zip, nsize);
535
-	  name[nsize]='\0';
536
-      } else
537
-	  name[0] = '\0';
538
-  }
539
-  zip+=LH_flen;
540
-  zsize-=LH_flen;
541
-
542
-  cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%x:%u:%u:%u\n", ((LH_flags & F_ENCR)!=0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion);
543
-  /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */
544
-
545
-  if(cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR)!=0, fc, LH_crc32, NULL) == CL_VIRUS) {
546
-      *ret = CL_VIRUS;
547
-      if (!SCAN_ALLMATCHES)
548
-          return 0;
549
-      virus_found = 1;
550
-  }
551
-
552
-  if(LH_flags & F_MSKED) {
553
-    cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n");
554
-    /* FIXME: need to find/craft a sample */
555
-    fmap_unneed_off(map, loff, SIZEOF_LH);
556
-    return 0;
557
-  }
558
-
559
-  if(detect_encrypted && (LH_flags & F_ENCR) && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
560
-    cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
561
-    *ret = cli_append_virus(ctx, "Heuristics.Encrypted.Zip");
562
-    if ((*ret == CL_VIRUS && !SCAN_ALLMATCHES) || *ret != CL_CLEAN) {
505
+static unsigned int lhdr(fmap_t *map, uint32_t loff, uint32_t zsize, unsigned int *fu, unsigned int fc, const uint8_t *ch, int *ret, cli_ctx *ctx, char *tmpd, int detect_encrypted, zip_cb zcb, uint32_t *file_local_header_size, uint32_t *file_local_data_size)
506
+{
507
+    const uint8_t *lh, *zip;
508
+    char name[256];
509
+    uint32_t csize, usize;
510
+    int virus_found = 0;
511
+
512
+    if (!(lh = fmap_need_off(map, loff, SIZEOF_LH))) {
513
+        cli_dbgmsg("cli_unzip: lh - out of file\n");
514
+        return 0;
515
+    }
516
+    if (LH_magic != 0x04034b50) {
517
+        if (!ch)
518
+            cli_dbgmsg("cli_unzip: lh - wrkcomplete\n");
519
+        else
520
+            cli_dbgmsg("cli_unzip: lh - bad magic\n");
521
+        fmap_unneed_off(map, loff, SIZEOF_LH);
522
+        return 0;
523
+    }
524
+
525
+    zip = lh + SIZEOF_LH;
526
+    zsize -= SIZEOF_LH;
527
+
528
+    if (zsize <= LH_flen) {
529
+        cli_dbgmsg("cli_unzip: lh - fname out of file\n");
530
+        fmap_unneed_off(map, loff, SIZEOF_LH);
531
+        return 0;
532
+    }
533
+    if (ctx->engine->cdb || cli_debug_flag) {
534
+        uint32_t nsize = (LH_flen >= sizeof(name)) ? sizeof(name) - 1 : LH_flen;
535
+        const char *src;
536
+        if (nsize && (src = fmap_need_ptr_once(map, zip, nsize))) {
537
+            memcpy(name, zip, nsize);
538
+            name[nsize] = '\0';
539
+        } else
540
+            name[0] = '\0';
541
+    }
542
+    zip += LH_flen;
543
+    zsize -= LH_flen;
544
+
545
+    cli_dbgmsg("cli_unzip: lh - ZMDNAME:%d:%s:%u:%u:%x:%u:%u:%u\n", ((LH_flags & F_ENCR) != 0), name, LH_usize, LH_csize, LH_crc32, LH_method, fc, ctx->recursion);
546
+    /* ZMDfmt virname:encrypted(0-1):filename(exact|*):usize(exact|*):csize(exact|*):crc32(exact|*):method(exact|*):fileno(exact|*):maxdepth(exact|*) */
547
+
548
+    if (cli_matchmeta(ctx, name, LH_csize, LH_usize, (LH_flags & F_ENCR) != 0, fc, LH_crc32, NULL) == CL_VIRUS) {
549
+        *ret = CL_VIRUS;
550
+        if (!SCAN_ALLMATCHES)
551
+            return 0;
552
+        virus_found = 1;
553
+    }
554
+
555
+    if (LH_flags & F_MSKED) {
556
+        cli_dbgmsg("cli_unzip: lh - header has got unusable masked data\n");
557
+        /* FIXME: need to find/craft a sample */
558
+        fmap_unneed_off(map, loff, SIZEOF_LH);
559
+        return 0;
560
+    }
561
+
562
+    if (detect_encrypted && (LH_flags & F_ENCR) && SCAN_HEURISTIC_ENCRYPTED_ARCHIVE) {
563
+        cli_dbgmsg("cli_unzip: Encrypted files found in archive.\n");
564
+        *ret = cli_append_virus(ctx, "Heuristics.Encrypted.Zip");
565
+        if ((*ret == CL_VIRUS && !SCAN_ALLMATCHES) || *ret != CL_CLEAN) {
566
+            fmap_unneed_off(map, loff, SIZEOF_LH);
567
+            return 0;
568
+        }
569
+        virus_found = 1;
570
+    }
571
+
572
+    if (LH_flags & F_USEDD) {
573
+        cli_dbgmsg("cli_unzip: lh - has data desc\n");
574
+        if (!ch) {
575
+            fmap_unneed_off(map, loff, SIZEOF_LH);
576
+            return 0;
577
+        } else {
578
+            usize = CH_usize;
579
+            csize = CH_csize;
580
+        }
581
+    } else {
582
+        usize = LH_usize;
583
+        csize = LH_csize;
584
+    }
585
+
586
+    if (zsize <= LH_elen) {
587
+        cli_dbgmsg("cli_unzip: lh - extra out of file\n");
563 588
         fmap_unneed_off(map, loff, SIZEOF_LH);
564 589
         return 0;
565 590
     }
566
-    virus_found = 1;
567
-  }
568
-
569
-  if(LH_flags & F_USEDD) {
570
-    cli_dbgmsg("cli_unzip: lh - has data desc\n");
571
-    if(!ch) {
572
-	fmap_unneed_off(map, loff, SIZEOF_LH);
573
-	return 0;
574
-    }
575
-    else { usize = CH_usize; csize = CH_csize; }
576
-  } else { usize = LH_usize; csize = LH_csize; }
577
-
578
-  if(zsize<=LH_elen) {
579
-    cli_dbgmsg("cli_unzip: lh - extra out of file\n");
580
-    fmap_unneed_off(map, loff, SIZEOF_LH);
581
-    return 0;
582
-  }
583
-  zip+=LH_elen;
584
-  zsize-=LH_elen;
585
-
586
-  if (NULL != file_local_header_size)
587
-      *file_local_header_size = zip - lh;
588
-  if (NULL != file_local_data_size)
589
-      *file_local_data_size = csize;
590
-
591
-  if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
592
-      cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
593
-  } else {
594
-      if(zsize<csize) {
595
-	  cli_dbgmsg("cli_unzip: lh - stream out of file\n");
596
-	  fmap_unneed_off(map, loff, SIZEOF_LH);
597
-	  return 0;
598
-      }
599
-
600
-      if(LH_flags & F_ENCR) {
601
-	  if(fmap_need_ptr_once(map, zip, csize))
602
-	      *ret = zdecrypt(zip, csize, usize, lh, fu, ctx, tmpd, zcb);
603
-      } else {
604
-	  if(fmap_need_ptr_once(map, zip, csize))
605
-	      *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb);
606
-      }
607
-      zip+=csize;
608
-      zsize-=csize;
609
-  }
610
-
611
-  if (virus_found != 0)
612
-      *ret = CL_VIRUS;
613
-
614
-  fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */
615
-  if(LH_flags & F_USEDD) {
616
-      if(zsize<12) {
617
-	  cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
618
-	  return 0;
619
-      }
620
-      zsize-=12;
621
-      if(fmap_need_ptr_once(map, zip, 4)) {
622
-	  if(cli_readint32(zip)==0x08074b50) {
623
-	      if(zsize<4) {
624
-		  cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
625
-		  return 0;
626
-	      }
627
-	      zip+=4;
628
-	  }
629
-      }
630
-      zip+=12;
631
-  }
632
-  return zip-lh;
591
+    zip += LH_elen;
592
+    zsize -= LH_elen;
593
+
594
+    if (NULL != file_local_header_size)
595
+        *file_local_header_size = zip - lh;
596
+    if (NULL != file_local_data_size)
597
+        *file_local_data_size = csize;
598
+
599
+    if (!csize) { /* FIXME: what's used for method0 files? csize or usize? Nothing in the specs, needs testing */
600
+        cli_dbgmsg("cli_unzip: lh - skipping empty file\n");
601
+    } else {
602
+        if (zsize < csize) {
603
+            cli_dbgmsg("cli_unzip: lh - stream out of file\n");
604
+            fmap_unneed_off(map, loff, SIZEOF_LH);
605
+            return 0;
606
+        }
607
+
608
+        if (LH_flags & F_ENCR) {
609
+            if (fmap_need_ptr_once(map, zip, csize))
610
+                *ret = zdecrypt(zip, csize, usize, lh, fu, ctx, tmpd, zcb);
611
+        } else {
612
+            if (fmap_need_ptr_once(map, zip, csize))
613
+                *ret = unz(zip, csize, usize, LH_method, LH_flags, fu, ctx, tmpd, zcb);
614
+        }
615
+        zip += csize;
616
+        zsize -= csize;
617
+    }
618
+
619
+    if (virus_found != 0)
620
+        *ret = CL_VIRUS;
621
+
622
+    fmap_unneed_off(map, loff, SIZEOF_LH); /* unneed now. block is guaranteed to exists till the next need */
623
+    if (LH_flags & F_USEDD) {
624
+        if (zsize < 12) {
625
+            cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
626
+            return 0;
627
+        }
628
+        zsize -= 12;
629
+        if (fmap_need_ptr_once(map, zip, 4)) {
630
+            if (cli_readint32(zip) == 0x08074b50) {
631
+                if (zsize < 4) {
632
+                    cli_dbgmsg("cli_unzip: lh - data desc out of file\n");
633
+                    return 0;
634
+                }
635
+                zip += 4;
636
+            }
637
+        }
638
+        zip += 12;
639
+    }
640
+    return zip - lh;
633 641
 }
634 642
 
635
-static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, struct zip_requests *requests, uint32_t *file_local_offset, uint32_t *file_local_header_size, uint32_t *file_local_data_size) {
636
-  char name[256];
637
-  int last = 0;
638
-  const uint8_t *ch;
639
-  int virus_found = 0;
640
-
641
-  if (NULL != file_local_offset)
642
-      *file_local_offset = 0;
643
-  if (NULL != file_local_header_size)
644
-      *file_local_header_size = 0;
645
-  if (NULL != file_local_data_size)
646
-      *file_local_data_size = 0;
647
-
648
-  if(!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) {
649
-      if(ch) fmap_unneed_ptr(map, ch, SIZEOF_CH);
650
-      cli_dbgmsg("cli_unzip: ch - wrkcomplete\n");
651
-      return 0;
652
-  }
653
-  coff+=SIZEOF_CH;
654
-
655
-  cli_dbgmsg("cli_unzip: ch - flags %x - method %x - csize %x - usize %x - flen %x - elen %x - clen %x - disk %x - off %x\n", CH_flags, CH_method, CH_csize, CH_usize, CH_flen, CH_elen, CH_clen, CH_dsk, CH_off);
656
-
657
-  if(zsize-coff<=CH_flen) {
658
-    cli_dbgmsg("cli_unzip: ch - fname out of file\n");
659
-    last=1;
660
-  }
661
-
662
-  name[0]='\0';
663
-  if(!last) {
664
-      unsigned int size = (CH_flen>=sizeof(name))?sizeof(name)-1:CH_flen;
665
-      const char *src = fmap_need_off_once(map, coff, size);
666
-      if(src) {
667
-	  memcpy(name, src, size);
668
-	  name[size]='\0';
669
-	  cli_dbgmsg("cli_unzip: ch - fname: %s\n", name);
670
-      }
671
-  }
672
-  coff+=CH_flen;
673
-
674
-  /* requests do not supply a ctx; also prevent multiple scans */
675
-  if(ctx && cli_matchmeta(ctx, name, CH_csize, CH_usize, (CH_flags & F_ENCR)!=0, fc, CH_crc32, NULL) == CL_VIRUS)
676
-    virus_found = 1;
677
-
678
-  if(zsize-coff<=CH_elen && !last) {
679
-    cli_dbgmsg("cli_unzip: ch - extra out of file\n");
680
-    last=1;
681
-  }
682
-  coff+=CH_elen;
683
-
684
-  if(zsize-coff<CH_clen && !last) {
685
-    cli_dbgmsg("cli_unzip: ch - comment out of file\n");
686
-    last = 1;
687
-  }
688
-  coff+=CH_clen;
689
-
690
-  if (!requests) {
691
-      if(CH_off<zsize-SIZEOF_LH) {
692
-          if (NULL != file_local_offset)
693
-              *file_local_offset = CH_off;
694
-          lhdr(map, CH_off, zsize-CH_off, fu, fc, ch, ret, ctx, tmpd, 1, zip_scan_cb, file_local_header_size, file_local_data_size);
695
-      } else cli_dbgmsg("cli_unzip: ch - local hdr out of file\n");
696
-  }
697
-  else {
698
-      int i;
699
-      size_t len;
700
-
701
-      if (!last) {
702
-          for (i = 0; i < requests->namecnt; ++i) {
703
-              cli_dbgmsg("checking for %i: %s\n", i, requests->names[i]);
704
-
705
-              len = MIN(sizeof(name)-1, requests->namelens[i]);
706
-              if (!strncmp(requests->names[i], name, len)) {
707
-                  requests->match = 1;
708
-                  requests->found = i;
709
-                  requests->loff = CH_off;
710
-              }
711
-          }
712
-      }
713
-  }
714
-
715
-  if (virus_found == 1)
716
-      *ret = CL_VIRUS;
717
-  fmap_unneed_ptr(map, ch, SIZEOF_CH);
718
-  return (last?0:coff);
643
+static unsigned int chdr(fmap_t *map, uint32_t coff, uint32_t zsize, unsigned int *fu, unsigned int fc, int *ret, cli_ctx *ctx, char *tmpd, struct zip_requests *requests, uint32_t *file_local_offset, uint32_t *file_local_header_size, uint32_t *file_local_data_size)
644
+{
645
+    char name[256];
646
+    int last = 0;
647
+    const uint8_t *ch;
648
+    int virus_found = 0;
649
+
650
+    if (NULL != file_local_offset)
651
+        *file_local_offset = 0;
652
+    if (NULL != file_local_header_size)
653
+        *file_local_header_size = 0;
654
+    if (NULL != file_local_data_size)
655
+        *file_local_data_size = 0;
656
+
657
+    if (!(ch = fmap_need_off(map, coff, SIZEOF_CH)) || CH_magic != 0x02014b50) {
658
+        if (ch) fmap_unneed_ptr(map, ch, SIZEOF_CH);
659
+        cli_dbgmsg("cli_unzip: ch - wrkcomplete\n");
660
+        return 0;
661
+    }
662
+    coff += SIZEOF_CH;
663
+
664
+    cli_dbgmsg("cli_unzip: ch - flags %x - method %x - csize %x - usize %x - flen %x - elen %x - clen %x - disk %x - off %x\n", CH_flags, CH_method, CH_csize, CH_usize, CH_flen, CH_elen, CH_clen, CH_dsk, CH_off);
665
+
666
+    if (zsize - coff <= CH_flen) {
667
+        cli_dbgmsg("cli_unzip: ch - fname out of file\n");
668
+        last = 1;
669
+    }
670
+
671
+    name[0] = '\0';
672
+    if (!last) {
673
+        unsigned int size = (CH_flen >= sizeof(name)) ? sizeof(name) - 1 : CH_flen;
674
+        const char *src   = fmap_need_off_once(map, coff, size);
675
+        if (src) {
676
+            memcpy(name, src, size);
677
+            name[size] = '\0';
678
+            cli_dbgmsg("cli_unzip: ch - fname: %s\n", name);
679
+        }
680
+    }
681
+    coff += CH_flen;
682
+
683
+    /* requests do not supply a ctx; also prevent multiple scans */
684
+    if (ctx && cli_matchmeta(ctx, name, CH_csize, CH_usize, (CH_flags & F_ENCR) != 0, fc, CH_crc32, NULL) == CL_VIRUS)
685
+        virus_found = 1;
686
+
687
+    if (zsize - coff <= CH_elen && !last) {
688
+        cli_dbgmsg("cli_unzip: ch - extra out of file\n");
689
+        last = 1;
690
+    }
691
+    coff += CH_elen;
692
+
693
+    if (zsize - coff < CH_clen && !last) {
694
+        cli_dbgmsg("cli_unzip: ch - comment out of file\n");
695
+        last = 1;
696
+    }
697
+    coff += CH_clen;
698
+
699
+    if (!requests) {
700
+        if (CH_off < zsize - SIZEOF_LH) {
701
+            if (NULL != file_local_offset)
702
+                *file_local_offset = CH_off;
703
+            lhdr(map, CH_off, zsize - CH_off, fu, fc, ch, ret, ctx, tmpd, 1, zip_scan_cb, file_local_header_size, file_local_data_size);
704
+        } else
705
+            cli_dbgmsg("cli_unzip: ch - local hdr out of file\n");
706
+    } else {
707
+        int i;
708
+        size_t len;
709
+
710
+        if (!last) {
711
+            for (i = 0; i < requests->namecnt; ++i) {
712
+                cli_dbgmsg("checking for %i: %s\n", i, requests->names[i]);
713
+
714
+                len = MIN(sizeof(name) - 1, requests->namelens[i]);
715
+                if (!strncmp(requests->names[i], name, len)) {
716
+                    requests->match = 1;
717
+                    requests->found = i;
718
+                    requests->loff  = CH_off;
719
+                }
720
+            }
721
+        }
722
+    }
723
+
724
+    if (virus_found == 1)
725
+        *ret = CL_VIRUS;
726
+    fmap_unneed_ptr(map, ch, SIZEOF_CH);
727
+    return (last ? 0 : coff);
719 728
 }
720 729
 
721
-int cli_unzip(cli_ctx *ctx) {
722
-  unsigned int fc=0, fu=0;
723
-  int ret=CL_CLEAN;
724
-  uint32_t fsize, lhoff = 0, coff = 0;
725
-  fmap_t *map = *ctx->fmap;
726
-  char *tmpd;
727
-  const char *ptr;
728
-  int virus_found = 0;
730
+int cli_unzip(cli_ctx *ctx)
731
+{
732
+    unsigned int fc = 0, fu = 0;
733
+    int ret = CL_CLEAN;
734
+    uint32_t fsize, lhoff = 0, coff = 0;
735
+    fmap_t *map = *ctx->fmap;
736
+    char *tmpd;
737
+    const char *ptr;
738
+    int virus_found = 0;
729 739
 #if HAVE_JSON
730
-  int toval = 0;
740
+    int toval = 0;
731 741
 #endif
732
-  int bZipBombDetected                 = 0;
733
-  uint32_t cur_file_local_offset       = 0;
734
-  uint32_t cur_file_local_header_size  = 0;
735
-  uint32_t cur_file_local_data_size    = 0;
736
-  uint32_t prev_file_local_offset      = 0;
737
-  uint32_t prev_file_local_header_size = 0;
738
-  uint32_t prev_file_local_data_size   = 0;
739
-
740
-  cli_dbgmsg("in cli_unzip\n");
741
-  fsize = (uint32_t)map->len;
742
-  if(sizeof(off_t)!=sizeof(uint32_t) && (size_t)fsize!=map->len) {
743
-    cli_dbgmsg("cli_unzip: file too big\n");
744
-    return CL_CLEAN;
745
-  }
746
-  if (fsize < SIZEOF_CH) {
747
-    cli_dbgmsg("cli_unzip: file too short\n");
748
-    return CL_CLEAN;
749
-  }
750
-  if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) {
751
-    return CL_ETMPDIR;
752
-  }
753
-  if (mkdir(tmpd, 0700)) {
754
-    cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd);
755
-    free(tmpd);
756
-    return CL_ETMPDIR;
757
-  }
758
-
759
-  for(coff=fsize-22 ; coff>0 ; coff--) { /* sizeof(EOC)==22 */
760
-      if(!(ptr = fmap_need_off_once(map, coff, 20)))
761
-	  continue;
762
-      if(cli_readint32(ptr)==0x06054b50) {
763
-	  uint32_t chptr = cli_readint32(&ptr[16]);
764
-	  if(!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue;
765
-	  coff=chptr;
766
-	  break;
767
-      }
768
-  }
769
-
770
-  if(coff) {
771
-      uint32_t nOverlappingFiles = 0;
772
-
773
-      cli_dbgmsg("cli_unzip: central @%x\n", coff);
774
-      while((coff=chdr(map, coff, fsize, &fu, fc+1, &ret, ctx, tmpd, NULL, &cur_file_local_offset, &cur_file_local_header_size, &cur_file_local_data_size))) {
775
-	  fc++;
776
-	  if (ctx->engine->maxfiles && fu>=ctx->engine->maxfiles) {
777
-	      cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
778
-	      ret=CL_EMAXFILES;
779
-	  }
780
-
781
-    if (cli_checktimelimit(ctx) != CL_SUCCESS) {
782
-        cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime);
783
-        ret = CL_ETIMEOUT;
784
-    }
785
-    /*
786
-     * Detect overlapping files and zip bombs.
787
-     */
788
-    if ((((cur_file_local_offset > prev_file_local_offset) && (cur_file_local_offset < prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size)) ||
789
-         ((prev_file_local_offset > cur_file_local_offset) && (prev_file_local_offset < cur_file_local_offset + cur_file_local_header_size + cur_file_local_data_size))) &&
790
-        (cur_file_local_header_size + cur_file_local_data_size > 0)) {
791
-        /* Overlapping file detected */
792
-        nOverlappingFiles++;
793
-
794
-        cli_dbgmsg("cli_unzip: Overlapping files detected.\n");
795
-        cli_dbgmsg("    previous file end:  %u\n", prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size);
796
-        cli_dbgmsg("    current file start: %u\n", cur_file_local_offset);
797
-        if (ZIP_MAX_NUM_OVERLAPPING_FILES < nOverlappingFiles) {
798
-          if (SCAN_HEURISTICS) {
799
-              ret         = cli_append_virus(ctx, "Heuristics.Zip.OverlappingFiles");
800
-              virus_found = 1;
801
-          } else {
802
-              ret = CL_EFORMAT;
803
-          }
804
-          bZipBombDetected = 1;
742
+    int bZipBombDetected                 = 0;
743
+    uint32_t cur_file_local_offset       = 0;
744
+    uint32_t cur_file_local_header_size  = 0;
745
+    uint32_t cur_file_local_data_size    = 0;
746
+    uint32_t prev_file_local_offset      = 0;
747
+    uint32_t prev_file_local_header_size = 0;
748
+    uint32_t prev_file_local_data_size   = 0;
749
+
750
+    cli_dbgmsg("in cli_unzip\n");
751
+    fsize = (uint32_t)map->len;
752
+    if (sizeof(off_t) != sizeof(uint32_t) && (size_t)fsize != map->len) {
753
+        cli_dbgmsg("cli_unzip: file too big\n");
754
+        return CL_CLEAN;
755
+    }
756
+    if (fsize < SIZEOF_CH) {
757
+        cli_dbgmsg("cli_unzip: file too short\n");
758
+        return CL_CLEAN;
759
+    }
760
+    if (!(tmpd = cli_gentemp(ctx->engine->tmpdir))) {
761
+        return CL_ETMPDIR;
762
+    }
763
+    if (mkdir(tmpd, 0700)) {
764
+        cli_dbgmsg("cli_unzip: Can't create temporary directory %s\n", tmpd);
765
+        free(tmpd);
766
+        return CL_ETMPDIR;
767
+    }
768
+
769
+    for (coff = fsize - 22; coff > 0; coff--) { /* sizeof(EOC)==22 */
770
+        if (!(ptr = fmap_need_off_once(map, coff, 20)))
771
+            continue;
772
+        if (cli_readint32(ptr) == 0x06054b50) {
773
+            uint32_t chptr = cli_readint32(&ptr[16]);
774
+            if (!CLI_ISCONTAINED(0, fsize, chptr, SIZEOF_CH)) continue;
775
+            coff = chptr;
776
+            break;
805 777
         }
806 778
     }
807
-    prev_file_local_offset      = cur_file_local_offset;
808
-    prev_file_local_header_size = cur_file_local_header_size;
809
-    prev_file_local_data_size   = cur_file_local_data_size;
779
+
780
+    if (coff) {
781
+        uint32_t nOverlappingFiles = 0;
782
+
783
+        cli_dbgmsg("cli_unzip: central @%x\n", coff);
784
+        while ((coff = chdr(map, coff, fsize, &fu, fc + 1, &ret, ctx, tmpd, NULL, &cur_file_local_offset, &cur_file_local_header_size, &cur_file_local_data_size))) {
785
+            fc++;
786
+            if (ctx->engine->maxfiles && fu >= ctx->engine->maxfiles) {
787
+                cli_dbgmsg("cli_unzip: Files limit reached (max: %u)\n", ctx->engine->maxfiles);
788
+                ret = CL_EMAXFILES;
789
+            }
790
+
791
+            if (cli_checktimelimit(ctx) != CL_SUCCESS) {
792
+                cli_dbgmsg("cli_unzip: Time limit reached (max: %u)\n", ctx->engine->maxscantime);
793
+                ret = CL_ETIMEOUT;
794
+            }
795
+            /*
796
+     * Detect overlapping files and zip bombs.
797
+     */
798
+            if ((((cur_file_local_offset > prev_file_local_offset) && (cur_file_local_offset < prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size)) ||
799
+                 ((prev_file_local_offset > cur_file_local_offset) && (prev_file_local_offset < cur_file_local_offset + cur_file_local_header_size + cur_file_local_data_size))) &&
800
+                (cur_file_local_header_size + cur_file_local_data_size > 0)) {
801
+                /* Overlapping file detected */
802
+                nOverlappingFiles++;
803
+
804
+                cli_dbgmsg("cli_unzip: Overlapping files detected.\n");
805
+                cli_dbgmsg("    previous file end:  %u\n", prev_file_local_offset + prev_file_local_header_size + prev_file_local_data_size);
806
+                cli_dbgmsg("    current file start: %u\n", cur_file_local_offset);
807
+                if (ZIP_MAX_NUM_OVERLAPPING_FILES < nOverlappingFiles) {
808
+                    if (SCAN_HEURISTICS) {
809
+                        ret         = cli_append_virus(ctx, "Heuristics.Zip.OverlappingFiles");
810
+                        virus_found = 1;
811
+                    } else {
812
+                        ret = CL_EFORMAT;
813
+                    }
814
+                    bZipBombDetected = 1;
815
+                }
816
+            }
817
+            prev_file_local_offset      = cur_file_local_offset;
818
+            prev_file_local_header_size = cur_file_local_header_size;
819
+            prev_file_local_data_size   = cur_file_local_data_size;
810 820
 
811 821
 #if HAVE_JSON
812
-          if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
813
-              ret=CL_ETIMEOUT;
814
-          }
822
+            if (cli_json_timeout_cycle_check(ctx, &toval) != CL_SUCCESS) {
823
+                ret = CL_ETIMEOUT;
824
+            }
815 825
 #endif
816
-          if (ret != CL_CLEAN) {
817
-              if (ret == CL_VIRUS && SCAN_ALLMATCHES && !bZipBombDetected) {
818
-                  ret = CL_CLEAN;
819
-                  virus_found = 1;
820
-              } else
821
-                  break;
822
-          }
823
-      }
824
-  } else cli_dbgmsg("cli_unzip: central not found, using localhdrs\n");
825
-  if (virus_found == 1)
826
-      ret = CL_VIRUS;
827
-  if(fu<=(fc/4)) { /* FIXME: make up a sane ratio or remove the whole logic */
828
-    fc = 0;
829
-    while (ret==CL_CLEAN && lhoff<fsize && (coff=lhdr(map, lhoff, fsize-lhoff, &fu, fc+1, NULL, &ret, ctx, tmpd, 1, zip_scan_cb, NULL, NULL))) {
830