Bug Summary

File:jdk/src/java.base/share/native/libzip/zip_util.c
Warning:line 1092, column 25
Value stored to 'off' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name zip_util.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -mthread-model posix -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -fno-rounding-math -masm-verbose -mconstructor-aliases -munwind-tables -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining -debugger-tuning=gdb -resource-dir /usr/lib/llvm-10/lib/clang/10.0.0 -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/modules_include/java.base/linux -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libjava -I /home/daniel/Projects/java/jdk/src/java.base/unix/native/libjava -I /home/daniel/Projects/java/jdk/src/hotspot/share/include -I /home/daniel/Projects/java/jdk/src/hotspot/os/posix/include -D LIBC=gnu -D _GNU_SOURCE -D _REENTRANT -D _LARGEFILE64_SOURCE -D LINUX -D DEBUG -D _LITTLE_ENDIAN -D ARCH="amd64" -D amd64 -D _LP64=1 -I /home/daniel/Projects/java/jdk/src/java.base/share/native/libzip -I /home/daniel/Projects/java/jdk/build/linux-x86_64-server-fastdebug/support/headers/java.base -D USE_MMAP -U DEBUG -D _FORTIFY_SOURCE=2 -internal-isystem /usr/local/include -internal-isystem /usr/lib/llvm-10/lib/clang/10.0.0/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wno-unused -Wno-unused-function -Wno-implicit-fallthrough -std=c99 -fdebug-compilation-dir /home/daniel/Projects/java/jdk/make -ferror-limit 19 -fmessage-length 0 -fvisibility hidden -stack-protector 1 -fgnuc-version=4.2.1 -fobjc-runtime=gcc -fdiagnostics-show-option -vectorize-loops -vectorize-slp -analyzer-output=html -faddrsig -o /home/daniel/Projects/java/scan/2021-12-21-193737-8510-1 -x c /home/daniel/Projects/java/jdk/src/java.base/share/native/libzip/zip_util.c
1/*
2 * Copyright (c) 1995, 2020, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26/*
27 * Support for reading ZIP/JAR files.
28 */
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <stddef.h>
33#include <string.h>
34#include <fcntl.h>
35#include <limits.h>
36#include <time.h>
37#include <ctype.h>
38#include <assert.h>
39
40#include "jni.h"
41#include "jni_util.h"
42#include "jlong.h"
43#include "jvm.h"
44#include "io_util.h"
45#include "io_util_md.h"
46#include "zip_util.h"
47#include <zlib.h>
48
49#ifdef _ALLBSD_SOURCE
50#define off64_t off_t
51#define mmap64 mmap
52#endif
53
54/* USE_MMAP means mmap the CEN & ENDHDR part of the zip file. */
55#ifdef USE_MMAP1
56#include <sys/mman.h>
57#endif
58
59#define MAXREFS0xFFFF 0xFFFF /* max number of open zip file references */
60
61#define MCREATE()JVM_RawMonitorCreate() JVM_RawMonitorCreate()
62#define MLOCK(lock)JVM_RawMonitorEnter(lock) JVM_RawMonitorEnter(lock)
63#define MUNLOCK(lock)JVM_RawMonitorExit(lock) JVM_RawMonitorExit(lock)
64#define MDESTROY(lock)JVM_RawMonitorDestroy(lock) JVM_RawMonitorDestroy(lock)
65
66#define CENSIZE(cen)(46 + ((((unsigned char *)(cen))[28]) | ((((unsigned char *)(
cen))[28 +1]) << 8)) + ((((unsigned char *)(cen))[30]) |
((((unsigned char *)(cen))[30 +1]) << 8)) + ((((unsigned
char *)(cen))[32]) | ((((unsigned char *)(cen))[32 +1]) <<
8)))
(CENHDR46 + CENNAM(cen)((((unsigned char *)(cen))[28]) | ((((unsigned char *)(cen))[
28 +1]) << 8))
+ CENEXT(cen)((((unsigned char *)(cen))[30]) | ((((unsigned char *)(cen))[
30 +1]) << 8))
+ CENCOM(cen)((((unsigned char *)(cen))[32]) | ((((unsigned char *)(cen))[
32 +1]) << 8))
)
67
68static jzfile *zfiles = 0; /* currently open zip files */
69static void *zfiles_lock = 0;
70
71static void freeCEN(jzfile *);
72
73#ifndef PATH_MAX4096
74#define PATH_MAX4096 1024
75#endif
76
77static jint INITIAL_META_COUNT = 2; /* initial number of entries in meta name array */
78
79/*
80 * Declare library specific JNI_Onload entry if static build
81 */
82#ifdef STATIC_BUILD
83DEF_STATIC_JNI_OnLoad
84#endif
85
86/*
87 * The ZFILE_* functions exist to provide some platform-independence with
88 * respect to file access needs.
89 */
90
91/*
92 * Opens the named file for reading, returning a ZFILE.
93 *
94 * Compare this with winFileHandleOpen in windows/native/java/io/io_util_md.c.
95 * This function does not take JNIEnv* and uses CreateFile (instead of
96 * CreateFileW). The expectation is that this function will be called only
97 * from ZIP_Open_Generic, which in turn is used by the JVM, where we do not
98 * need to concern ourselves with wide chars.
99 */
100static ZFILEint
101ZFILE_Open(const char *fname, int flags) {
102#ifdef WIN32
103 WCHAR *wfname, *wprefixed_fname;
104 size_t fname_length;
105 jlong fhandle;
106 const DWORD access =
107 (flags & O_RDWR02) ? (GENERIC_WRITE | GENERIC_READ) :
108 (flags & O_WRONLY01) ? GENERIC_WRITE :
109 GENERIC_READ;
110 const DWORD sharing =
111 FILE_SHARE_READ | FILE_SHARE_WRITE;
112 const DWORD disposition =
113 /* Note: O_TRUNC overrides O_CREAT */
114 (flags & O_TRUNC01000) ? CREATE_ALWAYS :
115 (flags & O_CREAT0100) ? OPEN_ALWAYS :
116 OPEN_EXISTING;
117 const DWORD maybeWriteThrough =
118 (flags & (O_SYNC04010000 | O_DSYNC010000)) ?
119 FILE_FLAG_WRITE_THROUGH :
120 FILE_ATTRIBUTE_NORMAL;
121 const DWORD maybeDeleteOnClose =
122 (flags & O_TEMPORARY) ?
123 FILE_FLAG_DELETE_ON_CLOSE :
124 FILE_ATTRIBUTE_NORMAL;
125 const DWORD flagsAndAttributes = maybeWriteThrough | maybeDeleteOnClose;
126
127 fname_length = strlen(fname);
128 if (fname_length < MAX_PATH) {
129 return (jlong)CreateFile(
130 fname, /* path name in multibyte char */
131 access, /* Read and/or write permission */
132 sharing, /* File sharing flags */
133 NULL((void*)0), /* Security attributes */
134 disposition, /* creation disposition */
135 flagsAndAttributes, /* flags and attributes */
136 NULL((void*)0));
137 } else {
138 /* Get required buffer size to convert to Unicode */
139 int wfname_len = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
140 fname, -1, NULL((void*)0), 0);
141 if (wfname_len == 0) {
142 return (jlong)INVALID_HANDLE_VALUE;
143 }
144 if ((wfname = (WCHAR*)malloc(wfname_len * sizeof(WCHAR))) == NULL((void*)0)) {
145 return (jlong)INVALID_HANDLE_VALUE;
146 }
147 if (MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
148 fname, -1, wfname, wfname_len) == 0) {
149 free(wfname);
150 return (jlong)INVALID_HANDLE_VALUE;
151 }
152 wprefixed_fname = getPrefixed(wfname, (int)fname_length);
153 fhandle = (jlong)CreateFileW(
154 wprefixed_fname, /* Wide char path name */
155 access, /* Read and/or write permission */
156 sharing, /* File sharing flags */
157 NULL((void*)0), /* Security attributes */
158 disposition, /* creation disposition */
159 flagsAndAttributes, /* flags and attributes */
160 NULL((void*)0));
161 free(wfname);
162 free(wprefixed_fname);
163 return fhandle;
164 }
165#else
166 return open(fname, flags, 0);
167#endif
168}
169
170/*
171 * The io_util_md.h files do not provide IO_CLOSE, hence we use platform
172 * specifics.
173 */
174static void
175ZFILE_Close(ZFILEint zfd) {
176#ifdef WIN32
177 CloseHandle((HANDLE) zfd);
178#else
179 close(zfd);
180#endif
181}
182
183static int
184ZFILE_read(ZFILEint zfd, char *buf, jint nbytes) {
185#ifdef WIN32
186 return (int) IO_ReadhandleRead(zfd, buf, nbytes);
187#else
188 return read(zfd, buf, nbytes);
189#endif
190}
191
192/*
193 * Initialize zip file support. Return 0 if successful otherwise -1
194 * if could not be initialized.
195 */
196static jint
197InitializeZip()
198{
199 static jboolean inited = JNI_FALSE0;
200
201 // Initialize errno to 0. It may be set later (e.g. during memory
202 // allocation) but we can disregard previous values.
203 errno(*__errno_location ()) = 0;
204
205 if (inited)
206 return 0;
207 zfiles_lock = MCREATE()JVM_RawMonitorCreate();
208 if (zfiles_lock == 0) {
209 return -1;
210 }
211 inited = JNI_TRUE1;
212
213 return 0;
214}
215
216/*
217 * Reads len bytes of data into buf.
218 * Returns 0 if all bytes could be read, otherwise returns -1.
219 */
220static int
221readFully(ZFILEint zfd, void *buf, jlong len) {
222 char *bp = (char *) buf;
223
224 while (len > 0) {
225 jlong limit = ((((jlong) 1) << 31) - 1);
226 jint count = (len < limit) ?
227 (jint) len :
228 (jint) limit;
229 jint n = ZFILE_read(zfd, bp, count);
230 if (n > 0) {
231 bp += n;
232 len -= n;
233 } else if (n == -1 && errno(*__errno_location ()) == EINTR4) {
234 /* Retry after EINTR (interrupted by signal). */
235 continue;
236 } else { /* EOF or IO error */
237 return -1;
238 }
239 }
240 return 0;
241}
242
243/*
244 * Reads len bytes of data from the specified offset into buf.
245 * Returns 0 if all bytes could be read, otherwise returns -1.
246 */
247static int
248readFullyAt(ZFILEint zfd, void *buf, jlong len, jlong offset)
249{
250 if (IO_Lseeklseek64(zfd, offset, SEEK_SET0) == -1) {
251 return -1; /* lseek failure. */
252 }
253
254 return readFully(zfd, buf, len);
255}
256
257/*
258 * Allocates a new zip file object for the specified file name.
259 * Returns the zip file object or NULL if not enough memory.
260 */
261static jzfile *
262allocZip(const char *name)
263{
264 jzfile *zip;
265 if (((zip = calloc(1, sizeof(jzfile))) != NULL((void*)0)) &&
266 ((zip->name = strdup(name)) != NULL((void*)0)) &&
267 ((zip->lock = MCREATE()JVM_RawMonitorCreate()) != NULL((void*)0))) {
268 zip->zfd = -1;
269 return zip;
270 }
271
272 if (zip != NULL((void*)0)) {
273 free(zip->name);
274 free(zip);
275 }
276 return NULL((void*)0);
277}
278
279/*
280 * Frees all native resources owned by the specified zip file object.
281 */
282static void
283freeZip(jzfile *zip)
284{
285 /* First free any cached jzentry */
286 ZIP_FreeEntry(zip,0);
287 if (zip->lock != NULL((void*)0)) MDESTROY(zip->lock)JVM_RawMonitorDestroy(zip->lock);
288 free(zip->name);
289 freeCEN(zip);
290
291#ifdef USE_MMAP1
292 if (zip->usemmap) {
293 if (zip->maddr != NULL((void*)0))
294 munmap((char *)zip->maddr, zip->mlen);
295 } else
296#endif
297 {
298 free(zip->cencache.data);
299 }
300 if (zip->comment != NULL((void*)0))
301 free(zip->comment);
302 if (zip->zfd != -1) ZFILE_Close(zip->zfd);
303 free(zip);
304}
305
306/* The END header is followed by a variable length comment of size < 64k. */
307static const jlong END_MAXLEN = 0xFFFF + ENDHDR22;
308
309#define READBLOCKSZ128 128
310
311static jboolean verifyEND(jzfile *zip, jlong endpos, char *endbuf) {
312 /* ENDSIG matched, however the size of file comment in it does not
313 match the real size. One "common" cause for this problem is some
314 "extra" bytes are padded at the end of the zipfile.
315 Let's do some extra verification, we don't care about the performance
316 in this situation.
317 */
318 jlong cenpos = endpos - ENDSIZ(endbuf)((((((unsigned char *)(endbuf))[12]) | ((((unsigned char *)(endbuf
))[12 +1]) << 8)) | (((((unsigned char *)(endbuf))[12 +
2]) | ((((unsigned char *)(endbuf))[12 +2 +1]) << 8)) <<
16)) &0xffffffffUL)
;
319 jlong locpos = cenpos - ENDOFF(endbuf)((((((unsigned char *)(endbuf))[16]) | ((((unsigned char *)(endbuf
))[16 +1]) << 8)) | (((((unsigned char *)(endbuf))[16 +
2]) | ((((unsigned char *)(endbuf))[16 +2 +1]) << 8)) <<
16)) &0xffffffffUL)
;
320 char buf[4];
321 return (cenpos >= 0 &&
322 locpos >= 0 &&
323 readFullyAt(zip->zfd, buf, sizeof(buf), cenpos) != -1 &&
324 CENSIG_AT(buf)(((buf)[0] == 'P') & ((buf)[1] == 'K') & ((buf)[2] ==
1) & ((buf)[3] == 2))
&&
325 readFullyAt(zip->zfd, buf, sizeof(buf), locpos) != -1 &&
326 LOCSIG_AT(buf)(((buf)[0] == 'P') & ((buf)[1] == 'K') & ((buf)[2] ==
3) & ((buf)[3] == 4))
);
327}
328
329/*
330 * Searches for end of central directory (END) header. The contents of
331 * the END header will be read and placed in endbuf. Returns the file
332 * position of the END header, otherwise returns -1 if the END header
333 * was not found or an error occurred.
334 */
335static jlong
336findEND(jzfile *zip, void *endbuf)
337{
338 char buf[READBLOCKSZ128];
339 jlong pos;
340 const jlong len = zip->len;
341 const ZFILEint zfd = zip->zfd;
342 const jlong minHDR = len - END_MAXLEN > 0 ? len - END_MAXLEN : 0;
343 const jlong minPos = minHDR - (sizeof(buf)-ENDHDR22);
344 jint clen;
345
346 for (pos = len - sizeof(buf); pos >= minPos; pos -= (sizeof(buf)-ENDHDR22)) {
347
348 int i;
349 jlong off = 0;
350 if (pos < 0) {
351 /* Pretend there are some NUL bytes before start of file */
352 off = -pos;
353 memset(buf, '\0', (size_t)off);
354 }
355
356 if (readFullyAt(zfd, buf + off, sizeof(buf) - off,
357 pos + off) == -1) {
358 return -1; /* System error */
359 }
360
361 /* Now scan the block backwards for END header signature */
362 for (i = sizeof(buf) - ENDHDR22; i >= 0; i--) {
363 if (buf[i+0] == 'P' &&
364 buf[i+1] == 'K' &&
365 buf[i+2] == '\005' &&
366 buf[i+3] == '\006' &&
367 ((pos + i + ENDHDR22 + ENDCOM(buf + i)((((unsigned char *)(buf + i))[20]) | ((((unsigned char *)(buf
+ i))[20 +1]) << 8))
== len)
368 || verifyEND(zip, pos + i, buf + i))) {
369 /* Found END header */
370 memcpy(endbuf, buf + i, ENDHDR22);
371
372 clen = ENDCOM(endbuf)((((unsigned char *)(endbuf))[20]) | ((((unsigned char *)(endbuf
))[20 +1]) << 8))
;
373 if (clen != 0) {
374 zip->comment = malloc(clen + 1);
375 if (zip->comment == NULL((void*)0)) {
376 return -1;
377 }
378 if (readFullyAt(zfd, zip->comment, clen, pos + i + ENDHDR22)
379 == -1) {
380 free(zip->comment);
381 zip->comment = NULL((void*)0);
382 return -1;
383 }
384 zip->comment[clen] = '\0';
385 zip->clen = clen;
386 }
387 return pos + i;
388 }
389 }
390 }
391
392 return -1; /* END header not found */
393}
394
395/*
396 * Searches for the ZIP64 end of central directory (END) header. The
397 * contents of the ZIP64 END header will be read and placed in end64buf.
398 * Returns the file position of the ZIP64 END header, otherwise returns
399 * -1 if the END header was not found or an error occurred.
400 *
401 * The ZIP format specifies the "position" of each related record as
402 * ...
403 * [central directory]
404 * [zip64 end of central directory record]
405 * [zip64 end of central directory locator]
406 * [end of central directory record]
407 *
408 * The offset of zip64 end locator can be calculated from endpos as
409 * "endpos - ZIP64_LOCHDR".
410 * The "offset" of zip64 end record is stored in zip64 end locator.
411 */
412static jlong
413findEND64(jzfile *zip, void *end64buf, jlong endpos)
414{
415 char loc64[ZIP64_LOCHDR20];
416 jlong end64pos;
417 if (readFullyAt(zip->zfd, loc64, ZIP64_LOCHDR20, endpos - ZIP64_LOCHDR20) == -1) {
418 return -1; // end64 locator not found
419 }
420 end64pos = ZIP64_LOCOFF(loc64)(((jlong)((((((unsigned char *)(loc64))[8]) | ((((unsigned char
*)(loc64))[8 +1]) << 8)) | (((((unsigned char *)(loc64
))[8 +2]) | ((((unsigned char *)(loc64))[8 +2 +1]) << 8
)) << 16)) &0xffffffffUL)) | (((jlong)((((((unsigned
char *)(loc64))[8 +4]) | ((((unsigned char *)(loc64))[8 +4 +
1]) << 8)) | (((((unsigned char *)(loc64))[8 +4 +2]) | (
(((unsigned char *)(loc64))[8 +4 +2 +1]) << 8)) <<
16)) &0xffffffffUL)) << 32))
;
421 if (readFullyAt(zip->zfd, end64buf, ZIP64_ENDHDR56, end64pos) == -1) {
422 return -1; // end64 record not found
423 }
424 return end64pos;
425}
426
427/*
428 * Returns a hash code value for a C-style NUL-terminated string.
429 */
430static unsigned int
431hash(const char *s)
432{
433 int h = 0;
434 while (*s != '\0')
435 h = 31*h + *s++;
436 return h;
437}
438
439/*
440 * Returns a hash code value for a string of a specified length.
441 */
442static unsigned int
443hashN(const char *s, int length)
444{
445 int h = 0;
446 while (length-- > 0)
447 h = 31*h + *s++;
448 return h;
449}
450
451static unsigned int
452hash_append(unsigned int hash, char c)
453{
454 return ((int)hash)*31 + c;
455}
456
457/*
458 * Returns true if the specified entry's name begins with the string
459 * "META-INF/" irrespective of case.
460 */
461static int
462isMetaName(const char *name, int length)
463{
464 const char *s;
465 if (length < (int)sizeof("META-INF/") - 1)
466 return 0;
467 for (s = "META-INF/"; *s != '\0'; s++) {
468 char c = *name++;
469 // Avoid toupper; it's locale-dependent
470 if (c >= 'a' && c <= 'z') c += 'A' - 'a';
471 if (*s != c)
472 return 0;
473 }
474 return 1;
475}
476
477/*
478 * Increases the capacity of zip->metanames.
479 * Returns non-zero in case of allocation error.
480 */
481static int
482growMetaNames(jzfile *zip)
483{
484 jint i;
485 /* double the meta names array */
486 const jint new_metacount = zip->metacount << 1;
487 zip->metanames =
488 realloc(zip->metanames, new_metacount * sizeof(zip->metanames[0]));
489 if (zip->metanames == NULL((void*)0)) return -1;
490 for (i = zip->metacount; i < new_metacount; i++)
491 zip->metanames[i] = NULL((void*)0);
492 zip->metacurrent = zip->metacount;
493 zip->metacount = new_metacount;
494 return 0;
495}
496
497/*
498 * Adds name to zip->metanames.
499 * Returns non-zero in case of allocation error.
500 */
501static int
502addMetaName(jzfile *zip, const char *name, int length)
503{
504 jint i;
505 if (zip->metanames == NULL((void*)0)) {
506 zip->metacount = INITIAL_META_COUNT;
507 zip->metanames = calloc(zip->metacount, sizeof(zip->metanames[0]));
508 if (zip->metanames == NULL((void*)0)) return -1;
509 zip->metacurrent = 0;
510 }
511
512 i = zip->metacurrent;
513
514 /* current meta name array isn't full yet. */
515 if (i < zip->metacount) {
516 zip->metanames[i] = (char *) malloc(length+1);
517 if (zip->metanames[i] == NULL((void*)0)) return -1;
518 memcpy(zip->metanames[i], name, length);
519 zip->metanames[i][length] = '\0';
520 zip->metacurrent++;
521 return 0;
522 }
523
524 /* No free entries in zip->metanames? */
525 if (growMetaNames(zip) != 0) return -1;
526 return addMetaName(zip, name, length);
527}
528
529static void
530freeMetaNames(jzfile *zip)
531{
532 if (zip->metanames) {
533 jint i;
534 for (i = 0; i < zip->metacount; i++)
535 free(zip->metanames[i]);
536 free(zip->metanames);
537 zip->metanames = NULL((void*)0);
538 }
539}
540
541/* Free Zip data allocated by readCEN() */
542static void
543freeCEN(jzfile *zip)
544{
545 free(zip->entries); zip->entries = NULL((void*)0);
546 free(zip->table); zip->table = NULL((void*)0);
547 freeMetaNames(zip);
548}
549
550/*
551 * Counts the number of CEN headers in a central directory extending
552 * from BEG to END. Might return a bogus answer if the zip file is
553 * corrupt, but will not crash.
554 */
555static jint
556countCENHeaders(unsigned char *beg, unsigned char *end)
557{
558 jint count = 0;
559 ptrdiff_t i;
560 for (i = 0; i + CENHDR46 <= end - beg; i += CENSIZE(beg + i)(46 + ((((unsigned char *)(beg + i))[28]) | ((((unsigned char
*)(beg + i))[28 +1]) << 8)) + ((((unsigned char *)(beg
+ i))[30]) | ((((unsigned char *)(beg + i))[30 +1]) <<
8)) + ((((unsigned char *)(beg + i))[32]) | ((((unsigned char
*)(beg + i))[32 +1]) << 8)))
)
561 count++;
562 return count;
563}
564
565#define ZIP_FORMAT_ERROR(message)if (1) { zip->msg = message; goto Catch; } else ((void)0) \
566if (1) { zip->msg = message; goto Catch; } else ((void)0)
567
568/*
569 * Reads zip file central directory. Returns the file position of first
570 * CEN header, otherwise returns -1 if an error occurred. If zip->msg != NULL
571 * then the error was a zip format error and zip->msg has the error text.
572 * Always pass in -1 for knownTotal; it's used for a recursive call.
573 */
574static jlong
575readCEN(jzfile *zip, jint knownTotal)
576{
577 /* Following are unsigned 32-bit */
578 jlong endpos, end64pos, cenpos, cenlen, cenoff;
579 /* Following are unsigned 16-bit */
580 jint total, tablelen, i, j;
581 unsigned char *cenbuf = NULL((void*)0);
582 unsigned char *cenend;
583 unsigned char *cp;
584#ifdef USE_MMAP1
585 static jlong pagesize;
586 jlong offset;
587#endif
588 unsigned char endbuf[ENDHDR22];
589 jint endhdrlen = ENDHDR22;
590 jzcell *entries;
591 jint *table;
592
593 /* Clear previous zip error */
594 zip->msg = NULL((void*)0);
595 /* Get position of END header */
596 if ((endpos = findEND(zip, endbuf)) == -1)
597 return -1; /* no END header or system error */
598
599 if (endpos == 0) return 0; /* only END header present */
600
601 freeCEN(zip);
602 /* Get position and length of central directory */
603 cenlen = ENDSIZ(endbuf)((((((unsigned char *)(endbuf))[12]) | ((((unsigned char *)(endbuf
))[12 +1]) << 8)) | (((((unsigned char *)(endbuf))[12 +
2]) | ((((unsigned char *)(endbuf))[12 +2 +1]) << 8)) <<
16)) &0xffffffffUL)
;
604 cenoff = ENDOFF(endbuf)((((((unsigned char *)(endbuf))[16]) | ((((unsigned char *)(endbuf
))[16 +1]) << 8)) | (((((unsigned char *)(endbuf))[16 +
2]) | ((((unsigned char *)(endbuf))[16 +2 +1]) << 8)) <<
16)) &0xffffffffUL)
;
605 total = ENDTOT(endbuf)((((unsigned char *)(endbuf))[10]) | ((((unsigned char *)(endbuf
))[10 +1]) << 8))
;
606 if (cenlen == ZIP64_MAGICVAL0xffffffffLL || cenoff == ZIP64_MAGICVAL0xffffffffLL ||
607 total == ZIP64_MAGICCOUNT0xffff) {
608 unsigned char end64buf[ZIP64_ENDHDR56];
609 if ((end64pos = findEND64(zip, end64buf, endpos)) != -1) {
610 cenlen = ZIP64_ENDSIZ(end64buf)(((jlong)((((((unsigned char *)(end64buf))[40]) | ((((unsigned
char *)(end64buf))[40 +1]) << 8)) | (((((unsigned char
*)(end64buf))[40 +2]) | ((((unsigned char *)(end64buf))[40 +
2 +1]) << 8)) << 16)) &0xffffffffUL)) | (((jlong
)((((((unsigned char *)(end64buf))[40 +4]) | ((((unsigned char
*)(end64buf))[40 +4 +1]) << 8)) | (((((unsigned char *
)(end64buf))[40 +4 +2]) | ((((unsigned char *)(end64buf))[40 +
4 +2 +1]) << 8)) << 16)) &0xffffffffUL)) <<
32))
;
611 cenoff = ZIP64_ENDOFF(end64buf)(((jlong)((((((unsigned char *)(end64buf))[48]) | ((((unsigned
char *)(end64buf))[48 +1]) << 8)) | (((((unsigned char
*)(end64buf))[48 +2]) | ((((unsigned char *)(end64buf))[48 +
2 +1]) << 8)) << 16)) &0xffffffffUL)) | (((jlong
)((((((unsigned char *)(end64buf))[48 +4]) | ((((unsigned char
*)(end64buf))[48 +4 +1]) << 8)) | (((((unsigned char *
)(end64buf))[48 +4 +2]) | ((((unsigned char *)(end64buf))[48 +
4 +2 +1]) << 8)) << 16)) &0xffffffffUL)) <<
32))
;
612 total = (jint)ZIP64_ENDTOT(end64buf)(((jlong)((((((unsigned char *)(end64buf))[32]) | ((((unsigned
char *)(end64buf))[32 +1]) << 8)) | (((((unsigned char
*)(end64buf))[32 +2]) | ((((unsigned char *)(end64buf))[32 +
2 +1]) << 8)) << 16)) &0xffffffffUL)) | (((jlong
)((((((unsigned char *)(end64buf))[32 +4]) | ((((unsigned char
*)(end64buf))[32 +4 +1]) << 8)) | (((((unsigned char *
)(end64buf))[32 +4 +2]) | ((((unsigned char *)(end64buf))[32 +
4 +2 +1]) << 8)) << 16)) &0xffffffffUL)) <<
32))
;
613 endpos = end64pos;
614 endhdrlen = ZIP64_ENDHDR56;
615 }
616 }
617
618 if (cenlen > endpos) {
619 ZIP_FORMAT_ERROR("invalid END header (bad central directory size)")if (1) { zip->msg = "invalid END header (bad central directory size)"
; goto Catch; } else ((void)0)
;
620 }
621 cenpos = endpos - cenlen;
622
623 /* Get position of first local file (LOC) header, taking into
624 * account that there may be a stub prefixed to the zip file. */
625 zip->locpos = cenpos - cenoff;
626 if (zip->locpos < 0) {
627 ZIP_FORMAT_ERROR("invalid END header (bad central directory offset)")if (1) { zip->msg = "invalid END header (bad central directory offset)"
; goto Catch; } else ((void)0)
;
628 }
629#ifdef USE_MMAP1
630 if (zip->usemmap) {
631 /* On Solaris & Linux prior to JDK 6, we used to mmap the whole jar file to
632 * read the jar file contents. However, this greatly increased the perceived
633 * footprint numbers because the mmap'ed pages were adding into the totals shown
634 * by 'ps' and 'top'. We switched to mmaping only the central directory of jar
635 * file while calling 'read' to read the rest of jar file. Here are a list of
636 * reasons apart from above of why we are doing so:
637 * 1. Greatly reduces mmap overhead after startup complete;
638 * 2. Avoids dual path code maintainance;
639 * 3. Greatly reduces risk of address space (not virtual memory) exhaustion.
640 */
641 if (pagesize == 0) {
642 pagesize = (jlong)sysconf(_SC_PAGESIZE_SC_PAGESIZE);
643 if (pagesize == 0) goto Catch;
644 }
645 if (cenpos > pagesize) {
646 offset = cenpos & ~(pagesize - 1);
647 } else {
648 offset = 0;
649 }
650 /* When we are not calling recursively, knownTotal is -1. */
651 if (knownTotal == -1) {
652 void* mappedAddr;
653 /* Mmap the CEN and END part only. We have to figure
654 out the page size in order to make offset to be multiples of
655 page size.
656 */
657 zip->mlen = cenpos - offset + cenlen + endhdrlen;
658 zip->offset = offset;
659 mappedAddr = mmap64(0, zip->mlen, PROT_READ0x1, MAP_SHARED0x01, zip->zfd, (off64_t) offset);
660 zip->maddr = (mappedAddr == (void*) MAP_FAILED((void *) -1)) ? NULL((void*)0) :
661 (unsigned char*)mappedAddr;
662
663 if (zip->maddr == NULL((void*)0)) {
664 jio_fprintf(stderrstderr, "mmap failed for CEN and END part of zip file\n");
665 goto Catch;
666 }
667 }
668 cenbuf = zip->maddr + cenpos - offset;
669 } else
670#endif
671 {
672 if ((cenbuf = malloc((size_t) cenlen)) == NULL((void*)0) ||
673 (readFullyAt(zip->zfd, cenbuf, cenlen, cenpos) == -1))
674 goto Catch;
675 }
676
677 cenend = cenbuf + cenlen;
678
679 /* Initialize zip file data structures based on the total number
680 * of central directory entries as stored in ENDTOT. Since this
681 * is a 2-byte field, but we (and other zip implementations)
682 * support approx. 2**31 entries, we do not trust ENDTOT, but
683 * treat it only as a strong hint. When we call ourselves
684 * recursively, knownTotal will have the "true" value.
685 *
686 * Keep this path alive even with the Zip64 END support added, just
687 * for zip files that have more than 0xffff entries but don't have
688 * the Zip64 enabled.
689 */
690 total = (knownTotal != -1) ? knownTotal : total;
691 entries = zip->entries = calloc(total, sizeof(entries[0]));
692 tablelen = zip->tablelen = ((total/2) | 1); // Odd -> fewer collisions
693 table = zip->table = malloc(tablelen * sizeof(table[0]));
694 /* According to ISO C it is perfectly legal for malloc to return zero
695 * if called with a zero argument. We check this for 'entries' but not
696 * for 'table' because 'tablelen' can't be zero (see computation above). */
697 if ((entries == NULL((void*)0) && total != 0) || table == NULL((void*)0)) goto Catch;
698 for (j = 0; j < tablelen; j++)
699 table[j] = ZIP_ENDCHAIN((jint)-1);
700
701 /* Iterate through the entries in the central directory */
702 for (i = 0, cp = cenbuf; cp <= cenend - CENHDR46; i++, cp += CENSIZE(cp)(46 + ((((unsigned char *)(cp))[28]) | ((((unsigned char *)(cp
))[28 +1]) << 8)) + ((((unsigned char *)(cp))[30]) | ((
((unsigned char *)(cp))[30 +1]) << 8)) + ((((unsigned char
*)(cp))[32]) | ((((unsigned char *)(cp))[32 +1]) << 8)
))
) {
703 /* Following are unsigned 16-bit */
704 jint method, nlen;
705 unsigned int hsh;
706
707 if (i >= total) {
708 /* This will only happen if the zip file has an incorrect
709 * ENDTOT field, which usually means it contains more than
710 * 65535 entries. */
711 cenpos = readCEN(zip, countCENHeaders(cenbuf, cenend));
712 goto Finally;
713 }
714
715 method = CENHOW(cp)((((unsigned char *)(cp))[10]) | ((((unsigned char *)(cp))[10
+1]) << 8))
;
716 nlen = CENNAM(cp)((((unsigned char *)(cp))[28]) | ((((unsigned char *)(cp))[28
+1]) << 8))
;
717
718 if (!CENSIG_AT(cp)(((cp)[0] == 'P') & ((cp)[1] == 'K') & ((cp)[2] == 1)
& ((cp)[3] == 2))
) {
719 ZIP_FORMAT_ERROR("invalid CEN header (bad signature)")if (1) { zip->msg = "invalid CEN header (bad signature)"; goto
Catch; } else ((void)0)
;
720 }
721 if (CENFLG(cp)((((unsigned char *)(cp))[8]) | ((((unsigned char *)(cp))[8 +
1]) << 8))
& 1) {
722 ZIP_FORMAT_ERROR("invalid CEN header (encrypted entry)")if (1) { zip->msg = "invalid CEN header (encrypted entry)"
; goto Catch; } else ((void)0)
;
723 }
724 if (method != STORED0 && method != DEFLATED8) {
725 ZIP_FORMAT_ERROR("invalid CEN header (bad compression method)")if (1) { zip->msg = "invalid CEN header (bad compression method)"
; goto Catch; } else ((void)0)
;
726 }
727 if (cp + CENHDR46 + nlen > cenend) {
728 ZIP_FORMAT_ERROR("invalid CEN header (bad header size)")if (1) { zip->msg = "invalid CEN header (bad header size)"
; goto Catch; } else ((void)0)
;
729 }
730 /* if the entry is metadata add it to our metadata names */
731 if (isMetaName((char *)cp+CENHDR46, nlen))
732 if (addMetaName(zip, (char *)cp+CENHDR46, nlen) != 0)
733 goto Catch;
734
735 /* Record the CEN offset and the name hash in our hash cell. */
736 entries[i].cenpos = cenpos + (cp - cenbuf);
737 entries[i].hash = hashN((char *)cp+CENHDR46, nlen);
738
739 /* Add the entry to the hash table */
740 hsh = entries[i].hash % tablelen;
741 entries[i].next = table[hsh];
742 table[hsh] = i;
743 }
744 if (cp != cenend) {
745 ZIP_FORMAT_ERROR("invalid CEN header (bad header size)")if (1) { zip->msg = "invalid CEN header (bad header size)"
; goto Catch; } else ((void)0)
;
746 }
747 zip->total = i;
748 goto Finally;
749
750 Catch:
751 freeCEN(zip);
752 cenpos = -1;
753
754 Finally:
755#ifdef USE_MMAP1
756 if (!zip->usemmap)
757#endif
758 free(cenbuf);
759
760 return cenpos;
761}
762
763/*
764 * Opens a zip file with the specified mode. Returns the jzfile object
765 * or NULL if an error occurred. If a zip error occurred then *pmsg will
766 * be set to the error message text if pmsg != 0. Otherwise, *pmsg will be
767 * set to NULL. Caller is responsible to free the error message.
768 */
769jzfile *
770ZIP_Open_Generic(const char *name, char **pmsg, int mode, jlong lastModified)
771{
772 jzfile *zip = NULL((void*)0);
773
774 /* Clear zip error message */
775 if (pmsg != NULL((void*)0)) {
776 *pmsg = NULL((void*)0);
777 }
778
779 zip = ZIP_Get_From_Cache(name, pmsg, lastModified);
780
781 if (zip == NULL((void*)0) && pmsg != NULL((void*)0) && *pmsg == NULL((void*)0)) {
782 ZFILEint zfd = ZFILE_Open(name, mode);
783 zip = ZIP_Put_In_Cache(name, zfd, pmsg, lastModified);
784 }
785 return zip;
786}
787
788/*
789 * Returns the jzfile corresponding to the given file name from the cache of
790 * zip files, or NULL if the file is not in the cache. If the name is longer
791 * than PATH_MAX or a zip error occurred then *pmsg will be set to the error
792 * message text if pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller
793 * is responsible to free the error message.
794 */
795jzfile *
796ZIP_Get_From_Cache(const char *name, char **pmsg, jlong lastModified)
797{
798 char buf[PATH_MAX4096];
799 jzfile *zip;
800
801 if (InitializeZip()) {
802 return NULL((void*)0);
803 }
804
805 /* Clear zip error message */
806 if (pmsg != 0) {
807 *pmsg = NULL((void*)0);
808 }
809
810 if (strlen(name) >= PATH_MAX4096) {
811 if (pmsg) {
812 *pmsg = strdup("zip file name too long");
813 }
814 return NULL((void*)0);
815 }
816 strcpy(buf, name);
817 JVM_NativePath(buf);
818 name = buf;
819
820 MLOCK(zfiles_lock)JVM_RawMonitorEnter(zfiles_lock);
821 for (zip = zfiles; zip != NULL((void*)0); zip = zip->next) {
822 if (strcmp(name, zip->name) == 0
823 && (zip->lastModified == lastModified || zip->lastModified == 0)
824 && zip->refs < MAXREFS0xFFFF) {
825 zip->refs++;
826 break;
827 }
828 }
829 MUNLOCK(zfiles_lock)JVM_RawMonitorExit(zfiles_lock);
830 return zip;
831}
832
833/*
834 * Reads data from the given file descriptor to create a jzfile, puts the
835 * jzfile in a cache, and returns that jzfile. Returns NULL in case of error.
836 * If a zip error occurs, then *pmsg will be set to the error message text if
837 * pmsg != 0. Otherwise, *pmsg will be set to NULL. Caller is responsible to
838 * free the error message.
839 */
840
841jzfile *
842ZIP_Put_In_Cache(const char *name, ZFILEint zfd, char **pmsg, jlong lastModified)
843{
844 return ZIP_Put_In_Cache0(name, zfd, pmsg, lastModified, JNI_TRUE1);
845}
846
847jzfile *
848ZIP_Put_In_Cache0(const char *name, ZFILEint zfd, char **pmsg, jlong lastModified,
849 jboolean usemmap)
850{
851 char errbuf[256];
852 jlong len;
853 jzfile *zip;
854
855 if ((zip = allocZip(name)) == NULL((void*)0)) {
856 return NULL((void*)0);
857 }
858
859#ifdef USE_MMAP1
860 zip->usemmap = usemmap;
861#endif
862 zip->refs = 1;
863 zip->lastModified = lastModified;
864
865 if (zfd == -1) {
866 if (pmsg && getLastErrorString(errbuf, sizeof(errbuf)) > 0)
867 *pmsg = strdup(errbuf);
868 freeZip(zip);
869 return NULL((void*)0);
870 }
871
872 // Assumption, zfd refers to start of file. Trivially, reuse errbuf.
873 if (readFully(zfd, errbuf, 4) != -1) { // errors will be handled later
874 zip->locsig = LOCSIG_AT(errbuf)(((errbuf)[0] == 'P') & ((errbuf)[1] == 'K') & ((errbuf
)[2] == 3) & ((errbuf)[3] == 4))
? JNI_TRUE1 : JNI_FALSE0;
875 }
876
877 len = zip->len = IO_Lseeklseek64(zfd, 0, SEEK_END2);
878 if (len <= 0) {
879 if (len == 0) { /* zip file is empty */
880 if (pmsg) {
881 *pmsg = strdup("zip file is empty");
882 }
883 } else { /* error */
884 if (pmsg && getLastErrorString(errbuf, sizeof(errbuf)) > 0)
885 *pmsg = strdup(errbuf);
886 }
887 ZFILE_Close(zfd);
888 freeZip(zip);
889 return NULL((void*)0);
890 }
891
892 zip->zfd = zfd;
893 if (readCEN(zip, -1) < 0) {
894 /* An error occurred while trying to read the zip file */
895 if (pmsg != 0) {
896 /* Set the zip error message */
897 if (zip->msg != NULL((void*)0))
898 *pmsg = strdup(zip->msg);
899 }
900 freeZip(zip);
901 return NULL((void*)0);
902 }
903 MLOCK(zfiles_lock)JVM_RawMonitorEnter(zfiles_lock);
904 zip->next = zfiles;
905 zfiles = zip;
906 MUNLOCK(zfiles_lock)JVM_RawMonitorExit(zfiles_lock);
907
908 return zip;
909}
910
911/*
912 * Opens a zip file for reading. Returns the jzfile object or NULL
913 * if an error occurred. If a zip error occurred then *msg will be
914 * set to the error message text if msg != 0. Otherwise, *msg will be
915 * set to NULL. Caller doesn't need to free the error message.
916 */
917JNIEXPORT__attribute__((visibility("default"))) jzfile *
918ZIP_Open(const char *name, char **pmsg)
919{
920 jzfile *file = ZIP_Open_Generic(name, pmsg, O_RDONLY00, 0);
921 if (file == NULL((void*)0) && pmsg != NULL((void*)0) && *pmsg != NULL((void*)0)) {
922 free(*pmsg);
923 *pmsg = "Zip file open error";
924 }
925 return file;
926}
927
928/*
929 * Closes the specified zip file object.
930 */
931JNIEXPORT__attribute__((visibility("default"))) void
932ZIP_Close(jzfile *zip)
933{
934 MLOCK(zfiles_lock)JVM_RawMonitorEnter(zfiles_lock);
935 if (--zip->refs > 0) {
936 /* Still more references so just return */
937 MUNLOCK(zfiles_lock)JVM_RawMonitorExit(zfiles_lock);
938 return;
939 }
940 /* No other references so close the file and remove from list */
941 if (zfiles == zip) {
942 zfiles = zfiles->next;
943 } else {
944 jzfile *zp;
945 for (zp = zfiles; zp->next != 0; zp = zp->next) {
946 if (zp->next == zip) {
947 zp->next = zip->next;
948 break;
949 }
950 }
951 }
952 MUNLOCK(zfiles_lock)JVM_RawMonitorExit(zfiles_lock);
953 freeZip(zip);
954 return;
955}
956
957/* Empirically, most CEN headers are smaller than this. */
958#define AMPLE_CEN_HEADER_SIZE160 160
959
960/* A good buffer size when we want to read CEN headers sequentially. */
961#define CENCACHE_PAGESIZE8192 8192
962
963static char *
964readCENHeader(jzfile *zip, jlong cenpos, jint bufsize)
965{
966 jint censize;
967 ZFILEint zfd = zip->zfd;
968 char *cen;
969 if (bufsize > zip->len - cenpos)
970 bufsize = (jint)(zip->len - cenpos);
971 if ((cen = malloc(bufsize)) == NULL((void*)0)) goto Catch;
972 if (readFullyAt(zfd, cen, bufsize, cenpos) == -1) goto Catch;
973 censize = CENSIZE(cen)(46 + ((((unsigned char *)(cen))[28]) | ((((unsigned char *)(
cen))[28 +1]) << 8)) + ((((unsigned char *)(cen))[30]) |
((((unsigned char *)(cen))[30 +1]) << 8)) + ((((unsigned
char *)(cen))[32]) | ((((unsigned char *)(cen))[32 +1]) <<
8)))
;
974 if (censize <= bufsize) return cen;
975 if ((cen = realloc(cen, censize)) == NULL((void*)0)) goto Catch;
976 if (readFully(zfd, cen+bufsize, censize-bufsize) == -1) goto Catch;
977 return cen;
978
979 Catch:
980 free(cen);
981 return NULL((void*)0);
982}
983
984static char *
985sequentialAccessReadCENHeader(jzfile *zip, jlong cenpos)
986{
987 cencache *cache = &zip->cencache;
988 char *cen;
989 if (cache->data != NULL((void*)0)
990 && (cenpos >= cache->pos)
991 && (cenpos + CENHDR46 <= cache->pos + CENCACHE_PAGESIZE8192))
992 {
993 cen = cache->data + cenpos - cache->pos;
994 if (cenpos + CENSIZE(cen)(46 + ((((unsigned char *)(cen))[28]) | ((((unsigned char *)(
cen))[28 +1]) << 8)) + ((((unsigned char *)(cen))[30]) |
((((unsigned char *)(cen))[30 +1]) << 8)) + ((((unsigned
char *)(cen))[32]) | ((((unsigned char *)(cen))[32 +1]) <<
8)))
<= cache->pos + CENCACHE_PAGESIZE8192)
995 /* A cache hit */
996 return cen;
997 }
998
999 if ((cen = readCENHeader(zip, cenpos, CENCACHE_PAGESIZE8192)) == NULL((void*)0))
1000 return NULL((void*)0);
1001 free(cache->data);
1002 cache->data = cen;
1003 cache->pos = cenpos;
1004 return cen;
1005}
1006
1007typedef enum { ACCESS_RANDOM, ACCESS_SEQUENTIAL } AccessHint;
1008
1009/*
1010 * Return a new initialized jzentry corresponding to a given hash cell.
1011 * In case of error, returns NULL.
1012 * We already sanity-checked all the CEN headers for ZIP format errors
1013 * in readCEN(), so we don't check them again here.
1014 * The ZIP lock should be held here.
1015 */
1016static jzentry *
1017newEntry(jzfile *zip, jzcell *zc, AccessHint accessHint)
1018{
1019 jlong locoff;
1020 jint nlen, elen, clen;
1021 jzentry *ze;
1022 char *cen;
1023
1024 if ((ze = (jzentry *) malloc(sizeof(jzentry))) == NULL((void*)0)) return NULL((void*)0);
1025 ze->name = NULL((void*)0);
1026 ze->extra = NULL((void*)0);
1027 ze->comment = NULL((void*)0);
1028
1029#ifdef USE_MMAP1
1030 if (zip->usemmap) {
1031 cen = (char*) zip->maddr + zc->cenpos - zip->offset;
1032 } else
1033#endif
1034 {
1035 if (accessHint == ACCESS_RANDOM)
1036 cen = readCENHeader(zip, zc->cenpos, AMPLE_CEN_HEADER_SIZE160);
1037 else
1038 cen = sequentialAccessReadCENHeader(zip, zc->cenpos);
1039 if (cen == NULL((void*)0)) goto Catch;
1040 }
1041
1042 nlen = CENNAM(cen)((((unsigned char *)(cen))[28]) | ((((unsigned char *)(cen))[
28 +1]) << 8))
;
1043 elen = CENEXT(cen)((((unsigned char *)(cen))[30]) | ((((unsigned char *)(cen))[
30 +1]) << 8))
;
1044 clen = CENCOM(cen)((((unsigned char *)(cen))[32]) | ((((unsigned char *)(cen))[
32 +1]) << 8))
;
1045 ze->time = CENTIM(cen)((((((unsigned char *)(cen))[12]) | ((((unsigned char *)(cen)
)[12 +1]) << 8)) | (((((unsigned char *)(cen))[12 +2]) |
((((unsigned char *)(cen))[12 +2 +1]) << 8)) << 16
)) &0xffffffffUL)
;
1046 ze->size = CENLEN(cen)((((((unsigned char *)(cen))[24]) | ((((unsigned char *)(cen)
)[24 +1]) << 8)) | (((((unsigned char *)(cen))[24 +2]) |
((((unsigned char *)(cen))[24 +2 +1]) << 8)) << 16
)) &0xffffffffUL)
;
1047 ze->csize = (CENHOW(cen)((((unsigned char *)(cen))[10]) | ((((unsigned char *)(cen))[
10 +1]) << 8))
== STORED0) ? 0 : CENSIZ(cen)((((((unsigned char *)(cen))[20]) | ((((unsigned char *)(cen)
)[20 +1]) << 8)) | (((((unsigned char *)(cen))[20 +2]) |
((((unsigned char *)(cen))[20 +2 +1]) << 8)) << 16
)) &0xffffffffUL)
;
1048 ze->crc = CENCRC(cen)((((((unsigned char *)(cen))[16]) | ((((unsigned char *)(cen)
)[16 +1]) << 8)) | (((((unsigned char *)(cen))[16 +2]) |
((((unsigned char *)(cen))[16 +2 +1]) << 8)) << 16
)) &0xffffffffUL)
;
1049 locoff = CENOFF(cen)((((((unsigned char *)(cen))[42]) | ((((unsigned char *)(cen)
)[42 +1]) << 8)) | (((((unsigned char *)(cen))[42 +2]) |
((((unsigned char *)(cen))[42 +2 +1]) << 8)) << 16
)) &0xffffffffUL)
;
1050 ze->pos = -(zip->locpos + locoff);
1051 ze->flag = CENFLG(cen)((((unsigned char *)(cen))[8]) | ((((unsigned char *)(cen))[8
+1]) << 8))
;
1052
1053 if ((ze->name = malloc(nlen + 1)) == NULL((void*)0)) goto Catch;
1054 memcpy(ze->name, cen + CENHDR46, nlen);
1055 ze->name[nlen] = '\0';
1056 ze->nlen = nlen;
1057 if (elen > 0) {
1058 char *extra = cen + CENHDR46 + nlen;
1059
1060 /* This entry has "extra" data */
1061 if ((ze->extra = malloc(elen + 2)) == NULL((void*)0)) goto Catch;
1062 ze->extra[0] = (unsigned char) elen;
1063 ze->extra[1] = (unsigned char) (elen >> 8);
1064 memcpy(ze->extra+2, extra, elen);
1065 if (ze->csize == ZIP64_MAGICVAL0xffffffffLL || ze->size == ZIP64_MAGICVAL0xffffffffLL ||
1066 locoff == ZIP64_MAGICVAL0xffffffffLL) {
1067 jint off = 0;
1068 while ((off + 4) < elen) { // spec: HeaderID+DataSize+Data
1069 jint sz = SH(extra, off + 2)((((unsigned char *)(extra))[off + 2]) | ((((unsigned char *)
(extra))[off + 2 +1]) << 8))
;
1070 if (SH(extra, off)((((unsigned char *)(extra))[off]) | ((((unsigned char *)(extra
))[off+1]) << 8))
== ZIP64_EXTID1) {
1071 off += 4;
1072 if (ze->size == ZIP64_MAGICVAL0xffffffffLL) {
1073 // if invalid zip64 extra fields, just skip
1074 if (sz < 8 || (off + 8) > elen)
1075 break;
1076 ze->size = LL(extra, off)(((jlong)((((((unsigned char *)(extra))[off]) | ((((unsigned char
*)(extra))[off+1]) << 8)) | (((((unsigned char *)(extra
))[off+2]) | ((((unsigned char *)(extra))[off+2 +1]) <<
8)) << 16)) &0xffffffffUL)) | (((jlong)((((((unsigned
char *)(extra))[off+4]) | ((((unsigned char *)(extra))[off+4
+1]) << 8)) | (((((unsigned char *)(extra))[off+4 +2])
| ((((unsigned char *)(extra))[off+4 +2 +1]) << 8)) <<
16)) &0xffffffffUL)) << 32))
;
1077 sz -= 8;
1078 off += 8;
1079 }
1080 if (ze->csize == ZIP64_MAGICVAL0xffffffffLL) {
1081 if (sz < 8 || (off + 8) > elen)
1082 break;
1083 ze->csize = LL(extra, off)(((jlong)((((((unsigned char *)(extra))[off]) | ((((unsigned char
*)(extra))[off+1]) << 8)) | (((((unsigned char *)(extra
))[off+2]) | ((((unsigned char *)(extra))[off+2 +1]) <<
8)) << 16)) &0xffffffffUL)) | (((jlong)((((((unsigned
char *)(extra))[off+4]) | ((((unsigned char *)(extra))[off+4
+1]) << 8)) | (((((unsigned char *)(extra))[off+4 +2])
| ((((unsigned char *)(extra))[off+4 +2 +1]) << 8)) <<
16)) &0xffffffffUL)) << 32))
;
1084 sz -= 8;
1085 off += 8;
1086 }
1087 if (locoff == ZIP64_MAGICVAL0xffffffffLL) {
1088 if (sz < 8 || (off + 8) > elen)
1089 break;
1090 ze->pos = -(zip->locpos + LL(extra, off)(((jlong)((((((unsigned char *)(extra))[off]) | ((((unsigned char
*)(extra))[off+1]) << 8)) | (((((unsigned char *)(extra
))[off+2]) | ((((unsigned char *)(extra))[off+2 +1]) <<
8)) << 16)) &0xffffffffUL)) | (((jlong)((((((unsigned
char *)(extra))[off+4]) | ((((unsigned char *)(extra))[off+4
+1]) << 8)) | (((((unsigned char *)(extra))[off+4 +2])
| ((((unsigned char *)(extra))[off+4 +2 +1]) << 8)) <<
16)) &0xffffffffUL)) << 32))
);
1091 sz -= 8;
1092 off += 8;
Value stored to 'off' is never read
1093 }
1094 break;
1095 }
1096 off += (sz + 4);
1097 }
1098 }
1099 }
1100
1101 if (clen > 0) {
1102 /* This entry has a comment */
1103 if ((ze->comment = malloc(clen + 1)) == NULL((void*)0)) goto Catch;
1104 memcpy(ze->comment, cen + CENHDR46 + nlen + elen, clen);
1105 ze->comment[clen] = '\0';
1106 }
1107 goto Finally;
1108
1109 Catch:
1110 free(ze->name);
1111 free(ze->extra);
1112 free(ze->comment);
1113 free(ze);
1114 ze = NULL((void*)0);
1115
1116 Finally:
1117#ifdef USE_MMAP1
1118 if (!zip->usemmap)
1119#endif
1120 if (cen != NULL((void*)0) && accessHint == ACCESS_RANDOM) free(cen);
1121 return ze;
1122}
1123
1124/*
1125 * Free the given jzentry.
1126 * In fact we maintain a one-entry cache of the most recently used
1127 * jzentry for each zip. This optimizes a common access pattern.
1128 */
1129
1130void
1131ZIP_FreeEntry(jzfile *jz, jzentry *ze)
1132{
1133 jzentry *last;
1134 ZIP_Lock(jz);
1135 last = jz->cache;
1136 jz->cache = ze;
1137 ZIP_Unlock(jz);
1138 if (last != NULL((void*)0)) {
1139 /* Free the previously cached jzentry */
1140 free(last->name);
1141 if (last->extra) free(last->extra);
1142 if (last->comment) free(last->comment);
1143 free(last);
1144 }
1145}
1146
1147/*
1148 * Returns the zip entry corresponding to the specified name, or
1149 * NULL if not found.
1150 */
1151jzentry *
1152ZIP_GetEntry(jzfile *zip, char *name, jint ulen)
1153{
1154 if (ulen == 0) {
1155 return ZIP_GetEntry2(zip, name, (jint)strlen(name), JNI_FALSE0);
1156 }
1157 return ZIP_GetEntry2(zip, name, ulen, JNI_TRUE1);
1158}
1159
1160jboolean equals(char* name1, int len1, char* name2, int len2) {
1161 if (len1 != len2) {
1162 return JNI_FALSE0;
1163 }
1164 while (len1-- > 0) {
1165 if (*name1++ != *name2++) {
1166 return JNI_FALSE0;
1167 }
1168 }
1169 return JNI_TRUE1;
1170}
1171
1172/*
1173 * Returns the zip entry corresponding to the specified name, or
1174 * NULL if not found.
1175 * This method supports embedded null character in "name", use ulen
1176 * for the length of "name".
1177 */
1178jzentry *
1179ZIP_GetEntry2(jzfile *zip, char *name, jint ulen, jboolean addSlash)
1180{
1181 unsigned int hsh = hashN(name, ulen);
1182 jint idx;
1183 jzentry *ze = 0;
1184
1185 ZIP_Lock(zip);
1186 if (zip->total == 0) {
1187 goto Finally;
1188 }
1189
1190 idx = zip->table[hsh % zip->tablelen];
1191
1192 /*
1193 * This while loop is an optimization where a double lookup
1194 * for name and name+/ is being performed. The name char
1195 * array has enough room at the end to try again with a
1196 * slash appended if the first table lookup does not succeed.
1197 */
1198 while(1) {
1199
1200 /* Check the cached entry first */
1201 ze = zip->cache;
1202 if (ze && equals(ze->name, ze->nlen, name, ulen)) {
1203 /* Cache hit! Remove and return the cached entry. */
1204 zip->cache = 0;
1205 ZIP_Unlock(zip);
1206 return ze;
1207 }
1208 ze = 0;
1209
1210 /*
1211 * Search down the target hash chain for a cell whose
1212 * 32 bit hash matches the hashed name.
1213 */
1214 while (idx != ZIP_ENDCHAIN((jint)-1)) {
1215 jzcell *zc = &zip->entries[idx];
1216
1217 if (zc->hash == hsh) {
1218 /*
1219 * OK, we've found a ZIP entry whose 32 bit hashcode
1220 * matches the name we're looking for. Try to read
1221 * its entry information from the CEN. If the CEN
1222 * name matches the name we're looking for, we're
1223 * done.
1224 * If the names don't match (which should be very rare)
1225 * we keep searching.
1226 */
1227 ze = newEntry(zip, zc, ACCESS_RANDOM);
1228 if (ze && equals(ze->name, ze->nlen, name, ulen)) {
1229 break;
1230 }
1231 if (ze != 0) {
1232 /* We need to release the lock across the free call */
1233 ZIP_Unlock(zip);
1234 ZIP_FreeEntry(zip, ze);
1235 ZIP_Lock(zip);
1236 }
1237 ze = 0;
1238 }
1239 idx = zc->next;
1240 }
1241
1242 /* Entry found, return it */
1243 if (ze != 0) {
1244 break;
1245 }
1246
1247 /* If no need to try appending slash, we are done */
1248 if (!addSlash) {
1249 break;
1250 }
1251
1252 /* Slash is already there? */
1253 if (ulen > 0 && name[ulen - 1] == '/') {
1254 break;
1255 }
1256
1257 /* Add slash and try once more */
1258 name[ulen++] = '/';
1259 name[ulen] = '\0';
1260 hsh = hash_append(hsh, '/');
1261 idx = zip->table[hsh % zip->tablelen];
1262 addSlash = JNI_FALSE0;
1263 }
1264
1265Finally:
1266 ZIP_Unlock(zip);
1267 return ze;
1268}
1269
1270/*
1271 * Returns the n'th (starting at zero) zip file entry, or NULL if the
1272 * specified index was out of range.
1273 */
1274JNIEXPORT__attribute__((visibility("default"))) jzentry *
1275ZIP_GetNextEntry(jzfile *zip, jint n)
1276{
1277 jzentry *result;
1278 if (n < 0 || n >= zip->total) {
1279 return 0;
1280 }
1281 ZIP_Lock(zip);
1282 result = newEntry(zip, &zip->entries[n], ACCESS_SEQUENTIAL);
1283 ZIP_Unlock(zip);
1284 return result;
1285}
1286
1287/*
1288 * Locks the specified zip file for reading.
1289 */
1290void
1291ZIP_Lock(jzfile *zip)
1292{
1293 MLOCK(zip->lock)JVM_RawMonitorEnter(zip->lock);
1294}
1295
1296/*
1297 * Unlocks the specified zip file.
1298 */
1299void
1300ZIP_Unlock(jzfile *zip)
1301{
1302 MUNLOCK(zip->lock)JVM_RawMonitorExit(zip->lock);
1303}
1304
1305/*
1306 * Returns the offset of the entry data within the zip file.
1307 * Returns -1 if an error occurred, in which case zip->msg will
1308 * contain the error text.
1309 */
1310jlong
1311ZIP_GetEntryDataOffset(jzfile *zip, jzentry *entry)
1312{
1313 /* The Zip file spec explicitly allows the LOC extra data size to
1314 * be different from the CEN extra data size, although the JDK
1315 * never creates such zip files. Since we cannot trust the CEN
1316 * extra data size, we need to read the LOC to determine the entry
1317 * data offset. We do this lazily to avoid touching the virtual
1318 * memory page containing the LOC when initializing jzentry
1319 * objects. (This speeds up javac by a factor of 10 when the JDK
1320 * is installed on a very slow filesystem.)
1321 */
1322 if (entry->pos <= 0) {
1323 unsigned char loc[LOCHDR30];
1324 if (readFullyAt(zip->zfd, loc, LOCHDR30, -(entry->pos)) == -1) {
1325 zip->msg = "error reading zip file";
1326 return -1;
1327 }
1328 if (!LOCSIG_AT(loc)(((loc)[0] == 'P') & ((loc)[1] == 'K') & ((loc)[2] ==
3) & ((loc)[3] == 4))
) {
1329 zip->msg = "invalid LOC header (bad signature)";
1330 return -1;
1331 }
1332 entry->pos = (- entry->pos) + LOCHDR30 + LOCNAM(loc)((((unsigned char *)(loc))[26]) | ((((unsigned char *)(loc))[
26 +1]) << 8))
+ LOCEXT(loc)((((unsigned char *)(loc))[28]) | ((((unsigned char *)(loc))[
28 +1]) << 8))
;
1333 }
1334 return entry->pos;
1335}
1336
1337/*
1338 * Reads bytes from the specified zip entry. Assumes that the zip
1339 * file had been previously locked with ZIP_Lock(). Returns the
1340 * number of bytes read, or -1 if an error occurred. If zip->msg != 0
1341 * then a zip error occurred and zip->msg contains the error text.
1342 *
1343 * The current implementation does not support reading an entry that
1344 * has the size bigger than 2**32 bytes in ONE invocation.
1345 */
1346jint
1347ZIP_Read(jzfile *zip, jzentry *entry, jlong pos, void *buf, jint len)
1348{
1349 jlong entry_size;
1350 jlong start;
1351
1352 if (zip == 0) {
1353 return -1;
1354 }
1355
1356 /* Clear previous zip error */
1357 zip->msg = NULL((void*)0);
1358
1359 if (entry == 0) {
1360 zip->msg = "ZIP_Read: jzentry is NULL";
1361 return -1;
1362 }
1363
1364 entry_size = (entry->csize != 0) ? entry->csize : entry->size;
1365
1366 /* Check specified position */
1367 if (pos < 0 || pos > entry_size - 1) {
1368 zip->msg = "ZIP_Read: specified offset out of range";
1369 return -1;
1370 }
1371
1372 /* Check specified length */
1373 if (len <= 0)
1374 return 0;
1375 if (len > entry_size - pos)
1376 len = (jint)(entry_size - pos);
1377
1378 /* Get file offset to start reading data */
1379 start = ZIP_GetEntryDataOffset(zip, entry);
1380 if (start < 0)
1381 return -1;
1382 start += pos;
1383
1384 if (start + len > zip->len) {
1385 zip->msg = "ZIP_Read: corrupt zip file: invalid entry size";
1386 return -1;
1387 }
1388
1389 if (readFullyAt(zip->zfd, buf, len, start) == -1) {
1390 zip->msg = "ZIP_Read: error reading zip file";
1391 return -1;
1392 }
1393 return len;
1394}
1395
1396
1397/* The maximum size of a stack-allocated buffer.
1398 */
1399#define BUF_SIZE4096 4096
1400
1401/*
1402 * This function is used by the runtime system to load compressed entries
1403 * from ZIP/JAR files specified in the class path. It is defined here
1404 * so that it can be dynamically loaded by the runtime if the zip library
1405 * is found.
1406 *
1407 * The current implementation does not support reading an entry that
1408 * has the size bigger than 2**32 bytes in ONE invocation.
1409 */
1410jboolean
1411InflateFully(jzfile *zip, jzentry *entry, void *buf, char **msg)
1412{
1413 z_stream strm;
1414 char tmp[BUF_SIZE4096];
1415 jlong pos = 0;
1416 jlong count = entry->csize;
1417
1418 *msg = 0; /* Reset error message */
1419
1420 if (count == 0) {
1421 *msg = "inflateFully: entry not compressed";
1422 return JNI_FALSE0;
1423 }
1424
1425 memset(&strm, 0, sizeof(z_stream));
1426 if (inflateInit2(&strm, -MAX_WBITS)inflateInit2_((&strm), (-15), "1.2.11", (int)sizeof(z_stream
))
!= Z_OK0) {
1427 *msg = strm.msg;
1428 return JNI_FALSE0;
1429 }
1430
1431 strm.next_out = buf;
1432 strm.avail_out = (uInt)entry->size;
1433
1434 while (count > 0) {
1435 jint n = count > (jlong)sizeof(tmp) ? (jint)sizeof(tmp) : (jint)count;
1436 ZIP_Lock(zip);
1437 n = ZIP_Read(zip, entry, pos, tmp, n);
1438 ZIP_Unlock(zip);
1439 if (n <= 0) {
1440 if (n == 0) {
1441 *msg = "inflateFully: Unexpected end of file";
1442 }
1443 inflateEnd(&strm);
1444 return JNI_FALSE0;
1445 }
1446 pos += n;
1447 count -= n;
1448 strm.next_in = (Bytef *)tmp;
1449 strm.avail_in = n;
1450 do {
1451 switch (inflate(&strm, Z_PARTIAL_FLUSH1)) {
1452 case Z_OK0:
1453 break;
1454 case Z_STREAM_END1:
1455 if (count != 0 || strm.total_out != (uInt)entry->size) {
1456 *msg = "inflateFully: Unexpected end of stream";
1457 inflateEnd(&strm);
1458 return JNI_FALSE0;
1459 }
1460 break;
1461 default:
1462 break;
1463 }
1464 } while (strm.avail_in > 0);
1465 }
1466
1467 inflateEnd(&strm);
1468 return JNI_TRUE1;
1469}
1470
1471/*
1472 * The current implementation does not support reading an entry that
1473 * has the size bigger than 2**32 bytes in ONE invocation.
1474 */
1475JNIEXPORT__attribute__((visibility("default"))) jzentry *
1476ZIP_FindEntry(jzfile *zip, char *name, jint *sizeP, jint *nameLenP)
1477{
1478 jzentry *entry = ZIP_GetEntry(zip, name, 0);
1479 if (entry) {
1480 *sizeP = (jint)entry->size;
1481 *nameLenP = (jint)strlen(entry->name);
1482 }
1483 return entry;
1484}
1485
1486/*
1487 * Reads a zip file entry into the specified byte array
1488 * When the method completes, it releases the jzentry.
1489 * Note: this is called from the separately delivered VM (hotspot/classic)
1490 * so we have to be careful to maintain the expected behaviour.
1491 */
1492JNIEXPORT__attribute__((visibility("default"))) jboolean
1493ZIP_ReadEntry(jzfile *zip, jzentry *entry, unsigned char *buf, char *entryname)
1494{
1495 char *msg;
1496 char tmpbuf[1024];
1497
1498 if (entry == 0) {
1499 jio_fprintf(stderrstderr, "jzentry was invalid");
1500 return JNI_FALSE0;
1501 }
1502
1503 strcpy(entryname, entry->name);
1504 if (entry->csize == 0) {
1505 /* Entry is stored */
1506 jlong pos = 0;
1507 jlong size = entry->size;
1508 while (pos < size) {
1509 jint n;
1510 jlong limit = ((((jlong) 1) << 31) - 1);
1511 jint count = (size - pos < limit) ?
1512 /* These casts suppress a VC++ Internal Compiler Error */
1513 (jint) (size - pos) :
1514 (jint) limit;
1515 ZIP_Lock(zip);
1516 n = ZIP_Read(zip, entry, pos, buf, count);
1517 msg = zip->msg;
1518 ZIP_Unlock(zip);
1519 if (n == -1) {
1520 if (msg == 0) {
1521 getErrorString(errno(*__errno_location ()), tmpbuf, sizeof(tmpbuf));
1522 msg = tmpbuf;
1523 }
1524 jio_fprintf(stderrstderr, "%s: %s\n", zip->name, msg);
1525 return JNI_FALSE0;
1526 }
1527 buf += n;
1528 pos += n;
1529 }
1530 } else {
1531 /* Entry is compressed */
1532 int ok = InflateFully(zip, entry, buf, &msg);
1533 if (!ok) {
1534 if ((msg == NULL((void*)0)) || (*msg == 0)) {
1535 msg = zip->msg;
1536 }
1537 if (msg == 0) {
1538 getErrorString(errno(*__errno_location ()), tmpbuf, sizeof(tmpbuf));
1539 msg = tmpbuf;
1540 }
1541 jio_fprintf(stderrstderr, "%s: %s\n", zip->name, msg);
1542 return JNI_FALSE0;
1543 }
1544 }
1545
1546 ZIP_FreeEntry(zip, entry);
1547
1548 return JNI_TRUE1;
1549}
1550
1551JNIEXPORT__attribute__((visibility("default"))) jboolean
1552ZIP_InflateFully(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg)
1553{
1554 z_stream strm;
1555 int i = 0;
1556 memset(&strm, 0, sizeof(z_stream));
1557
1558 *pmsg = 0; /* Reset error message */
1559
1560 if (inflateInit2(&strm, MAX_WBITS)inflateInit2_((&strm), (15), "1.2.11", (int)sizeof(z_stream
))
!= Z_OK0) {
1561 *pmsg = strm.msg;
1562 return JNI_FALSE0;
1563 }
1564
1565 strm.next_out = (Bytef *) outBuf;
1566 strm.avail_out = (uInt)outLen;
1567 strm.next_in = (Bytef *) inBuf;
1568 strm.avail_in = (uInt)inLen;
1569
1570 do {
1571 switch (inflate(&strm, Z_PARTIAL_FLUSH1)) {
1572 case Z_OK0:
1573 break;
1574 case Z_STREAM_END1:
1575 if (strm.total_out != (uInt)outLen) {
1576 *pmsg = "INFLATER_inflateFully: Unexpected end of stream";
1577 inflateEnd(&strm);
1578 return JNI_FALSE0;
1579 }
1580 break;
1581 case Z_DATA_ERROR(-3):
1582 *pmsg = "INFLATER_inflateFully: Compressed data corrupted";
1583 inflateEnd(&strm);
1584 return JNI_FALSE0;
1585 case Z_MEM_ERROR(-4):
1586 *pmsg = "INFLATER_inflateFully: out of memory";
1587 inflateEnd(&strm);
1588 return JNI_FALSE0;
1589 default:
1590 *pmsg = "INFLATER_inflateFully: internal error";
1591 inflateEnd(&strm);
1592 return JNI_FALSE0;
1593 }
1594 } while (strm.avail_in > 0);
1595
1596 inflateEnd(&strm);
1597 return JNI_TRUE1;
1598}
1599
1600static voidpf tracking_zlib_alloc(voidpf opaque, uInt items, uInt size) {
1601 size_t* needed = (size_t*) opaque;
1602 *needed += (size_t) items * (size_t) size;
1603 return (voidpf) calloc((size_t) items, (size_t) size);
1604}
1605
1606static void tracking_zlib_free(voidpf opaque, voidpf address) {
1607 free((void*) address);
1608}
1609
1610static voidpf zlib_block_alloc(voidpf opaque, uInt items, uInt size) {
1611 char** range = (char**) opaque;
1612 voidpf result = NULL((void*)0);
1613 size_t needed = (size_t) items * (size_t) size;
1614
1615 if (range[1] - range[0] >= (ptrdiff_t) needed) {
1616 result = (voidpf) range[0];
1617 range[0] += needed;
1618 }
1619
1620 return result;
1621}
1622
1623static void zlib_block_free(voidpf opaque, voidpf address) {
1624 /* Nothing to do. */
1625}
1626
1627static char const* deflateInit2Wrapper(z_stream* strm, int level) {
1628 int err = deflateInit2(strm, level >= 0 && level <= 9 ? level : Z_DEFAULT_COMPRESSION,deflateInit2_((strm),(level >= 0 && level <= 9 ?
level : (-1)),(8),(31),(8), (0), "1.2.11", (int)sizeof(z_stream
))
1629 Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY)deflateInit2_((strm),(level >= 0 && level <= 9 ?
level : (-1)),(8),(31),(8), (0), "1.2.11", (int)sizeof(z_stream
))
;
1630 if (err == Z_MEM_ERROR(-4)) {
1631 return "Out of memory in deflateInit2";
1632 }
1633
1634 if (err != Z_OK0) {
1635 return "Internal error in deflateInit2";
1636 }
1637
1638 return NULL((void*)0);
1639}
1640
1641JNIEXPORT__attribute__((visibility("default"))) char const*
1642ZIP_GZip_InitParams(size_t inLen, size_t* outLen, size_t* tmpLen, int level) {
1643 z_stream strm;
1644 *tmpLen = 0;
1645 char const* errorMsg;
1646
1647 memset(&strm, 0, sizeof(z_stream));
1648 strm.zalloc = tracking_zlib_alloc;
1649 strm.zfree = tracking_zlib_free;
1650 strm.opaque = (voidpf) tmpLen;
1651
1652 errorMsg = deflateInit2Wrapper(&strm, level);
1653
1654 if (errorMsg == NULL((void*)0)) {
1655 *outLen = (size_t) deflateBound(&strm, (uLong) inLen);
1656 deflateEnd(&strm);
1657 }
1658
1659 return errorMsg;
1660}
1661
1662JNIEXPORT__attribute__((visibility("default"))) size_t
1663ZIP_GZip_Fully(char* inBuf, size_t inLen, char* outBuf, size_t outLen, char* tmp, size_t tmpLen,
1664 int level, char* comment, char const** pmsg) {
1665 z_stream strm;
1666 gz_header hdr;
1667 int err;
1668 char* block[] = {tmp, tmpLen + tmp};
1669 size_t result = 0;
1670
1671 memset(&strm, 0, sizeof(z_stream));
1672 strm.zalloc = zlib_block_alloc;
1673 strm.zfree = zlib_block_free;
1674 strm.opaque = (voidpf) block;
1675
1676 *pmsg = deflateInit2Wrapper(&strm, level);
1677
1678 if (*pmsg == NULL((void*)0)) {
1679 strm.next_out = (Bytef *) outBuf;
1680 strm.avail_out = (uInt) outLen;
1681 strm.next_in = (Bytef *) inBuf;
1682 strm.avail_in = (uInt) inLen;
1683
1684 if (comment != NULL((void*)0)) {
1685 memset(&hdr, 0, sizeof(hdr));
1686 hdr.comment = (Bytef*) comment;
1687 deflateSetHeader(&strm, &hdr);
1688 }
1689
1690 err = deflate(&strm, Z_FINISH4);
1691
1692 if (err == Z_OK0 || err == Z_BUF_ERROR(-5)) {
1693 *pmsg = "Buffer too small";
1694 } else if (err != Z_STREAM_END1) {
1695 *pmsg = "Intern deflate error";
1696 } else {
1697 result = (size_t) strm.total_out;
1698 }
1699
1700 deflateEnd(&strm);
1701 }
1702
1703 return result;
1704}