From 6ff8169263b21e10db0b28c67879be8206bc1dc1 Mon Sep 17 00:00:00 2001 From: DongHun Kwak Date: Thu, 28 Jun 2018 14:26:11 +0900 Subject: [PATCH] Imported Upstream version 610c23 Change-Id: I142aafc73cc3be226ecc74419fed6272d7c895e8 Signed-off-by: DongHun Kwak --- History.610 | 54 +++++++++++- INSTALL | 97 +++++++++++---------- README | 101 +++++++++++++++------ beos/beos.c | 8 +- extract.c | 100 +++++++++++++++++++-- fileio.c | 140 ++++++++++++++++++----------- memdiag.c | 23 ++--- unix/unix.c | 8 +- unzpriv.h | 16 ++-- unzvers.h | 6 +- vms/vms.c | 266 +++++++++++++++++++++++++++++++++++++++++--------------- win32/win32.c | 25 +++--- zip-comment.txt | 16 +++- 13 files changed, 617 insertions(+), 243 deletions(-) diff --git a/History.610 b/History.610 index 1e7e141..e280906 100644 --- a/History.610 +++ b/History.610 @@ -661,7 +661,10 @@ Features added (or removed): suggestions. Other related, minor code tidying. (unzip.c, unzip.h, unzpriv.h, vms/cmdline.c) [SMS] -6.1c21 (08 Jun 2017): +6.1c22 (08 Jun 2017): + - No news. + +6.1c23 (11 Dec 2017): - No news. @@ -1774,7 +1777,7 @@ Bugs fixed: fake "compression method" of 99, and the actual compression method is stored in an AES_WG extra block. In some cases, the AES_WG "99" value was being used instead of the actual value from the extra - block.) (extract.c) [Elvis Angelaccio, SMS] + block.) (extract.c) [Elvis Angelaccio, SMS] - Revised some "UT"-related comments. (process.c) [SMS] 6.1c21 (12 May 2017): @@ -1941,3 +1944,50 @@ Bugs fixed: (fn_matched, xn_matched) before returning after an error. New macro: unzpriv.h:SKIP_ZI(). (process.c, unzpriv.h, zipinfo.c) [Jiri Kukacka, SMS] + +6.1c23 (29 Nov 2017): + - On Windows with Unicode support, for an archive whose paths used + backslash ("\") directory separators, the backslashes were + mishandled, resulting in extracted file paths/names like "dir_name" + instead of "dir\name". Similar problems could have occurred with + absolute paths in an archive. Both backslash directory separators + and absolute paths violate the standard for zip archives, but they + can be found in some archives. UnZip's policy is to treat backslash + characters as slash characters ("/") for archive members which claim + to originate on FAT (or similar) file systems, but this was failing + in some cases on Windows with Unicode support enabled. + Forum topic: http://www.info-zip.org/phpBB3/viewtopic.php?f=7&t=541 + (extract.c) [SMS] + - On Windows with Unicode support, some name storage could be reused + inappropriately, resulting in a file with a Unicode name being + extracted with a (wrong) name left over from some previously + processed file. + Forum topic: http://www.info-zip.org/phpBB3/viewtopic.php?f=7&t=541 + (fileio.c) [SMS] + - Some standard memory-allocation function names were still used + instead of the private ones which support the crude, optional, + dynamic memory tracing diagnostic capability for use by developers. + (fileio.c, unzpriv.h, win32/win32.c) [SMS] + - On Windows with Unicode support, memory leaked when creating a + directory for extracted files. (win32/win32.c) [Andreas + Schniertshauer, SMS] + - On VMS, in -f/--freshen (/FRESHEN) mode, UnZip did not attempt to + create nonexistent files, but it would erroneously create a directory + stack which would lead to a nonexistent file. For example, in an + empty directory (where there's nothing to freshen), when freshening + "a/b/c.txt" UnZip would create "[.a.b]", and then not create "c.txt" + in it. Now, as on other systems, when freshening, neither + directories nor files are created when they do not already exist. + (Exception: When overwriting, or creating a new version of, an + existing file (interactive "[r]ename" option), the user-specified + directories and file are always created.) (vms/vms.c) [SMS] + - Long member names in an archive could cause buffer overflow in + encryption password processing. (fileio.c) [R. Freingruber, SMS] + - Long member names in an archive which require character-set + conversion could cause buffer overflow in character-set conversion. + (fileio.c) [R. Freingruber, SMS] + - An archive name with no ".zip" suffix caused buffer overflow in + split-archive segment name ("xxx.z01", ...) formation. (fileio.c) + [R. Freingruber, SMS] + - Invalid extra-field data (EF_STREAM, "xl" extra block) could cause + buffer overflow. (extract.c) [R. Freingruber, SMS] diff --git a/INSTALL b/INSTALL index 20cf4ae..016593d 100644 --- a/INSTALL +++ b/INSTALL @@ -1,17 +1,14 @@ INSTALL -- Info-ZIP UnZip Installation Instructions =================================================== - UnZip version 6.1. Revised: 2017-01-27 + UnZip version 6.1. Revised: 2017-06-14 ------------------------------------------------------------------------ On most system types, the general procedure to build and install -UnZip follows these steps: +UnZip follows these steps (described in more detail below): - 1. Unpack the UnZip source kit. (Some optional features, such as - optional compression or encryption methods, may require additional - source kits. Obtain and unpack any additional source kits, if - needed.) + 1. Unpack the UnZip source kit. 2. Build. That is, compile and link the programs. A C compiler and a "make" program are usually required. Other standard utility @@ -591,9 +588,8 @@ MVS, z/OS and execute it to compile and link all the sources. C/370 2.1 or later is required. See README.MVS for further details. (This is a new port and may need a little more work even to compile.) There has - been considerable work on the MVS and z/OS ports lately (indeed, z/OS - may be split off as its own port soon), so there should be updates to - these procedures shortly. + been considerable work on the MVS and z/OS ports in recent years, but + not much lately. VM/CMS Unpack all the files and transfer them with ASCII -> EBCDIC @@ -605,7 +601,7 @@ VM/CMS will abend without access to the C/370 runtime library. See the README.CMS file for more details. -Windows (XP, Vista, 7, and so on) +Windows (XP, Vista, 7, 10, and so on) UnZip solution and project files for Microsoft Visual Studio 2010 are supplied in the win32\vc10\ subdirectory. Optional features, such as optional compression and encryption methods, are controlled by @@ -628,8 +624,8 @@ Windows (XP, Vista, 7, and so on) Studio 2010 are supplied in the windll\vc10\ subdirectory. As with UnZip itself, optional features are controlled by Preprocessor Definitions (C macros). Also similarly, the solution file, - unzip32_dll.sln, includes the "libbz2" project as as a prerequisite - for the "unz32dll" and "uzexampl" projects. + unzip32_dll.sln, includes the "libbz2" project as a prerequisite for + the "unz32dll" and "uzexampl" projects. Currently, Microsoft Visual Studio 2010 (Visual C++ v10.0), VS 2012 (VC++ v11.0), VS 2013 (VC++ 12.0), and VS 2015 (VC++ 14.0) are the @@ -914,11 +910,11 @@ Human68K, TOPS-20, AOS/VS, etc. Post-Installation ----------------- - Some operating systems may require a timezone variable to be set -correctly (often "TZ"). Unix and VMS generally do so by default. -Windows does, if set up properly. Other operating systems may not. See -the discussion of the -f and -u options in the UnZip man page (or -docs/unzip.txt). + Some operating systems may require some kind of timezone +configuration (environment variable "TZ", or other). Unix, VMS (V7.0 or +later), and Windows generally do this by default. Other operating +systems may not. See the discussion of the -f and -u options in the +UnZip man page (or docs/unzip.txt). ------------------------------------------------------------------------ @@ -931,6 +927,17 @@ docs/unzip.txt). System-Specific C macros Unicode-related C macros + Note that in the descriptions below, some of these macros are +described as defined by default. In some cases, this is done +statically, in one of the header files; in other cases, it may be done +dynamically, by the builders (scripts, "make" or MMS/MMK description +files, Visual Studio project files, and so on). In any case, the result +may be affected by the builders being used, build options specified by +the user, compiler limitations (especially on very old systems), files +which are included in (or have been removed from) the kit, and so on. +Thus, "default" in the following descriptions is normally accurate, but +that can be influenced by various external factors. + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - General C Macros @@ -950,11 +957,11 @@ BZIP2_SFX bzip2 compression support is disabled in UnZipSFX even when it's enabled in UnZip itself. -BZIP2_SUPPORT (requires bzip2 object library) +BZIP2_SUPPORT Enable support for bzip2 compression. UnZip can optionally support the "bzip2" compression algorithm on most ports on 32-bit (or higher) - platforms. Currently, this support is integrated in the builders for - MSDOS 32-bit (DJGPP), Unix, VMS, and Windows. + platforms. Currently, this support is enabled by default in the + builders for MSDOS 32-bit (DJGPP), Unix, VMS, and Windows. Compilation: - MSDOS: You have to supply the macro definition "USEBZ2=1" on the @@ -985,11 +992,10 @@ CHEAP_SFX_AUTORUN with the "-d " command line option, therefore CHEAP_SFX_AUTORUN implicitly sets the NO_SFX_EXDIR option (below). -IZ_CRYPT_AES_WG (requires additional external code distribution) +IZ_CRYPT_AES_WG Enable WinZip/Gladman AES (strong) encryption support. Currently, - this support is integrated in the Make procedures of MSDOS 32-bit - (DJGPP), VMS, Windows, and many Unix systems. A separately - distributed IZ_AES_WG source code kit is required. + this support is enabled by default in the builders for MSDOS 32-bit + (DJGPP), Unix, VMS, and Windows. IZ_CRYPT_AES_WG_SFX Enable WinZip/Gladman AES (strong) encryption support in UnZipSFX (if @@ -998,15 +1004,16 @@ IZ_CRYPT_AES_WG_SFX it's enabled in UnZip itself. IZ_CRYPT_TRAD_SFX - Enable Traditional (weak) encryption support in UnZipSFX. The - default setting is to disable Traditional encryption in UnZipSFX, to - reduce its size. In UnZip, encryption support is enabled by default. + Enable Traditional (weak) encryption support in UnZipSFX. By + default, to reduce the size of the UnZipSFX executable, Traditional + encryption support is disabled in UnZipSFX even when it's enabled in + UnZip itself. In UnZip, encryption support is enabled by default. See also NO_CRYPT, below. DATE_FORMAT=DF_DMY or DF_MDY or DF_YMD Specify the order in which date components are printed in non-ZipInfo-mode listings: day-month-year, month-day-year, or - year-month-day. On DOS, FlexOS, OS2, Theos and Windows, the format + year-month-day. On DOS, FlexOS, OS2, Theos, and Windows, the format is automatically obtained from the operating system; most others default to DF_MDY. @@ -1032,12 +1039,12 @@ NO_DEFLATE64 (default in UnZipSFX) better compression ratios on highly redundant data. For better compatibility with archives which use this method, UnZip should be built with support for Deflate64 enabled. However, this results in - significantly larger memory requirements to run the program. For - 16-bit executables (DOS and OS/2), the special memory management to - support the 64K history buffer results in a slight speed penalty. - For UnZipSFX, "Deflate64" support should be unnecessary so long as - the Info-ZIP Zip utility does not support it. The NO_DEFLATE64 - option disables Deflate64 support. + larger memory requirements to run the program. For 16-bit + executables (DOS and OS/2), the special memory management to support + the 64K history buffer results in a slight speed penalty. For + UnZipSFX, "Deflate64" support should be unnecessary so long as the + Info-ZIP Zip utility does not support it. The NO_DEFLATE64 option + disables Deflate64 support. DELETE_IF_FULL (any system with unlink() function) If a write error is encountered (most likely due to a full disk), @@ -1052,10 +1059,11 @@ LZMA_SFX enabled in UnZip itself. LZMA_SUPPORT - Enable LZMA compression support in UnZip. + Enable LZMA compression support in UnZip. Enabled by default on + Unix, VMS, and Windows. LZW_CLEAN -UNSHRINK_SUPPORT (now default, as of January 2005) +UNSHRINK_SUPPORT (default, as of January 2005) The "shrinking" algorithm from PKZIP 1.0 is an LZW variant. Unisys patented the Lempel-Ziv-Welch algorithm in 1985 and has publicly claimed that decompression is covered by it. (IBM also patented the @@ -1063,11 +1071,12 @@ UNSHRINK_SUPPORT (now default, as of January 2005) Unisys and IBM patents expired worldwide, so unshrinking is now enabled again by default. If you do not wish to include the LZW method, you may still disable it by defining LZW_CLEAN. (Unshrinking - was used by PKZIP 1.0 and 1.1, and Zip 1.0 and 1.1. All newer - archives use only the deflation method.) + was used by PKZIP 1.0 and 1.1, and Zip 1.0 and 1.1. Newer program + versions do not use the "shrinking" method.) NO_BUILD_DATE - Omit the build date from the "Compiled with" line in the "-v" report. + Omit the build date from the "Compiled with" line in the "-v" report, + to make the build reproducible. NO_CRYPT Disable all encryption support in all programs. @@ -1117,8 +1126,7 @@ OS2_EAS List the sizes of OS/2 EAs and ACLs for each file as two extra columns in "unzip -l" output. This is primarily useful on OS/2 systems, but, because zipfiles are portable, OS2_EAS can be defined - for any system. (May be extended someday to show sizes of Mac - resource forks, RISCOS and VMS file info, etc.) + for any system. PPMD_SFX Enable PPMd compression support in UnZipSFX (if it's enabled in @@ -1127,7 +1135,8 @@ PPMD_SFX enabled in UnZip itself. PPMD_SUPPORT - Enable PPMd compression support in UnZip. + Enable PPMd compression support in UnZip. Enabled by default on + Unix, VMS, and Windows. UNIXBACKUP (default on OS/2, Unix, Windows) Enable a -B option that instructs UnZip to rename files that would @@ -1154,7 +1163,7 @@ USE_UNREDUCE_SMITH all restrictions in Smith's copyright. See the UnZip COPYING.OLD file for details. -VMS_TEXT_CONV (default everywhere except VMS) +VMS_TEXT_CONV (default everywhere except VMS, where it's not needed) NO_VMS_TEXT_CONV VMS_TEXT_CONV enables conversion of some VMS-specific text file formats, and is defined by default in UnZip (but not in UnZipSFX). @@ -1171,7 +1180,7 @@ NO_VMS_TEXT_CONV field analyzer to identify such text files. (Very old versions of UnZip applied some heuristics instead.) -WILD_STOP_AT_DIR (incompatible with WINDLL!) +WILD_STOP_AT_DIR Enables an additional option "-W". When "-W" is specified, the pattern-matching routine is modified so that both "?" (single-char wildcard) and "*" (multi-char wildcard) do not match the directory diff --git a/README b/README index b720319..0c14366 100644 --- a/README +++ b/README @@ -2,7 +2,7 @@ ------------------------ Program version: 6.1c (BETA). - Document date: 2016-04-07 + Document date: 2017-12-08 ------------------------------------------------------------------------ @@ -73,7 +73,7 @@ additional (mostly old) documentation of particular interest to developers. For program usage information, source kits include a "docs" -subdirectory wich contains ".txt" files with formatted Unix "man" +subdirectory which contains ".txt" files with formatted Unix "man" output, and may also include ".htx" files with VMS help output. ------------------------------------------------------------------------ @@ -97,29 +97,21 @@ complaints and suggestions involving their use on almost anything. UnZip has been ported to operating systems like AmigaDOS, AOS/VS, Atari TOS, Acorn RISC OS, BeOS, FlexOS, Human68k, IBM mainframes (MVS, VM/CMS, z/OS), Macintosh (pre-OS-X), MS-DOS, OS/2, SMS/QDOS, Tandem NSK, and -TOPS-20. A DLL is available for OS/2 and Windows. +TOPS-20. A DLL is available for OS/2 and Windows. An object library is +available on Unix, VMS, and Windows. ------------------------------------------------------------------------ - Significant New Features and Behavior Changes Since UnZip 6.00 + Significant Behavior Changes and New Features Since UnZip 6.00 -------------------------------------------------------------- -- Optional support for WinZip-compatible AES encryption (compression - method 99). For better export control, the source kit for AES - encryption is distributed separately from the main UnZip source kit. - See aes_wg/README_AES_WG.txt for more information. - -- Optional support for compression methods LZMA (14) and PPMd (98). - See szip/README_SZIP.txt for more information. - -- Full Unicode support for Windows + For more details on new command-line options or other features, + please see the usual Unix "man" or VMS HELP documentation. -- New -I and -O options for ISO and OEM character set conversion, - respectively, using iconv. See INSTALL (or unix/Makefile) for details - on enabling iconv support. +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- New command-line parser (like the one used by Zip). Functional - changes include: +- Behavior change: New command-line parser (like the one used by Zip). + Functional changes include: - Addition of long options, like "--license". - Addition of two-character short options, for example, "-so". Note that this can make some combined one-character options ambiguous. @@ -171,11 +163,27 @@ TOPS-20. A DLL is available for OS/2 and Windows. options), and a user-specified "rename" (file-system) path/name should be used as specified. -- New -da/--auto-extract-dir option to specify a destination directory - for extracted files which is derived from the base name of the - archive. For example, with -da, extraction of "fred.zip" is done into - subdirectory "fred" instead of into the current directory. (On VMS, - subdirectory "[.fred]".) +- Behavior change (possible): New -da/--auto-extract-dir option to + specify a destination directory for extracted files which is derived + from the base name of the archive. For example, with -da, extraction + of "fred.zip" is done into subdirectory "fred" instead of into the + current directory. (On VMS, subdirectory "[.fred]".) Previously + (with the old command-line parser), "-da" would be interpreted as + equivalent to "-d a", which would extract into the destination + directory "a". + +- Optional support for WinZip-compatible AES encryption (compression + method 99). See aes_wg/README_AES_WG.txt for more information. + +- Optional support for compression methods LZMA (14) and PPMd (98). + See szip/README_SZIP.txt for more information. + +- Better Unicode support for Windows + +- New -I and -O options for ISO and OEM character set conversion, + respectively, using iconv. See INSTALL (or unix/Makefile) for details + on enabling/disabling iconv support. (The unix/configure script + should enable it automatically, by default, where it appears to work.) - -j/--junk-dirs option now accepts an optional value, the number of directory levels to discard. As before, plain "-j" discards all @@ -230,9 +238,9 @@ TOPS-20. A DLL is available for OS/2 and Windows. If you have a question regarding redistribution of Info-ZIP software, whether as-is, as packaging for a commercial product, or as an integral part of a commercial product, please read the Frequently Asked Questions -(FAQ) section of the included COPYING file. All Info-ZIP releases are -now covered by the Info-ZIP license. See the file LICENSE. The most -current license should be available at: +(FAQ) section of the included COPYING.OLD file. All Info-ZIP releases +are now covered by the Info-ZIP license. See the file LICENSE. The +most current license should be available at: http://info-zip.org/license.html ftp://ftp.info-zip.org/pub/infozip/license.html @@ -337,8 +345,47 @@ in the next release. ------- Too much time has passed between the releases of UnZip versions 6.10b -and 6.1c. UnZip 6.1c lacks support for some new features in Zip 3.1d. +and 6.1c. UnZip 6.1c lacks support for some new features in Zip 3.1d. We'll try to get the missing features into UnZip 6.1d, and to get the final UnZip 6.1 released in a more timely way. ------------------------------------------------------------------------ + + WARNING + ------- + + The Info-ZIP AES_WG source kit (iz_aes_wg.zip), and the UnZip and + Zip source kits which include it, are subject to US export control + laws. BEFORE downloading or using any version of any of these + kits, read the following Encryption Notice. You agree to follow + these terms (as well as the terms of the Info-ZIP license) when + you download and/or use any of these source kits. + +- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + Encryption Notice + ----------------- + + This software kit includes encryption software. The country or + other jurisdiction where you are may restrict the import, + possession, use, and/or re-export to another country, of + encryption software. BEFORE using any encryption software, please + check all applicable laws, regulations, and policies concerning + the import, possession, use, and re-export of encryption software, + to see if these are permitted. Some helpful information may be + found at: http://www.wassenaar.org/ + + Export and re-export of this software from the US are governed by + the US Department of Commerce, Bureau of Industry and Security + (BIS). This is open-source ("publicly available") software. + Info-ZIP has submitted the required notification to the BIS. The + details are: + Export Commodity Control Number (ECCN) 5D002 + License Exception: Technology Software Unrestricted (TSU) + (Export Administration Regulations (EAR) Section 740.13) + + A copy of the required BIS notification is available in the file + aes_wg/USexport_aes_wg.msg in the source kits, and at: + ftp://ftp.info-zip.org/pub/infozip/crypt/USexport_AES_WG.msg + +------------------------------------------------------------------------ diff --git a/beos/beos.c b/beos/beos.c index b14b0bc..ecdc2c8 100644 --- a/beos/beos.c +++ b/beos/beos.c @@ -1733,7 +1733,11 @@ void charset_to_intern(char *string, char *from_charset) d = buf = malloc(buflen + 1); if (d) { - memset( buf, 0, buflen); + /* 2017-11-29 Rene Freingruber, SMS. + * Was using buflen, ignoring last byte. Next strcpy() was + * strncpy() with a bad maxchar parameter (buflen). + */ + memset( buf, 0, (buflen+ 1)); /* 2015-02-12 William Robinet, SMS. CVE-2015-1315. * Added FILNAMSIZ check to avoid buffer overflow. Better would @@ -1742,7 +1746,7 @@ void charset_to_intern(char *string, char *from_charset) if ((iconv(cd, &s, &slen, &d, &dlen) != (size_t)-1) && (strlen(buf) < FILNAMSIZ)) { - strncpy(string, buf, buflen); + strcpy(string, buf); } free(buf); } diff --git a/extract.c b/extract.c index 7188243..7fd5d36 100644 --- a/extract.c +++ b/extract.c @@ -18,6 +18,7 @@ check_unmatched_names() match_include_exclude() name_abs_rel() + name_abs_relw() name_junk() name_junkw() test_compr_eb() @@ -35,6 +36,7 @@ password_check() (IZ_CRYPT_ANY) detect_apl_dbl() (UNIX && __APPLE__) backslash_slash() (ndef SFX) + backslash_slashw() (ndef SFX) extract_test_trailer() extract_or_test_member() mapname_dir_vollab() @@ -630,6 +632,43 @@ static int name_abs_rel( __G) /* Return PK-type error code. */ } /* name_abs_rel(). */ +#if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) + +/******************************/ +/* Function name_abs_relw() */ +/******************************/ + +static int name_abs_relw( __G) /* Return PK-type error code. */ + __GDEF +{ + int error = PK_OK; + + /* Transform an absolute path to a relative path, and warn user. */ + if (G.unipath_widefilename[0] == L'/') + { + Info(slide, 0x401, ((char *)slide, + LoadFarString(AbsolutePathWarning), + FnFilterW1(G.unipath_widefilename))); + error = PK_WARN; + + do /* While there's a leading slash, ... */ + { + wchar_t *wp; + + wp = G.unipath_widefilename + 1; + do /* Left-shift all characters one place. */ + { + *(wp-1) = *wp; + } while (*wp++ != L'\0'); + } while (G.unipath_widefilename[0] == L'/'); + } + + return error; +} /* name_abs_relw(). */ + +#endif /* defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */ + + /**************************/ /* Function name_junk() */ /**************************/ @@ -719,7 +758,7 @@ static int name_junkw( __G) /* Return PK-type error code. */ if (uO.jflag < 0) { /* "-j": Junking all directories. Find last slash (if any). */ - wslp = wcschr( G.unipath_widefilename, '/'); + wslp = wcschr( G.unipath_widefilename, L'/'); if (wslp != NULL) { /* Found a last slash. Name begins after it. */ @@ -733,7 +772,7 @@ static int name_junkw( __G) /* Return PK-type error code. */ for (i = 0; i < uO.jflag; i++) { - wslp = wcschr( G.unipath_jdir_widefilename, '/'); + wslp = wcschr( G.unipath_jdir_widefilename, L'/'); if (wslp == NULL) { if (G.filename[ strlen( G.filename)- 1] == '/') @@ -1219,8 +1258,11 @@ static int ef_scan_for_stream( ef_ptr, ef_len, btmp_siz, btmp, xlhdr, cmnt) /* Loop through (and save) the bitmap bytes. */ data_byte = 0; do - { - if (bitmap_byte_max >= eb_len) /* Stay within the block. */ + { /* Stay within the block (and whole field). */ + /* 2017-11-29 Rene Freingruber, SMS. + * Added check for end of extra field (ef_len). + */ + if ((bitmap_byte_max >= eb_len) || (data_byte >= ef_len)) { /* Out of data before end-of-bitmap. */ TTrace((stderr, @@ -1230,6 +1272,7 @@ static int ef_scan_for_stream( ef_ptr, ef_len, btmp_siz, btmp, xlhdr, cmnt) } /* If the user has space for another, then return a bitmap byte. */ + bitmap = *(ef_ptr+ (data_byte++)); if (bitmap_byte_max < *btmp_siz) { @@ -2085,7 +2128,7 @@ static int detect_apl_dbl( __G) #endif /* defined( UNIX) && defined( __APPLE__) */ -# ifndef SFX +#ifndef SFX /********************************/ /* Function backslash_slash() */ @@ -2121,7 +2164,46 @@ static int backslash_slash( __G) return error; } /* backslash_slash(). */ -# endif /* ndef SFX */ + +# if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) + +/*********************************/ +/* Function backslash_slashw() */ +/*********************************/ +static int backslash_slashw( __G) + __GDEF +{ + int error = PK_OK; /* Return PK-type error code. */ + + if ((G.pInfo->hostnum == FS_FAT_) && !MBSCHR(G.filename, '/')) + { + wchar_t *wp = G.unipath_widefilename; + + if (*wp) + { + do + { + if (*wp == L'\\') + { + if (!G.reported_backslash) + { + Info(slide, 0x21, ((char *)slide, + LoadFarString(BackslashPathSep), G.zipfn)); + G.reported_backslash = TRUE; + error = PK_WARN; + } + *wp = L'/'; + } + } while (*(++wp)); + } + } + + return error; +} /* backslash_slashw(). */ + +# endif /* if defined(UNICODE_SUPPORT) && defined(WIN32_WIDE) */ + +#endif /* ndef SFX */ /*************************************/ @@ -3571,7 +3653,7 @@ startover: * SFX, because we assume that our Zip doesn't do it. */ #ifndef SFX - error = backslash_slash( __G); + error = backslash_slashw( __G); if (error != PK_OK) { if (*perr_in_arch == PK_OK) @@ -3582,7 +3664,7 @@ startover: if (!*prenamed) { /* Transform absolute path to relative path, and warn user. */ - error = name_abs_rel( __G); + error = name_abs_relw( __G); if (error != PK_OK) *perr_in_arch = error; } @@ -5266,7 +5348,6 @@ static int extract_or_test_entrylistw(__G__ mbr_ndx, if (G.pInfo->lcflag) { /* replace with lowercase filename */ wcslwr(G.unipath_widefilename); } -# endif /* def DYNAMIC_WIDE_NAME [else] */ # if 0 if (G.pInfo->vollabel && (length > 8) && (G.unipath_widefilename[8] == '.')) { @@ -5276,6 +5357,7 @@ static int extract_or_test_entrylistw(__G__ mbr_ndx, } # endif /* 0 */ } +# endif /* def DYNAMIC_WIDE_NAME [else] */ # ifndef SFX /* Filename consistency checks must come after reading in the diff --git a/fileio.c b/fileio.c index a001dd4..4eb7e29 100644 --- a/fileio.c +++ b/fileio.c @@ -14,7 +14,10 @@ output, file-related sorts of things, plus some miscellaneous stuff. Most of the stuff has to do with opening, closing, reading and/or writing files. - Contains: open_input_file() + Contains: open_infile() + close_infile() + set_zipfn_sgmnt_name() + open_infile_sgmnt() open_outfile() (not: VMS, AOS/VS, CMSMVS, MACOS, TANDEM) undefer_input() defer_leftover_input() @@ -24,6 +27,7 @@ seek_zipf() fgets_ans() flush() (non-VMS) + partflush() is_vms_varlen_txt() (non-VMS, VMS_TEXT_CONV only) disk_error() (non-VMS) UzpMessagePrnt() @@ -43,7 +47,9 @@ str2iso() (CRYPT && NEED_STR2ISO, only) str2oem() (CRYPT && NEED_STR2OEM, only) memset() (ZMEM only) + memcmp() (ZMEM only) memcpy() (ZMEM only) + labs() zstrnicmp() (NO_STRNICMP only) zstat() (REGULUS only) plastchar() (_MBCS only) @@ -347,8 +353,9 @@ int set_zipfn_sgmnt_name( __G__ sgmnt_nr) zuvl_t sgmnt_nr; #endif /* def PROTO [else] */ { - char *suffix; - int sufx_len; + int dgt_ndx; + int sufx_ndx; + size_t zipfn_len; /* sizeof( ".z65535") == 8 should be safe. */ #define SGMNT_NAME_BOOST 8 @@ -361,10 +368,12 @@ int set_zipfn_sgmnt_name( __G__ sgmnt_nr) return 1; } + zipfn_len = strlen( G.zipfn); + if (G.zipfn_sgmnt == NULL) - { - G.zipfn_sgmnt_size = (int)strlen(G.zipfn)+ SGMNT_NAME_BOOST; - if ((G.zipfn_sgmnt = izu_malloc(G.zipfn_sgmnt_size)) == NULL) + { /* Allocate new space. */ + G.zipfn_sgmnt_size = (int)zipfn_len+ SGMNT_NAME_BOOST; + if ((G.zipfn_sgmnt = izu_malloc( G.zipfn_sgmnt_size)) == NULL) { G.zipfn_sgmnt_size = -1; return 1; @@ -372,11 +381,11 @@ int set_zipfn_sgmnt_name( __G__ sgmnt_nr) } else { - if (G.zipfn_sgmnt_size < (int)strlen(G.zipfn)+ SGMNT_NAME_BOOST) - { - G.zipfn_sgmnt_size = (int)strlen(G.zipfn)+ SGMNT_NAME_BOOST; - izu_free(G.zipfn_sgmnt); - if ((G.zipfn_sgmnt = izu_malloc(G.zipfn_sgmnt_size)) == NULL) + if (G.zipfn_sgmnt_size < (int)zipfn_len+ SGMNT_NAME_BOOST) + { /* Allocated space could be too small. Reallocate. */ + G.zipfn_sgmnt_size = (int)zipfn_len+ SGMNT_NAME_BOOST; + G.zipfn_sgmnt = izu_realloc( G.zipfn_sgmnt, G.zipfn_sgmnt_size); + if (G.zipfn_sgmnt == NULL) { G.zipfn_sgmnt_size = -1; return 1; @@ -384,11 +393,10 @@ int set_zipfn_sgmnt_name( __G__ sgmnt_nr) } } - if (sgmnt_nr == G.ecrec.number_this_disk) { - zfstrcpy(G.zipfn_sgmnt, G.zipfn); - return 0; /* Last segment. Name already ".zip." */ + zfstrcpy( G.zipfn_sgmnt, G.zipfn); + return 0; /* Last segment. Leave archive name as-is. */ } #ifdef VMS @@ -402,30 +410,33 @@ int set_zipfn_sgmnt_name( __G__ sgmnt_nr) #else /* def VMS */ - zfstrcpy(G.zipfn_sgmnt, G.zipfn); - /* Expect to find ".zXX" at the end of the segment file name. */ - sufx_len = IZ_MAX( 0, ((int)strlen(G.zipfn_sgmnt)- 4)); - suffix = G.zipfn_sgmnt+ sufx_len; - - /* try find filename extension and set right position for add number */ - if (zfstrcmp(suffix, ZSUFX) == 0) + dgt_ndx = -1; /* Suffix not found. */ + zfstrcpy( G.zipfn_sgmnt, G.zipfn); /* Copy whole archive name. */ + /* Expect ".zip", or similar suffix, at the end of the segment file name. */ + sufx_ndx = IZ_MAX( 0, ((int)strlen( G.zipfn_sgmnt)- strlen( ZSUFX))); + if (zfstrcmp( (G.zipfn+ sufx_ndx), ZSUFX) == 0) /* Case-insens? */ { - suffix += 2; /* Point to digits after ".z". */ -# ifdef ZSUFX2 - } - else if (zfstrcmp(suffix, ZSUFX2) == 0) /* Check alternate suffix. */ - { - suffix[1] = 'z'; /* Should be always lowercase??? */ - suffix += 2; /* Point to digits after ".z". */ -# endif + dgt_ndx = strlen( G.zipfn_sgmnt)- 2; } +# ifdef ZSUFX2 else { - zfstrcpy( (suffix+ sufx_len), ZSUFX); - suffix += sufx_len+ 2; + sufx_ndx = IZ_MAX( 0, ((int)strlen( G.zipfn_sgmnt)- strlen( ZSUFX2))); + if (zfstrcmp( (G.zipfn+ sufx_ndx), ZSUFX2) == 0) /* Case-insens? */ + { + dgt_ndx = strlen( G.zipfn_sgmnt)- 2; + } + } +# endif /* def ZSUFX2 */ + + if (dgt_ndx < 0) + { /* No suffix detected. Append the (local) standard suffix. */ + strcpy( (G.zipfn_sgmnt+ zipfn_len), ZSUFX); + dgt_ndx = zipfn_len+ strlen( ZSUFX)- 2; } - /* Insert the next segment number into the file name (G.zipfn_sgmnt). */ - sprintf(suffix, "%02d", (sgmnt_nr+ 1)); + + /* Overwrite the last two suffix characters with the next segment number. */ + sprintf( (G.zipfn_sgmnt+ dgt_ndx), "%02d", (sgmnt_nr+ 1)); #endif /* def VMS [else] */ @@ -615,7 +626,7 @@ int open_outfile(__G) /* return 1 if fail */ if (flen > tlen) flen = tlen; tlen = FILNAMSIZ; } else { - tname = (char *)malloc(tlen); + tname = (char *)izu_malloc(tlen); if (tname == NULL) return 1; /* in case we run out of space */ strcpy(tname, G.filename); /* make backup name */ @@ -707,7 +718,7 @@ int open_outfile(__G) /* return 1 if fail */ # ifdef TOPS20 char *tfilnam; - if ((tfilnam = (char *)malloc(2*strlen(G.filename)+1)) == (char *)NULL) + if ((tfilnam = (char *)izu_malloc(2*strlen(G.filename)+1)) == (char *)NULL) return 1; strcpy(tfilnam, G.filename); upper(tfilnam); @@ -2396,6 +2407,8 @@ int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) int r = IZ_PW_ENTERED; char *m; char *prompt; + char *ep; + char *zp; # ifndef REENTRANT /* tell picky compilers to shut up about "unused variable" warnings */ @@ -2404,9 +2417,12 @@ int UZ_EXP UzpPassword (pG, rcnt, pwbuf, size, zfn, efn) if (*rcnt == 0) { /* First call for current entry */ *rcnt = 2; - if ((prompt = (char *)malloc(2*FILNAMSIZ + 15)) != (char *)NULL) { - sprintf(prompt, LoadFarString(PasswPrompt), - FnFilter1(zfn), FnFilter2(efn)); + zp = FnFilter1( zfn); + ep = FnFilter2( efn); + prompt = (char *)izu_malloc( /* Slightly too long (2* "%s"). */ + sizeof( PasswPrompt)+ strlen( zp)+ strlen( ep)); + if (prompt != (char *)NULL) { + sprintf(prompt, LoadFarString(PasswPrompt), zp, ep); m = prompt; } else m = (char *)LoadFarString(PasswPrompt2); @@ -2601,7 +2617,7 @@ time_t dos_to_unix_time(dosdatetime) return (time_t)-1; # ifdef TOPS20 - tmx = (struct tmx *)malloc(sizeof(struct tmx)); + tmx = (struct tmx *)izu_malloc(sizeof(struct tmx)); sprintf (temp, "%02d/%02d/%02d %02d:%02d:%02d", mo+1, dy+1, yr, hh, mm, ss); time_parse(temp, tmx, (char *)0); m_time = time_make(tmx); @@ -3146,7 +3162,7 @@ int do_string(__G__ length, option) /* return PK-type error code */ { if (G.filename_full) izu_free(G.filename_full); - G.filename_full = malloc( fnbufsiz); + G.filename_full = izu_malloc( fnbufsiz); if (G.filename_full == NULL) return PK_MEM; G.fnfull_bufsize = fnbufsiz; @@ -3162,7 +3178,7 @@ int do_string(__G__ length, option) /* return PK-type error code */ fnbufsiz = length + 1; if (G.filename_full) izu_free(G.filename_full); - G.filename_full = malloc(fnbufsiz); + G.filename_full = izu_malloc(fnbufsiz); if (G.filename_full == NULL) return PK_MEM; G.fnfull_bufsize = fnbufsiz; @@ -3182,6 +3198,21 @@ int do_string(__G__ length, option) /* return PK-type error code */ block_len = 0; strncpy(G.filename, G.filename_full, length); G.filename[length] = '\0'; /* terminate w/zero: ASCIIZ */ + + /* 2017-07-25 SMS. + * Moved to here from case EXTRA_FIELD:, below. (Old Unicode + * names were getting reused.) + * 2013-02-11 SMS. + * Free old G.unipath_filename storage, if not already + * done (G.unipath_filename == G.filename_full). + */ + if ((G.unipath_filename != NULL) && + (G.unipath_filename != G.filename_full)) + { + izu_free( G.unipath_filename); + } + G.unipath_filename = NULL; + #else /* def UNICODE_SUPPORT */ if (length == 0) { @@ -3284,7 +3315,7 @@ int do_string(__G__ length, option) /* return PK-type error code */ return PK_COOL; } /* Allocate new extra field storage, and fill it. */ - if ((G.extra_field = (uch *)malloc(length)) == (uch *)NULL) { + if ((G.extra_field = (uch *)izu_malloc(length)) == (uch *)NULL) { Info(slide, 0x401, ((char *)slide, LoadFarString(ExtraFieldTooLong), length)); /* cur_zipfile_bufstart already takes account of extra_bytes, @@ -3321,6 +3352,8 @@ int do_string(__G__ length, option) /* return PK-type error code */ error = PK_WARN; } #ifdef UNICODE_SUPPORT + +#if 0 /* See case DS_FN:, above. */ /* 2013-02-11 SMS. * Free old G.unipath_filename storage, if not already * done (G.unipath_filename == G.filename_full). @@ -3331,12 +3364,15 @@ int do_string(__G__ length, option) /* return PK-type error code */ izu_free( G.unipath_filename); } G.unipath_filename = NULL; +#endif /* 0 */ + if (G.UzO.U_flag < 2) { /* check if GPB11 (General Purpuse Bit 11) is set indicating the standard path and comment are UTF-8 */ if (G.pInfo->GPFIsUTF8) { /* if GPB11 set then filename_full is untruncated UTF-8 */ - if (!(G.unipath_filename = malloc(strlen(G.filename_full)+1))) + if (!(G.unipath_filename = + izu_malloc(strlen(G.filename_full)+1))) return PK_MEM; strcpy(G.unipath_filename, G.filename_full); } else { @@ -3401,9 +3437,9 @@ int do_string(__G__ length, option) /* return PK-type error code */ } # ifdef WIN32_WIDE # ifdef DYNAMIC_WIDE_NAME - /* 2013-02-12 SMS. - * Free old G.unipath_widefilename storage. - */ + /* 2013-02-12 SMS. + * Free old G.unipath_widefilename storage. + */ if (G.unipath_widefilename != NULL) { izu_free( G.unipath_widefilename); @@ -3415,10 +3451,15 @@ int do_string(__G__ length, option) /* return PK-type error code */ if (G.has_win32_wide) { if (G.unipath_filename) # ifdef DYNAMIC_WIDE_NAME + { /* Get wide path from UTF-8 */ - G.unipath_widefilename = utf8_to_wchar_string(G.unipath_filename); + G.unipath_widefilename = + utf8_to_wchar_string( G.unipath_filename); + } else - G.unipath_widefilename = utf8_to_wchar_string(G.filename); + { + G.unipath_widefilename = utf8_to_wchar_string( G.filename); + } # else /* def DYNAMIC_WIDE_NAME */ /* Get wide path from UTF-8 */ utf8_to_wchar_string( G.unipath_widefilename, @@ -3469,7 +3510,8 @@ int do_string(__G__ length, option) /* return PK-type error code */ izu_free(G.filenotes[G.filenote_slot]); /* should not happen */ G.filenotes[G.filenote_slot] = NULL; if (tmp_fnote[0]) { - if (!(G.filenotes[G.filenote_slot] = malloc(strlen(tmp_fnote)+1))) + if (!(G.filenotes[G.filenote_slot] = + izu_malloc(strlen(tmp_fnote)+1))) return PK_MEM; strcpy(G.filenotes[G.filenote_slot], tmp_fnote); } diff --git a/memdiag.c b/memdiag.c index e8dc260..a0f4457 100644 --- a/memdiag.c +++ b/memdiag.c @@ -30,6 +30,7 @@ void izu_md_check( void) md_ptr_t mdp; int i; int idd = 0; + unsigned char uc; mdp = &md_ht; while ((mdp = mdp->fwd) != &md_ht) @@ -39,35 +40,35 @@ void izu_md_check( void) /* Verify contents of beginning fill region. */ for (i = 0; i < MD_FILL_BEG_SIZE; i++) { - if (((unsigned char *)((unsigned char *)mdp)+ (sizeof md_ht))[ i] != - MD_FILL_BEG_FILL) + uc = ((unsigned char *)((unsigned char *)mdp)+ (sizeof md_ht))[ i]; + + if (uc != MD_FILL_BEG_FILL) { if (idd == 0) { idd = 1; fprintf( stderr, " mdp = %08x , siz = %8ld.\n", mdp, mdp->siz); } - fprintf( stderr, " bf[%d] = %02x.\n", - i, - ((unsigned char *)((unsigned char *)mdp)+ (sizeof md_ht))[ i]); + fprintf( stderr, " bf[%d] = %02x >%c<\n", + i, uc, (isprint( uc) ? uc : '.')); } } /* Verify contents of ending fill region. */ for (i = 0; i < MD_FILL_END_SIZE; i++) { - if (((unsigned char *)((unsigned char *)mdp)+ (sizeof md_ht)+ - MD_FILL_BEG_SIZE+ mdp->siz)[ i] != MD_FILL_END_FILL) + uc = ((unsigned char *)((unsigned char *)mdp)+ (sizeof md_ht)+ + MD_FILL_BEG_SIZE+ mdp->siz)[ i]; + + if (uc != MD_FILL_END_FILL) { if (idd == 0) { idd = 1; fprintf( stderr, " mdp = %08x , siz = %8ld.\n", mdp, mdp->siz); } - fprintf( stderr, " ef[%d] = %02x.\n", - i, - ((unsigned char *)((unsigned char *)mdp)+ (sizeof md_ht)+ - MD_FILL_BEG_SIZE+ mdp->siz)[ i]); + fprintf( stderr, " ef[%d] = %02x >%c<\n", + i, uc, (isprint( uc) ? uc : '.')); } } } diff --git a/unix/unix.c b/unix/unix.c index faf72d2..d839c18 100644 --- a/unix/unix.c +++ b/unix/unix.c @@ -2450,7 +2450,11 @@ void charset_to_intern(char *string, char *from_charset) d = buf = izu_malloc(buflen + 1); if (d) { - memset( buf, 0, buflen); + /* 2017-11-29 Rene Freingruber, SMS. + * Was using buflen, ignoring last byte. Next strcpy() was + * strncpy() with a bad maxchar parameter (buflen). + */ + memset( buf, 0, (buflen+ 1)); /* 2015-02-12 William Robinet, SMS. CVE-2015-1315. * Added FILNAMSIZ check to avoid buffer overflow. Better would @@ -2459,7 +2463,7 @@ void charset_to_intern(char *string, char *from_charset) if ((iconv(cd, &s, &slen, &d, &dlen) != (size_t)-1) && (strlen(buf) < FILNAMSIZ)) { - strncpy(string, buf, buflen); + strcpy(string, buf); } izu_free(buf); } diff --git a/unzpriv.h b/unzpriv.h index 00ced35..1361f34 100644 --- a/unzpriv.h +++ b/unzpriv.h @@ -779,10 +779,10 @@ #ifdef MEMDIAG -void izu_free( void *ptr); -void *izu_malloc( size_t siz); -void *izu_realloc( void *ptr, size_t siz); -void izu_md_check( void); +extern void izu_free( void *ptr); +extern void *izu_malloc( size_t siz); +extern void *izu_realloc( void *ptr, size_t siz); +extern void izu_md_check( void); #else /* def MEMDIAG */ # define izu_free free # define izu_malloc malloc @@ -1044,8 +1044,8 @@ void izu_md_check( void); # define INT_16BIT /* on 16-bit systems int size is 16 bits */ # endif #else -# define nearmalloc malloc -# define nearfree free +# define nearmalloc izu_malloc +# define nearfree izu_free # if (!defined(__IBMC__) || !defined(OS2)) # ifndef near # define near @@ -1155,8 +1155,8 @@ void izu_md_check( void); #else # define zfstrcpy(dest, src) strcpy((dest), (src)) # define zfstrcmp(s1, s2) strcmp((s1), (s2)) -# define zfmalloc malloc -# define zffree(x) free(x) +# define zfmalloc izu_malloc +# define zffree(x) izu_free(x) # ifdef QDOS # define LoadFarString(x) Qstrfix(x) /* fix up _ for '.' */ # define LoadFarStringSmall(x) Qstrfix(x) diff --git a/unzvers.h b/unzvers.h index 2043282..fb324aa 100644 --- a/unzvers.h +++ b/unzvers.h @@ -27,8 +27,8 @@ # endif # ifdef BETA -# define UZ_BETALEVEL "c22-BETA" -# define UZ_VERSION_DATE "2017-06-08" /* Internal beta version. */ +# define UZ_BETALEVEL "c23-BETA" +# define UZ_VERSION_DATE "2017-12-08" /* Internal beta version. */ # else # define UZ_BETALEVEL "" # define UZ_VERSION_DATE "2017-XX-XX" /* Official release version. */ @@ -42,7 +42,7 @@ # define UZ_PATCHLEVEL 0 -# define UZ_VER_STRING "6.1c22" /* Sync with Version numbers! */ +# define UZ_VER_STRING "6.1c23" /* Sync with Version numbers! */ # ifndef IZ_COMPANY_NAME # define IZ_COMPANY_NAME "Info-ZIP" diff --git a/vms/vms.c b/vms/vms.c index 4b71726..57106a7 100644 --- a/vms/vms.c +++ b/vms/vms.c @@ -225,8 +225,6 @@ static int (*_close_routine)(__GPRO); static int _read_link_rms(__GPRO__ int byte_count, char *link_text_buf); #endif /* def SYMLINKS */ -static void init_buf_ring(void); -static void set_default_datetime_XABs(__GPRO); static int create_default_output(__GPRO); static int create_rms_output(__GPRO); static int create_qio_output(__GPRO); @@ -4674,8 +4672,8 @@ static void adj_file_name_ods5(__GPRO__ char *dest, char *src) -#define FN_MASK 7 -#define USE_DEFAULT (FN_MASK+1) +#define FN_MASK 7 +#define RENAMED (FN_MASK+1) /* * Checkdir function codes: @@ -4683,7 +4681,7 @@ static void adj_file_name_ods5(__GPRO__ char *dest, char *src) * INIT - get ready for "filename" * APPEND_DIR - append pathcomp * APPEND_NAME - append filename - * APPEND_NAME | USE_DEFAULT - expand filename using collected path + * APPEND_NAME | RENAMED - expand filename using collected path * GETPATH - return resulting filespec * END - free dynamically allocated space prior to program exit */ @@ -4733,9 +4731,9 @@ int mapname(__G__ renamed) return (error & ~MPN_MASK) | MPN_ERR_SKIP; } - if ( renamed ) + if (renamed) { - if ( !(error = checkdir(__G__ pathcomp, APPEND_NAME | USE_DEFAULT)) ) + if (!(error = checkdir(__G__ pathcomp, APPEND_NAME | RENAMED))) strcpy(G.filename, pathcomp); return error; } @@ -4866,7 +4864,9 @@ int mapname(__G__ renamed) return error; } - /* can create path as long as not just freshening, or if user told us */ + /* Can create path, if not just freshening, or if user told us. + * On VMS, "user told us" = RENAMED, which is handled in checkdir(). + */ G.create_dirs = !uO.fflag; created_dir = FALSE; /* not yet */ @@ -5008,6 +5008,93 @@ int mapname(__G__ renamed) +static int create_dir( dir_spec) + /* Returns: + * Zero: No error. (Directory created or already existed.) + * Non-zero: Directory creation failed. + * + * 2017-10-07 SMS. New. + * Disabled the old code to save a created dir name, and then skip + * dir creation if the same dir spec recurs. The fix in checkdir() + * to stop creating nonexistent dirs in freshen mode requires + * testing for dir existence, so now this function won't be invoked + * repeatedly for the same dir spec. (Unless someone fiddles with a + * dir mid-job, in which case always checking the dirs should work + * better. Testing with an UnZip kit on an Alpha XP1000 showed no + * reliable performance difference between pre- and post-fix code. + * Post-fix, the disabled code (DIR_TEST_OPT) is pointless.) + */ + char *dir_spec; +{ + int sts; + +#ifdef DIR_TEST_OPT + + /* Retained for historical interest only, I hope. 2017-10-07 SMS. */ + + /* Previously created directory (initialized to impossible dir. spec.) */ + static char dir_spec_prev[ FILNAMSIZ] = "\t"; + + if (STRICMP( dir_spec_prev, dir_spec) == 0) + { /* Previously created this directory. */ + return 0; + } +#endif /* def DIR_TEST_OPT */ + + sts = mkdir( dir_spec, 0); + if (sts == 0) + { + created_dir = TRUE; + } + else if (errno == EEXIST) + { + sts = 0; /* Good enough, although unlikely. */ + } + +#ifdef DIR_TEST_OPT + if (sts == 0) + { + strcpy( dir_spec_prev, dir_spec); /* Save created dir spec. */ + } +#endif /* def DIR_TEST_OPT */ + + return sts; + +} /* end function create_dir() */ + + + +static int test_dir_exists( dir_spec) + /* Returns: + * Zero: Directory does not exist.) + * Non-zero: Directory exists. + */ + char *dir_spec; +{ + int sts; + struct FAB fab; + struct NAMX_STRUCT nam; + + fab = cc$rms_fab; /* Initialize FAB. */ + nam = CC_RMS_NAMX; /* Initialize NAM[L]. */ + fab.FAB_NAMX = &nam; /* Point FAB to NAM[L]. */ + + NAMX_DNA_FNA_SET( fab) + FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNA = PATH_DEFAULT; + FAB_OR_NAML(fab, nam).FAB_OR_NAML_DNS = strlen( PATH_DEFAULT); + FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNA = dir_spec; + FAB_OR_NAML(fab, nam).FAB_OR_NAML_FNS = strlen( dir_spec); + nam.NAMX_ESA = NULL; + nam.NAMX_ESS = 0; + + sts = sys$parse( &fab); + + return ((sts & STS$M_SEVERITY) == STS$K_SUCCESS); + +} /* end function test_dir_exists() */ + + + int checkdir(__G__ pathcomp, fcn) /* * returns: @@ -5018,22 +5105,29 @@ int checkdir(__G__ pathcomp, fcn) * exists and is not a directory, but is supposed to be * MPN_ERR_TOOLONG - path is too long * MPN_NOMEM - can't allocate memory for filename buffers + * + * In unix/unix.c:checkdir(), APPEND_DIR causes directory creation, as + * the Unix directory path is accumulated. (Some (older?) Unix mkdir() + * implementations fail with ENOENT if the parent directory does not + * already exist.) + * + * Here, APPEND_DIR accumulates a VMS directory spec, but APPEND_NAME + * causes the actual directory creation. On VMS, mkdir() can create the + * whole directory stack at one time. */ __GDEF char *pathcomp; int fcn; { - int function=fcn & FN_MASK; - static char pathbuf[FILNAMSIZ]; + int function = fcn & FN_MASK; /* Strip flags from function code. */ + static char pathbuf[FILNAMSIZ]; /* Accumulated VMS path. */ - /* previously created directory (initialized to impossible dir. spec.) */ - static char lastdir[FILNAMSIZ] = "\t"; static char *pathptr = pathbuf; /* For debugger */ static char *devptr, *dirptr; static int devlen, dirlen; static int root_dirlen; - static char *end; + static char *end; /* Ptr to current end of pathbuf. */ static int first_comp, root_has_dir; static int rootlen=0; static char *rootend; @@ -5042,19 +5136,20 @@ int checkdir(__G__ pathcomp, fcn) struct FAB fab; struct NAMX_STRUCT nam; - /************ *** ROOT *** ************/ #if (!defined(SFX) || defined(SFX_EXDIR)) + if (function == ROOT) - { /* Assume VMS root spec */ + { /* Assume VMS root dir spec. */ /* 2006-01-20 SMS. - Changed to use sys$parse() instead of sys$filescan() for analysis - of the user-specified destination directory. Previously, various - values behaved badly, without complaint, e.g. "-d sys$scratch". - */ + * Changed to use sys$parse() instead of sys$filescan() for + * analysis of the user-specified destination directory. + * Previously, various values behaved badly, without complaint, + * e.g. "-d sys$scratch". + */ /* If the root path has already been set, return immediately. */ if (rootlen > 0) @@ -5139,22 +5234,26 @@ int checkdir(__G__ pathcomp, fcn) devlen = nam.NAMX_L_DIR - nam.NAMX_ESA; - /* If directory not found, then create it. */ + /* If directory not found, then create it, if allowed. */ if (status == RMS$_DNF) { - if (status = mkdir(nam.NAMX_ESA, 0)) + if (!G.create_dirs) + { + /* Skip (or treat as stored file). */ + return MPN_INF_SKIP; + } + else if (mkdir( nam.NAMX_ESA, 0)) { Info(slide, 1, ((char *)slide, - "Can not create destination directory: %s\n", - FnFilter1(nam.NAMX_ESA))); - - /* path didn't exist, tried to create, and failed. */ + "Can not create destination directory: %s\n", + FnFilter1(nam.NAMX_ESA))); + /* Path didn't exist, tried to create, and failed. */ return MPN_ERR_SKIP; } } /* Save the (valid) device:[directory] spec. */ - strcpy(pathbuf, nam.NAMX_ESA); + strcpy( pathbuf, nam.NAMX_ESA); /* At this point, the true destination is known. If the user * supplied an invalid destination directory, the default @@ -5199,8 +5298,8 @@ int checkdir(__G__ pathcomp, fcn) first_comp = !root_has_dir; return MPN_OK; } -#endif /* !SFX || SFX_EXDIR */ +#endif /* !SFX || SFX_EXDIR */ /************ *** INIT *** @@ -5218,8 +5317,11 @@ int checkdir(__G__ pathcomp, fcn) } end = rootend; first_comp = !root_has_dir; + + /* Reset dirlen. If ROOT set, change terminator (from "]") to ".". */ if ( dirlen = root_dirlen ) end[-1] = '.'; + *end = '\0'; return MPN_OK; } @@ -5228,11 +5330,12 @@ int checkdir(__G__ pathcomp, fcn) /****************** *** APPEND_DIR *** ******************/ + if ( function == APPEND_DIR ) { int cmplen; - cmplen = strlen(pathcomp); + cmplen = strlen( pathcomp); if ( first_comp ) { @@ -5270,11 +5373,13 @@ int checkdir(__G__ pathcomp, fcn) /******************* *** APPEND_NAME *** *******************/ + if ( function == APPEND_NAME ) - { - if ( fcn & USE_DEFAULT ) - { /* Expand renamed filename using collected path, return - * at pathcomp */ + { /* Expand filename using collected path, return at pathcomp. + * Create directories as needed, if allowed (not -f/--freshen). + */ + if (fcn & RENAMED) + { /* Renamed (user-specified) filename, so always create dirs. */ fab = cc$rms_fab; /* Initialize FAB. */ nam = CC_RMS_NAMX; /* Initialize NAM[L]. */ fab.FAB_NAMX = &nam; /* Point FAB to NAM[L]. */ @@ -5288,65 +5393,85 @@ int checkdir(__G__ pathcomp, fcn) nam.NAMX_ESA = pathcomp; /* (Great design. ---v. SMS.) */ nam.NAMX_ESS = NAMX_MAXRSS; /* Assume large enough. */ - if (!OK(status = sys$parse(&fab)) && status == RMS$_DNF ) - /* Directory not found: */ - { /* ... try to create it */ + status = sys$parse( &fab); + if (status == RMS$_DNF) + { /* 2017-10-07 SMS. Removed redundant "!OK(status) &&" + * from test. An otherwise bad user-specified file spec + * will generate an error ("Cannot create ($create) + * output file") when its use is attempted. Good + * enough? + */ + /* Directory not found. Try to create it, if allowed. + * Here, RENAMED, it's always allowed. + */ char save; char *dirend; int mkdir_failed; dirend = (char*)nam.NAMX_L_DIR + nam.NAMX_B_DIR; - save = *dirend; - *dirend = '\0'; - if ( (mkdir_failed = mkdir(nam.NAMX_L_DEV, 0)) && - errno == EEXIST ) - mkdir_failed = 0; - *dirend = save; - if ( mkdir_failed ) - return 3; - created_dir = TRUE; - } /* if (sys$parse... */ + save = *dirend; /* Save real name char. */ + *dirend = '\0'; /* Temporarily NUL-terminate dev:[dir] spec. */ + + mkdir_failed = create_dir( nam.NAMX_L_DEV); + *dirend = save; /* Restore real name char. */ + if (mkdir_failed) + { + return MPN_INF_SKIP; + } + } /* end:if RMS$_DNF */ pathcomp[nam.NAMX_ESL] = '\0'; return MPN_OK; - } /* if (USE_DEFAULT) */ + } /* end:if RENAMED */ else - { + { /* Normal (not renamed) filename. Create dirs, if allowed. */ + int dir_exists; + *end = '\0'; - if ( dirlen ) + if (dirlen > 0) { - dirptr[dirlen-1] = ']'; /* Close directory */ + dirptr[dirlen-1] = ']'; /* Close (non-null) directory spec. */ + dir_exists = test_dir_exists( pathbuf); - /* - * Try to create the target directory. - * Don't waste time creating directory that was created - * last time. - */ - if ( STRICMP(lastdir, pathbuf) ) + /* Try to create the target dir, if required and allowed. */ + if (!dir_exists) { - mkdir_failed = 0; - if ( mkdir(pathbuf, 0) ) + if (!G.create_dirs) { - if ( errno != EEXIST ) - mkdir_failed = 1; /* Mine for GETPATH */ + /* Skip (or treat as stored file). */ + return MPN_INF_SKIP; } else - created_dir = TRUE; - strcpy(lastdir, pathbuf); + { + mkdir_failed = create_dir( pathbuf); + } } } else - { /* + { /* (dirlen <= 0) * Target directory unspecified. - * Try to create "SYS$DISK:[]" + * Try to create "SYS$DISK:[]", if required and allowed. */ - if ( strcmp(lastdir, PATH_DEFAULT) ) + dir_exists = test_dir_exists( PATH_DEFAULT); + + /* Try to create the target dir, if required and allowed. */ + if (!dir_exists) { - strcpy(lastdir, PATH_DEFAULT); - mkdir_failed = 0; - if ( mkdir(lastdir, 0) && errno != EEXIST ) - mkdir_failed = 1; /* Mine for GETPATH */ + if (!G.create_dirs) + { + /* Skip (or treat as stored file). */ + return MPN_INF_SKIP; + } + else + { + mkdir_failed = create_dir( PATH_DEFAULT); + } } } + if (mkdir_failed) + { + return MPN_INF_SKIP; + } + if ( strlen(pathcomp) + (end-pathbuf) > NAMX_MAXRSS ) return MPN_INF_TRUNC; strcpy(end, pathcomp); @@ -5355,10 +5480,10 @@ int checkdir(__G__ pathcomp, fcn) } } - /*************** *** GETPATH *** ***************/ + if ( function == GETPATH ) { if ( mkdir_failed ) @@ -5368,10 +5493,10 @@ int checkdir(__G__ pathcomp, fcn) return MPN_OK; } - /*********** *** END *** ***********/ + if ( function == END ) { Trace((stderr, "checkdir(): nothing to free...\n")); @@ -5380,7 +5505,6 @@ int checkdir(__G__ pathcomp, fcn) } return MPN_INVALID; /* should never reach */ - } diff --git a/win32/win32.c b/win32/win32.c index 521a6e7..f6b56ac 100644 --- a/win32/win32.c +++ b/win32/win32.c @@ -1,5 +1,5 @@ /* - Copyright (c) 1990-2015 Info-ZIP. All rights reserved. + Copyright (c) 1990-2017 Info-ZIP. All rights reserved. See the accompanying file LICENSE, version 2009-Jan-02 or later (the contents of which are also included in unzip.h) for terms of use. @@ -1218,7 +1218,7 @@ void close_outfile(__G) return; } - if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + if ((slnk_entry = (slinkentry *)izu_malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); @@ -1255,7 +1255,7 @@ void close_outfile(__G) Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); - free(slnk_entry); + izu_free(slnk_entry); fclose(G.outfile); return; } @@ -1447,7 +1447,7 @@ void close_outfile(__G) return; } - if ((slnk_entry = (slinkentry *)malloc(slnk_entrysize)) == NULL) { + if ((slnk_entry = (slinkentry *)izu_malloc(slnk_entrysize)) == NULL) { Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed: no mem\n", FnFilter1(G.filename))); @@ -1481,7 +1481,7 @@ void close_outfile(__G) Info(slide, 0x201, ((char *)slide, "warning: symbolic link (%s) failed\n", FnFilter1(G.filename))); - free(slnk_entry); + izu_free(slnk_entry); fclose(G.outfile); return; } @@ -3822,7 +3822,6 @@ int checkdirw(__G__ pathcompw, flag) return MPN_ERR_TOOLONG; } { - char *buildpathFAT = wchar_to_local_string(G.buildpathFATw, G.unicode_escape_all); int i = MKDIRW(G.buildpathFATw, 0777); if (i == -1) { /* create the directory */ Info(slide, 1, ((char *)slide, @@ -3838,7 +3837,7 @@ int checkdirw(__G__ pathcompw, flag) return MPN_ERR_SKIP; } G.created_dir = TRUE; - } + } } else if (!S_ISDIR(G.statbuf.st_mode)) { Info(slide, 1, ((char *)slide, "checkdir(2) error: %s exists but is not directory\n\ @@ -4114,7 +4113,6 @@ int checkdirw(__G__ pathcompw, flag) /* file exists, or need 2+ subdir levels */ /* 2013-03-12 SMS. * izu_free(pathcomp); - * Should be "izu_free(pathcompw);"??? */ return MPN_ERR_SKIP; } @@ -4575,10 +4573,10 @@ int zstat_win32w(__W32STAT_GLOBALS__ const wchar_t *pathw, z_stat *buf) if ((flags != INVALID_FILE_ATTRIBUTES) && (flags & FILE_ATTRIBUTE_DIRECTORY)) { # ifdef Tracing - char *path = wchar_to_local_string((wchar_t *)pathw, G.unicode_escape_all); + char *path = wchar_to_local_string((wchar_t *)pathw, + G.unicode_escape_all); Trace((stderr, "\nstat(\"%s\",...) failed on existing directory\n", - - FnFilter1(path))); + FnFilter1(path))); izu_free(path); # endif /* def Tracing */ memset(buf, 0, sizeof(z_stat)); @@ -4746,6 +4744,7 @@ char *wide_to_local_string(wide_string, escape_all) if (max_bytes < MB_CUR_MAX) max_bytes = MB_CUR_MAX; + /* Over-allocate a working buffer. */ if ((buffer = (char *)izu_malloc(wsize * max_bytes + 1)) == NULL) { return NULL; } @@ -4799,6 +4798,8 @@ char *wide_to_local_string(wide_string, escape_all) izu_free(escape_string); } } + + /* Re-allocate a buffer with the final size. */ if ((local_string = (char *)izu_realloc( buffer, strlen(buffer) + 1)) == NULL) { izu_free(buffer); @@ -5027,7 +5028,7 @@ int symlinkw( const char *target, const wchar_t *namew, int is_dir) { sts = GetLastError(); } - free( targetw); + izu_free( targetw); } return sts; } diff --git a/zip-comment.txt b/zip-comment.txt index cdabaa3..e8d16fe 100644 --- a/zip-comment.txt +++ b/zip-comment.txt @@ -1,8 +1,18 @@ -Info-Zip UnZip -- Source kit. Version 6.1c22 (pre-BETA) 2017-06-08. +Info-Zip UnZip -- Source kit. Version 6.1c23 (pre-BETA) 2017-12-11. -See enclosed files INSTALL, LICENSE, and README. For information on -Info-Zip UnZip and Zip: +Kit contents copyright (c) 1990-2017 Info-ZIP. All rights reserved. + License terms in: LICENSE +Exceptions: + aes_wg/ Copyright (c) 2002, Dr Brian Gladman. All rights reserved. + License terms in: aes_wg/aes.h + bzip2/ Copyright (C) 1996-2010 Julian R Seward. All rights reserved. + License terms in: bzip2/LICENSE + szip/ Public domain, Igor Pavlov. + +See also enclosed files INSTALL and README. + +For information on Info-Zip UnZip and Zip: http://info-zip.org/ http://sourceforge.net/projects/infozip/ Executables for some released versions may also be available: -- 2.7.4