160b4ad09SPeter Avalos /*-
26b384f39SPeter Avalos  * Copyright (c) 2004-2013 Tim Kientzle
36b384f39SPeter Avalos  * Copyright (c) 2011-2012,2014 Michihiro NAKAJIMA
46b384f39SPeter Avalos  * Copyright (c) 2013 Konrad Kleine
560b4ad09SPeter Avalos  * All rights reserved.
660b4ad09SPeter Avalos  *
760b4ad09SPeter Avalos  * Redistribution and use in source and binary forms, with or without
860b4ad09SPeter Avalos  * modification, are permitted provided that the following conditions
960b4ad09SPeter Avalos  * are met:
1060b4ad09SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
1160b4ad09SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
1260b4ad09SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
1360b4ad09SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
1460b4ad09SPeter Avalos  *    documentation and/or other materials provided with the distribution.
1560b4ad09SPeter Avalos  *
1660b4ad09SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
1760b4ad09SPeter Avalos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1860b4ad09SPeter Avalos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1960b4ad09SPeter Avalos  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
2060b4ad09SPeter Avalos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2160b4ad09SPeter Avalos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2260b4ad09SPeter Avalos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2360b4ad09SPeter Avalos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2460b4ad09SPeter Avalos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2560b4ad09SPeter Avalos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2660b4ad09SPeter Avalos  */
2760b4ad09SPeter Avalos 
2860b4ad09SPeter Avalos #include "archive_platform.h"
299c82a63eSPeter Avalos __FBSDID("$FreeBSD: head/lib/libarchive/archive_read_support_format_zip.c 201102 2009-12-28 03:11:36Z kientzle $");
3060b4ad09SPeter Avalos 
316b384f39SPeter Avalos /*
326b384f39SPeter Avalos  * The definitive documentation of the Zip file format is:
336b384f39SPeter Avalos  *   http://www.pkware.com/documents/casestudies/APPNOTE.TXT
346b384f39SPeter Avalos  *
356b384f39SPeter Avalos  * The Info-Zip project has pioneered various extensions to better
366b384f39SPeter Avalos  * support Zip on Unix, including the 0x5455 "UT", 0x5855 "UX", 0x7855
376b384f39SPeter Avalos  * "Ux", and 0x7875 "ux" extensions for time and ownership
386b384f39SPeter Avalos  * information.
396b384f39SPeter Avalos  *
406b384f39SPeter Avalos  * History of this code: The streaming Zip reader was first added to
416b384f39SPeter Avalos  * libarchive in January 2005.  Support for seekable input sources was
426b384f39SPeter Avalos  * added in Nov 2011.  Zip64 support (including a significant code
436b384f39SPeter Avalos  * refactoring) was added in 2014.
446b384f39SPeter Avalos  */
456b384f39SPeter Avalos 
4660b4ad09SPeter Avalos #ifdef HAVE_ERRNO_H
4760b4ad09SPeter Avalos #include <errno.h>
4860b4ad09SPeter Avalos #endif
4960b4ad09SPeter Avalos #ifdef HAVE_STDLIB_H
5060b4ad09SPeter Avalos #include <stdlib.h>
5160b4ad09SPeter Avalos #endif
5260b4ad09SPeter Avalos #ifdef HAVE_ZLIB_H
5360b4ad09SPeter Avalos #include <zlib.h>
5460b4ad09SPeter Avalos #endif
55085658deSDaniel Fojt #ifdef HAVE_BZLIB_H
56085658deSDaniel Fojt #include <bzlib.h>
57085658deSDaniel Fojt #endif
58085658deSDaniel Fojt #ifdef HAVE_LZMA_H
59085658deSDaniel Fojt #include <lzma.h>
60085658deSDaniel Fojt #endif
61*50f8aa9cSAntonio Huete Jimenez #ifdef HAVE_ZSTD_H
62*50f8aa9cSAntonio Huete Jimenez #include <zstd.h>
63*50f8aa9cSAntonio Huete Jimenez #endif
6460b4ad09SPeter Avalos 
6560b4ad09SPeter Avalos #include "archive.h"
666b384f39SPeter Avalos #include "archive_digest_private.h"
676b384f39SPeter Avalos #include "archive_cryptor_private.h"
6859bf7050SPeter Avalos #include "archive_endian.h"
6960b4ad09SPeter Avalos #include "archive_entry.h"
70c09f92d2SPeter Avalos #include "archive_entry_locale.h"
716b384f39SPeter Avalos #include "archive_hmac_private.h"
7260b4ad09SPeter Avalos #include "archive_private.h"
7359bf7050SPeter Avalos #include "archive_rb.h"
7460b4ad09SPeter Avalos #include "archive_read_private.h"
75085658deSDaniel Fojt #include "archive_ppmd8_private.h"
7660b4ad09SPeter Avalos 
779c82a63eSPeter Avalos #ifndef HAVE_ZLIB_H
789c82a63eSPeter Avalos #include "archive_crc32.h"
799c82a63eSPeter Avalos #endif
809c82a63eSPeter Avalos 
81c09f92d2SPeter Avalos struct zip_entry {
8259bf7050SPeter Avalos 	struct archive_rb_node	node;
836b384f39SPeter Avalos 	struct zip_entry	*next;
84c09f92d2SPeter Avalos 	int64_t			local_header_offset;
85c09f92d2SPeter Avalos 	int64_t			compressed_size;
86c09f92d2SPeter Avalos 	int64_t			uncompressed_size;
87c09f92d2SPeter Avalos 	int64_t			gid;
88c09f92d2SPeter Avalos 	int64_t			uid;
89d4d8193eSPeter Avalos 	struct archive_string	rsrcname;
90c09f92d2SPeter Avalos 	time_t			mtime;
91c09f92d2SPeter Avalos 	time_t			atime;
92c09f92d2SPeter Avalos 	time_t			ctime;
93c09f92d2SPeter Avalos 	uint32_t		crc32;
94c09f92d2SPeter Avalos 	uint16_t		mode;
956b384f39SPeter Avalos 	uint16_t		zip_flags; /* From GP Flags Field */
966b384f39SPeter Avalos 	unsigned char		compression;
976b384f39SPeter Avalos 	unsigned char		system; /* From "version written by" */
986b384f39SPeter Avalos 	unsigned char		flags; /* Our extra markers. */
996b384f39SPeter Avalos 	unsigned char		decdat;/* Used for Decryption check */
1006b384f39SPeter Avalos 
1016b384f39SPeter Avalos 	/* WinZip AES encryption extra field should be available
1026b384f39SPeter Avalos 	 * when compression is 99. */
1036b384f39SPeter Avalos 	struct {
1046b384f39SPeter Avalos 		/* Vendor version: AE-1 - 0x0001, AE-2 - 0x0002 */
1056b384f39SPeter Avalos 		unsigned	vendor;
1066b384f39SPeter Avalos #define AES_VENDOR_AE_1	0x0001
1076b384f39SPeter Avalos #define AES_VENDOR_AE_2	0x0002
1086b384f39SPeter Avalos 		/* AES encryption strength:
1096b384f39SPeter Avalos 		 * 1 - 128 bits, 2 - 192 bits, 2 - 256 bits. */
1106b384f39SPeter Avalos 		unsigned	strength;
1116b384f39SPeter Avalos 		/* Actual compression method. */
1126b384f39SPeter Avalos 		unsigned char	compression;
1136b384f39SPeter Avalos 	}			aes_extra;
114c09f92d2SPeter Avalos };
115c09f92d2SPeter Avalos 
1166b384f39SPeter Avalos struct trad_enc_ctx {
1176b384f39SPeter Avalos 	uint32_t	keys[3];
1186b384f39SPeter Avalos };
1196b384f39SPeter Avalos 
1206b384f39SPeter Avalos /* Bits used in zip_flags. */
1216b384f39SPeter Avalos #define ZIP_ENCRYPTED	(1 << 0)
1226b384f39SPeter Avalos #define ZIP_LENGTH_AT_END	(1 << 3)
1236b384f39SPeter Avalos #define ZIP_STRONG_ENCRYPTED	(1 << 6)
1246b384f39SPeter Avalos #define ZIP_UTF8_NAME	(1 << 11)
1256b384f39SPeter Avalos /* See "7.2 Single Password Symmetric Encryption Method"
1266b384f39SPeter Avalos    in http://www.pkware.com/documents/casestudies/APPNOTE.TXT */
1276b384f39SPeter Avalos #define ZIP_CENTRAL_DIRECTORY_ENCRYPTED	(1 << 13)
1286b384f39SPeter Avalos 
1296b384f39SPeter Avalos /* Bits used in flags. */
1306b384f39SPeter Avalos #define LA_USED_ZIP64	(1 << 0)
1316b384f39SPeter Avalos #define LA_FROM_CENTRAL_DIRECTORY (1 << 1)
1326b384f39SPeter Avalos 
1336b384f39SPeter Avalos /*
1346b384f39SPeter Avalos  * See "WinZip - AES Encryption Information"
1356b384f39SPeter Avalos  *     http://www.winzip.com/aes_info.htm
1366b384f39SPeter Avalos  */
1376b384f39SPeter Avalos /* Value used in compression method. */
1386b384f39SPeter Avalos #define WINZIP_AES_ENCRYPTION	99
1396b384f39SPeter Avalos /* Authentication code size. */
1406b384f39SPeter Avalos #define AUTH_CODE_SIZE	10
1416b384f39SPeter Avalos /**/
1426b384f39SPeter Avalos #define MAX_DERIVED_KEY_BUF_SIZE	(AES_MAX_KEY_SIZE * 2 + 2)
1436b384f39SPeter Avalos 
14460b4ad09SPeter Avalos struct zip {
145c09f92d2SPeter Avalos 	/* Structural information about the archive. */
1466b384f39SPeter Avalos 	struct archive_string	format_name;
147c09f92d2SPeter Avalos 	int64_t			central_directory_offset;
148*50f8aa9cSAntonio Huete Jimenez 	int64_t			central_directory_offset_adjusted;
1496b384f39SPeter Avalos 	size_t			central_directory_entries_total;
1506b384f39SPeter Avalos 	size_t			central_directory_entries_on_this_disk;
1516b384f39SPeter Avalos 	int			has_encrypted_entries;
152c09f92d2SPeter Avalos 
153c09f92d2SPeter Avalos 	/* List of entries (seekable Zip only) */
154c09f92d2SPeter Avalos 	struct zip_entry	*zip_entries;
15559bf7050SPeter Avalos 	struct archive_rb_tree	tree;
156d4d8193eSPeter Avalos 	struct archive_rb_tree	tree_rsrc;
157c09f92d2SPeter Avalos 
1586b384f39SPeter Avalos 	/* Bytes read but not yet consumed via __archive_read_consume() */
159c09f92d2SPeter Avalos 	size_t			unconsumed;
160c09f92d2SPeter Avalos 
1616b384f39SPeter Avalos 	/* Information about entry we're currently reading. */
1626b384f39SPeter Avalos 	struct zip_entry	*entry;
16360b4ad09SPeter Avalos 	int64_t			entry_bytes_remaining;
16460b4ad09SPeter Avalos 
16560b4ad09SPeter Avalos 	/* These count the number of bytes actually read for the entry. */
16660b4ad09SPeter Avalos 	int64_t			entry_compressed_bytes_read;
16760b4ad09SPeter Avalos 	int64_t			entry_uncompressed_bytes_read;
16860b4ad09SPeter Avalos 
1698029ab02SPeter Avalos 	/* Running CRC32 of the decompressed data */
1708029ab02SPeter Avalos 	unsigned long		entry_crc32;
1716b384f39SPeter Avalos 	unsigned long		(*crc32func)(unsigned long, const void *,
1726b384f39SPeter Avalos 				    size_t);
1736b384f39SPeter Avalos 	char			ignore_crc32;
1748029ab02SPeter Avalos 
17560b4ad09SPeter Avalos 	/* Flags to mark progress of decompression. */
17660b4ad09SPeter Avalos 	char			decompress_init;
17760b4ad09SPeter Avalos 	char			end_of_entry;
17860b4ad09SPeter Avalos 
17960b4ad09SPeter Avalos 	unsigned char 		*uncompressed_buffer;
18060b4ad09SPeter Avalos 	size_t 			uncompressed_buffer_size;
181085658deSDaniel Fojt 
182085658deSDaniel Fojt #ifdef HAVE_ZLIB_H
18360b4ad09SPeter Avalos 	z_stream		stream;
18460b4ad09SPeter Avalos 	char			stream_valid;
18560b4ad09SPeter Avalos #endif
18660b4ad09SPeter Avalos 
187085658deSDaniel Fojt #if HAVE_LZMA_H && HAVE_LIBLZMA
188085658deSDaniel Fojt 	lzma_stream		zipx_lzma_stream;
189085658deSDaniel Fojt 	char            zipx_lzma_valid;
190085658deSDaniel Fojt #endif
191085658deSDaniel Fojt 
192085658deSDaniel Fojt #ifdef HAVE_BZLIB_H
193085658deSDaniel Fojt 	bz_stream		bzstream;
194085658deSDaniel Fojt 	char            bzstream_valid;
195085658deSDaniel Fojt #endif
196085658deSDaniel Fojt 
197*50f8aa9cSAntonio Huete Jimenez #if HAVE_ZSTD_H && HAVE_LIBZSTD
198*50f8aa9cSAntonio Huete Jimenez 	ZSTD_DStream	*zstdstream;
199*50f8aa9cSAntonio Huete Jimenez 	char            zstdstream_valid;
200*50f8aa9cSAntonio Huete Jimenez #endif
201*50f8aa9cSAntonio Huete Jimenez 
202085658deSDaniel Fojt 	IByteIn			zipx_ppmd_stream;
203085658deSDaniel Fojt 	ssize_t			zipx_ppmd_read_compressed;
204085658deSDaniel Fojt 	CPpmd8			ppmd8;
205085658deSDaniel Fojt 	char			ppmd8_valid;
206085658deSDaniel Fojt 	char			ppmd8_stream_failed;
207085658deSDaniel Fojt 
208c09f92d2SPeter Avalos 	struct archive_string_conv *sconv;
209c09f92d2SPeter Avalos 	struct archive_string_conv *sconv_default;
210c09f92d2SPeter Avalos 	struct archive_string_conv *sconv_utf8;
211c09f92d2SPeter Avalos 	int			init_default_conversion;
2126b384f39SPeter Avalos 	int			process_mac_extensions;
2136b384f39SPeter Avalos 
2146b384f39SPeter Avalos 	char			init_decryption;
2156b384f39SPeter Avalos 
2166b384f39SPeter Avalos 	/* Decryption buffer. */
217e95abc47Szrj 	/*
218e95abc47Szrj 	 * The decrypted data starts at decrypted_ptr and
219e95abc47Szrj 	 * extends for decrypted_bytes_remaining.  Decryption
220e95abc47Szrj 	 * adds new data to the end of this block, data is returned
221e95abc47Szrj 	 * to clients from the beginning.  When the block hits the
222e95abc47Szrj 	 * end of decrypted_buffer, it has to be shuffled back to
223e95abc47Szrj 	 * the beginning of the buffer.
224e95abc47Szrj 	 */
2256b384f39SPeter Avalos 	unsigned char 		*decrypted_buffer;
2266b384f39SPeter Avalos 	unsigned char 		*decrypted_ptr;
2276b384f39SPeter Avalos 	size_t 			decrypted_buffer_size;
2286b384f39SPeter Avalos 	size_t 			decrypted_bytes_remaining;
2296b384f39SPeter Avalos 	size_t 			decrypted_unconsumed_bytes;
2306b384f39SPeter Avalos 
2316b384f39SPeter Avalos 	/* Traditional PKWARE decryption. */
2326b384f39SPeter Avalos 	struct trad_enc_ctx	tctx;
2336b384f39SPeter Avalos 	char			tctx_valid;
2346b384f39SPeter Avalos 
235e95abc47Szrj 	/* WinZip AES decryption. */
2366b384f39SPeter Avalos 	/* Contexts used for AES decryption. */
2376b384f39SPeter Avalos 	archive_crypto_ctx	cctx;
2386b384f39SPeter Avalos 	char			cctx_valid;
2396b384f39SPeter Avalos 	archive_hmac_sha1_ctx	hctx;
2406b384f39SPeter Avalos 	char			hctx_valid;
2416b384f39SPeter Avalos 
2426b384f39SPeter Avalos 	/* Strong encryption's decryption header information. */
2436b384f39SPeter Avalos 	unsigned		iv_size;
2446b384f39SPeter Avalos 	unsigned		alg_id;
2456b384f39SPeter Avalos 	unsigned		bit_len;
2466b384f39SPeter Avalos 	unsigned		flags;
2476b384f39SPeter Avalos 	unsigned		erd_size;
2486b384f39SPeter Avalos 	unsigned		v_size;
2496b384f39SPeter Avalos 	unsigned		v_crc32;
2506b384f39SPeter Avalos 	uint8_t			*iv;
2516b384f39SPeter Avalos 	uint8_t			*erd;
2526b384f39SPeter Avalos 	uint8_t			*v_data;
25360b4ad09SPeter Avalos };
25460b4ad09SPeter Avalos 
2556b384f39SPeter Avalos /* Many systems define min or MIN, but not all. */
2566b384f39SPeter Avalos #define	zipmin(a,b) ((a) < (b) ? (a) : (b))
25760b4ad09SPeter Avalos 
258*50f8aa9cSAntonio Huete Jimenez #ifdef HAVE_ZLIB_H
259*50f8aa9cSAntonio Huete Jimenez static int
260*50f8aa9cSAntonio Huete Jimenez zip_read_data_deflate(struct archive_read *a, const void **buff,
261*50f8aa9cSAntonio Huete Jimenez 	size_t *size, int64_t *offset);
262*50f8aa9cSAntonio Huete Jimenez #endif
263*50f8aa9cSAntonio Huete Jimenez #if HAVE_LZMA_H && HAVE_LIBLZMA
264*50f8aa9cSAntonio Huete Jimenez static int
265*50f8aa9cSAntonio Huete Jimenez zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
266*50f8aa9cSAntonio Huete Jimenez 	size_t *size, int64_t *offset);
267*50f8aa9cSAntonio Huete Jimenez #endif
268*50f8aa9cSAntonio Huete Jimenez 
269085658deSDaniel Fojt /* This function is used by Ppmd8_DecodeSymbol during decompression of Ppmd8
270085658deSDaniel Fojt  * streams inside ZIP files. It has 2 purposes: one is to fetch the next
271085658deSDaniel Fojt  * compressed byte from the stream, second one is to increase the counter how
272085658deSDaniel Fojt  * many compressed bytes were read. */
273085658deSDaniel Fojt static Byte
ppmd_read(void * p)274085658deSDaniel Fojt ppmd_read(void* p) {
275085658deSDaniel Fojt 	/* Get the handle to current decompression context. */
276085658deSDaniel Fojt 	struct archive_read *a = ((IByteIn*)p)->a;
277085658deSDaniel Fojt 	struct zip *zip = (struct zip*) a->format->data;
278085658deSDaniel Fojt 	ssize_t bytes_avail = 0;
279085658deSDaniel Fojt 
280085658deSDaniel Fojt 	/* Fetch next byte. */
281085658deSDaniel Fojt 	const uint8_t* data = __archive_read_ahead(a, 1, &bytes_avail);
282085658deSDaniel Fojt 	if(bytes_avail < 1) {
283085658deSDaniel Fojt 		zip->ppmd8_stream_failed = 1;
284085658deSDaniel Fojt 		return 0;
285085658deSDaniel Fojt 	}
286085658deSDaniel Fojt 
287085658deSDaniel Fojt 	__archive_read_consume(a, 1);
288085658deSDaniel Fojt 
289085658deSDaniel Fojt 	/* Increment the counter. */
290085658deSDaniel Fojt 	++zip->zipx_ppmd_read_compressed;
291085658deSDaniel Fojt 
292085658deSDaniel Fojt 	/* Return the next compressed byte. */
293085658deSDaniel Fojt 	return data[0];
294085658deSDaniel Fojt }
295085658deSDaniel Fojt 
2966b384f39SPeter Avalos /* ------------------------------------------------------------------------ */
297c09f92d2SPeter Avalos 
298c09f92d2SPeter Avalos /*
2996b384f39SPeter Avalos   Traditional PKWARE Decryption functions.
300c09f92d2SPeter Avalos  */
3016b384f39SPeter Avalos 
3026b384f39SPeter Avalos static void
trad_enc_update_keys(struct trad_enc_ctx * ctx,uint8_t c)3036b384f39SPeter Avalos trad_enc_update_keys(struct trad_enc_ctx *ctx, uint8_t c)
304c09f92d2SPeter Avalos {
3056b384f39SPeter Avalos 	uint8_t t;
3066b384f39SPeter Avalos #define CRC32(c, b) (crc32(c ^ 0xffffffffUL, &b, 1) ^ 0xffffffffUL)
307c09f92d2SPeter Avalos 
3086b384f39SPeter Avalos 	ctx->keys[0] = CRC32(ctx->keys[0], c);
3096b384f39SPeter Avalos 	ctx->keys[1] = (ctx->keys[1] + (ctx->keys[0] & 0xff)) * 134775813L + 1;
3106b384f39SPeter Avalos 	t = (ctx->keys[1] >> 24) & 0xff;
3116b384f39SPeter Avalos 	ctx->keys[2] = CRC32(ctx->keys[2], t);
3126b384f39SPeter Avalos #undef CRC32
313d4d8193eSPeter Avalos }
314c09f92d2SPeter Avalos 
3156b384f39SPeter Avalos static uint8_t
trad_enc_decrypt_byte(struct trad_enc_ctx * ctx)316e95abc47Szrj trad_enc_decrypt_byte(struct trad_enc_ctx *ctx)
31759bf7050SPeter Avalos {
3186b384f39SPeter Avalos 	unsigned temp = ctx->keys[2] | 2;
3196b384f39SPeter Avalos 	return (uint8_t)((temp * (temp ^ 1)) >> 8) & 0xff;
320d4d8193eSPeter Avalos }
321d4d8193eSPeter Avalos 
322d4d8193eSPeter Avalos static void
trad_enc_decrypt_update(struct trad_enc_ctx * ctx,const uint8_t * in,size_t in_len,uint8_t * out,size_t out_len)3236b384f39SPeter Avalos trad_enc_decrypt_update(struct trad_enc_ctx *ctx, const uint8_t *in,
3246b384f39SPeter Avalos     size_t in_len, uint8_t *out, size_t out_len)
325d4d8193eSPeter Avalos {
3266b384f39SPeter Avalos 	unsigned i, max;
327d4d8193eSPeter Avalos 
3286b384f39SPeter Avalos 	max = (unsigned)((in_len < out_len)? in_len: out_len);
3296b384f39SPeter Avalos 
3306b384f39SPeter Avalos 	for (i = 0; i < max; i++) {
331e95abc47Szrj 		uint8_t t = in[i] ^ trad_enc_decrypt_byte(ctx);
3326b384f39SPeter Avalos 		out[i] = t;
3336b384f39SPeter Avalos 		trad_enc_update_keys(ctx, t);
334d4d8193eSPeter Avalos 	}
335d4d8193eSPeter Avalos }
336d4d8193eSPeter Avalos 
337d4d8193eSPeter Avalos static int
trad_enc_init(struct trad_enc_ctx * ctx,const char * pw,size_t pw_len,const uint8_t * key,size_t key_len,uint8_t * crcchk)3386b384f39SPeter Avalos trad_enc_init(struct trad_enc_ctx *ctx, const char *pw, size_t pw_len,
3396b384f39SPeter Avalos     const uint8_t *key, size_t key_len, uint8_t *crcchk)
340c09f92d2SPeter Avalos {
3416b384f39SPeter Avalos 	uint8_t header[12];
342d4d8193eSPeter Avalos 
3436b384f39SPeter Avalos 	if (key_len < 12) {
3446b384f39SPeter Avalos 		*crcchk = 0xff;
3456b384f39SPeter Avalos 		return -1;
346c09f92d2SPeter Avalos 	}
347d4d8193eSPeter Avalos 
3486b384f39SPeter Avalos 	ctx->keys[0] = 305419896L;
3496b384f39SPeter Avalos 	ctx->keys[1] = 591751049L;
3506b384f39SPeter Avalos 	ctx->keys[2] = 878082192L;
3516b384f39SPeter Avalos 
3526b384f39SPeter Avalos 	for (;pw_len; --pw_len)
3536b384f39SPeter Avalos 		trad_enc_update_keys(ctx, *pw++);
3546b384f39SPeter Avalos 
3556b384f39SPeter Avalos 	trad_enc_decrypt_update(ctx, key, 12, header, 12);
3566b384f39SPeter Avalos 	/* Return the last byte for CRC check. */
3576b384f39SPeter Avalos 	*crcchk = header[11];
3586b384f39SPeter Avalos 	return 0;
359d4d8193eSPeter Avalos }
360c09f92d2SPeter Avalos 
3616b384f39SPeter Avalos #if 0
3626b384f39SPeter Avalos static void
3636b384f39SPeter Avalos crypt_derive_key_sha1(const void *p, int size, unsigned char *key,
3646b384f39SPeter Avalos     int key_size)
36559bf7050SPeter Avalos {
3666b384f39SPeter Avalos #define MD_SIZE 20
3676b384f39SPeter Avalos 	archive_sha1_ctx ctx;
3686b384f39SPeter Avalos 	unsigned char md1[MD_SIZE];
3696b384f39SPeter Avalos 	unsigned char md2[MD_SIZE * 2];
3706b384f39SPeter Avalos 	unsigned char mkb[64];
3716b384f39SPeter Avalos 	int i;
37259bf7050SPeter Avalos 
3736b384f39SPeter Avalos 	archive_sha1_init(&ctx);
3746b384f39SPeter Avalos 	archive_sha1_update(&ctx, p, size);
3756b384f39SPeter Avalos 	archive_sha1_final(&ctx, md1);
37659bf7050SPeter Avalos 
3776b384f39SPeter Avalos 	memset(mkb, 0x36, sizeof(mkb));
3786b384f39SPeter Avalos 	for (i = 0; i < MD_SIZE; i++)
3796b384f39SPeter Avalos 		mkb[i] ^= md1[i];
3806b384f39SPeter Avalos 	archive_sha1_init(&ctx);
3816b384f39SPeter Avalos 	archive_sha1_update(&ctx, mkb, sizeof(mkb));
3826b384f39SPeter Avalos 	archive_sha1_final(&ctx, md2);
383d4d8193eSPeter Avalos 
3846b384f39SPeter Avalos 	memset(mkb, 0x5C, sizeof(mkb));
3856b384f39SPeter Avalos 	for (i = 0; i < MD_SIZE; i++)
3866b384f39SPeter Avalos 		mkb[i] ^= md1[i];
3876b384f39SPeter Avalos 	archive_sha1_init(&ctx);
3886b384f39SPeter Avalos 	archive_sha1_update(&ctx, mkb, sizeof(mkb));
3896b384f39SPeter Avalos 	archive_sha1_final(&ctx, md2 + MD_SIZE);
390d4d8193eSPeter Avalos 
3916b384f39SPeter Avalos 	if (key_size > 32)
3926b384f39SPeter Avalos 		key_size = 32;
3936b384f39SPeter Avalos 	memcpy(key, md2, key_size);
3946b384f39SPeter Avalos #undef MD_SIZE
395d4d8193eSPeter Avalos }
396d4d8193eSPeter Avalos #endif
39760b4ad09SPeter Avalos 
39860b4ad09SPeter Avalos /*
3996b384f39SPeter Avalos  * Common code for streaming or seeking modes.
4006b384f39SPeter Avalos  *
4016b384f39SPeter Avalos  * Includes code to read local file headers, decompress data
4026b384f39SPeter Avalos  * from entry bodies, and common API.
40360b4ad09SPeter Avalos  */
40460b4ad09SPeter Avalos 
4056b384f39SPeter Avalos static unsigned long
real_crc32(unsigned long crc,const void * buff,size_t len)4066b384f39SPeter Avalos real_crc32(unsigned long crc, const void *buff, size_t len)
40760b4ad09SPeter Avalos {
4086b384f39SPeter Avalos 	return crc32(crc, buff, (unsigned int)len);
40960b4ad09SPeter Avalos }
41060b4ad09SPeter Avalos 
4116b384f39SPeter Avalos /* Used by "ignorecrc32" option to speed up tests. */
4126b384f39SPeter Avalos static unsigned long
fake_crc32(unsigned long crc,const void * buff,size_t len)4136b384f39SPeter Avalos fake_crc32(unsigned long crc, const void *buff, size_t len)
41460b4ad09SPeter Avalos {
4156b384f39SPeter Avalos 	(void)crc; /* UNUSED */
4166b384f39SPeter Avalos 	(void)buff; /* UNUSED */
4176b384f39SPeter Avalos 	(void)len; /* UNUSED */
4186b384f39SPeter Avalos 	return 0;
419c09f92d2SPeter Avalos }
420c09f92d2SPeter Avalos 
421e95abc47Szrj static const struct {
4226b384f39SPeter Avalos 	int id;
4236b384f39SPeter Avalos 	const char * name;
4246b384f39SPeter Avalos } compression_methods[] = {
4256b384f39SPeter Avalos 	{0, "uncompressed"}, /* The file is stored (no compression) */
4266b384f39SPeter Avalos 	{1, "shrinking"}, /* The file is Shrunk */
4276b384f39SPeter Avalos 	{2, "reduced-1"}, /* The file is Reduced with compression factor 1 */
4286b384f39SPeter Avalos 	{3, "reduced-2"}, /* The file is Reduced with compression factor 2 */
4296b384f39SPeter Avalos 	{4, "reduced-3"}, /* The file is Reduced with compression factor 3 */
4306b384f39SPeter Avalos 	{5, "reduced-4"}, /* The file is Reduced with compression factor 4 */
4316b384f39SPeter Avalos 	{6, "imploded"},  /* The file is Imploded */
4326b384f39SPeter Avalos 	{7, "reserved"},  /* Reserved for Tokenizing compression algorithm */
4336b384f39SPeter Avalos 	{8, "deflation"}, /* The file is Deflated */
4346b384f39SPeter Avalos 	{9, "deflation-64-bit"}, /* Enhanced Deflating using Deflate64(tm) */
4356b384f39SPeter Avalos 	{10, "ibm-terse"},/* PKWARE Data Compression Library Imploding
4366b384f39SPeter Avalos 			   * (old IBM TERSE) */
4376b384f39SPeter Avalos 	{11, "reserved"}, /* Reserved by PKWARE */
4386b384f39SPeter Avalos 	{12, "bzip"},     /* File is compressed using BZIP2 algorithm */
4396b384f39SPeter Avalos 	{13, "reserved"}, /* Reserved by PKWARE */
4406b384f39SPeter Avalos 	{14, "lzma"},     /* LZMA (EFS) */
4416b384f39SPeter Avalos 	{15, "reserved"}, /* Reserved by PKWARE */
4426b384f39SPeter Avalos 	{16, "reserved"}, /* Reserved by PKWARE */
4436b384f39SPeter Avalos 	{17, "reserved"}, /* Reserved by PKWARE */
4446b384f39SPeter Avalos 	{18, "ibm-terse-new"}, /* File is compressed using IBM TERSE (new) */
4456b384f39SPeter Avalos 	{19, "ibm-lz777"},/* IBM LZ77 z Architecture (PFS) */
446*50f8aa9cSAntonio Huete Jimenez 	{93, "zstd"},     /*  Zstandard (zstd) Compression */
447085658deSDaniel Fojt 	{95, "xz"},       /* XZ compressed data */
448085658deSDaniel Fojt 	{96, "jpeg"},     /* JPEG compressed data */
4496b384f39SPeter Avalos 	{97, "wav-pack"}, /* WavPack compressed data */
4506b384f39SPeter Avalos 	{98, "ppmd-1"},   /* PPMd version I, Rev 1 */
4516b384f39SPeter Avalos 	{99, "aes"}       /* WinZip AES encryption  */
4526b384f39SPeter Avalos };
453c09f92d2SPeter Avalos 
454c09f92d2SPeter Avalos static const char *
compression_name(const int compression)4556b384f39SPeter Avalos compression_name(const int compression)
456c09f92d2SPeter Avalos {
4576b384f39SPeter Avalos 	static const int num_compression_methods =
4586b384f39SPeter Avalos 		sizeof(compression_methods)/sizeof(compression_methods[0]);
4596b384f39SPeter Avalos 	int i=0;
460c09f92d2SPeter Avalos 
4616b384f39SPeter Avalos 	while(compression >= 0 && i < num_compression_methods) {
4626b384f39SPeter Avalos 		if (compression_methods[i].id == compression)
4636b384f39SPeter Avalos 			return compression_methods[i].name;
4646b384f39SPeter Avalos 		i++;
4656b384f39SPeter Avalos 	}
466c09f92d2SPeter Avalos 	return "??";
46760b4ad09SPeter Avalos }
46860b4ad09SPeter Avalos 
46960b4ad09SPeter Avalos /* Convert an MSDOS-style date/time into Unix-style time. */
47060b4ad09SPeter Avalos static time_t
zip_time(const char * p)47160b4ad09SPeter Avalos zip_time(const char *p)
47260b4ad09SPeter Avalos {
47360b4ad09SPeter Avalos 	int msTime, msDate;
47460b4ad09SPeter Avalos 	struct tm ts;
47560b4ad09SPeter Avalos 
47660b4ad09SPeter Avalos 	msTime = (0xff & (unsigned)p[0]) + 256 * (0xff & (unsigned)p[1]);
47760b4ad09SPeter Avalos 	msDate = (0xff & (unsigned)p[2]) + 256 * (0xff & (unsigned)p[3]);
47860b4ad09SPeter Avalos 
47960b4ad09SPeter Avalos 	memset(&ts, 0, sizeof(ts));
48060b4ad09SPeter Avalos 	ts.tm_year = ((msDate >> 9) & 0x7f) + 80; /* Years since 1900. */
48160b4ad09SPeter Avalos 	ts.tm_mon = ((msDate >> 5) & 0x0f) - 1; /* Month number. */
48260b4ad09SPeter Avalos 	ts.tm_mday = msDate & 0x1f; /* Day of month. */
48360b4ad09SPeter Avalos 	ts.tm_hour = (msTime >> 11) & 0x1f;
48460b4ad09SPeter Avalos 	ts.tm_min = (msTime >> 5) & 0x3f;
48560b4ad09SPeter Avalos 	ts.tm_sec = (msTime << 1) & 0x3e;
48660b4ad09SPeter Avalos 	ts.tm_isdst = -1;
48760b4ad09SPeter Avalos 	return mktime(&ts);
48860b4ad09SPeter Avalos }
48960b4ad09SPeter Avalos 
49060b4ad09SPeter Avalos /*
49160b4ad09SPeter Avalos  * The extra data is stored as a list of
49260b4ad09SPeter Avalos  *	id1+size1+data1 + id2+size2+data2 ...
49360b4ad09SPeter Avalos  *  triplets.  id and size are 2 bytes each.
49460b4ad09SPeter Avalos  */
495e95abc47Szrj static int
process_extra(struct archive_read * a,struct archive_entry * entry,const char * p,size_t extra_length,struct zip_entry * zip_entry)496085658deSDaniel Fojt process_extra(struct archive_read *a, struct archive_entry *entry,
497085658deSDaniel Fojt      const char *p, size_t extra_length, struct zip_entry* zip_entry)
49860b4ad09SPeter Avalos {
499c09f92d2SPeter Avalos 	unsigned offset = 0;
500085658deSDaniel Fojt 	struct zip *zip = (struct zip *)(a->format->data);
501c09f92d2SPeter Avalos 
502e95abc47Szrj 	if (extra_length == 0) {
503e95abc47Szrj 		return ARCHIVE_OK;
504e95abc47Szrj 	}
505e95abc47Szrj 
506e95abc47Szrj 	if (extra_length < 4) {
507085658deSDaniel Fojt 		size_t i = 0;
508085658deSDaniel Fojt 		/* Some ZIP files may have trailing 0 bytes. Let's check they
509085658deSDaniel Fojt 		 * are all 0 and ignore them instead of returning an error.
510085658deSDaniel Fojt 		 *
511085658deSDaniel Fojt 		 * This is not technically correct, but some ZIP files look
512085658deSDaniel Fojt 		 * like this and other tools support those files - so let's
513085658deSDaniel Fojt 		 * also  support them.
514085658deSDaniel Fojt 		 */
515085658deSDaniel Fojt 		for (; i < extra_length; i++) {
516085658deSDaniel Fojt 			if (p[i] != 0) {
517085658deSDaniel Fojt 				archive_set_error(&a->archive,
518085658deSDaniel Fojt 				    ARCHIVE_ERRNO_FILE_FORMAT,
519085658deSDaniel Fojt 				    "Too-small extra data: "
520085658deSDaniel Fojt 				    "Need at least 4 bytes, "
521085658deSDaniel Fojt 				    "but only found %d bytes",
522085658deSDaniel Fojt 				    (int)extra_length);
523e95abc47Szrj 				return ARCHIVE_FAILED;
524e95abc47Szrj 			}
525085658deSDaniel Fojt 		}
526085658deSDaniel Fojt 
527085658deSDaniel Fojt 		return ARCHIVE_OK;
528085658deSDaniel Fojt 	}
529085658deSDaniel Fojt 
530e95abc47Szrj 	while (offset <= extra_length - 4) {
53160b4ad09SPeter Avalos 		unsigned short headerid = archive_le16dec(p + offset);
53260b4ad09SPeter Avalos 		unsigned short datasize = archive_le16dec(p + offset + 2);
5336b384f39SPeter Avalos 
53460b4ad09SPeter Avalos 		offset += 4;
5356b384f39SPeter Avalos 		if (offset + datasize > extra_length) {
536085658deSDaniel Fojt 			archive_set_error(&a->archive,
537085658deSDaniel Fojt 			    ARCHIVE_ERRNO_FILE_FORMAT, "Extra data overflow: "
538085658deSDaniel Fojt 			    "Need %d bytes but only found %d bytes",
539e95abc47Szrj 			    (int)datasize, (int)(extra_length - offset));
540e95abc47Szrj 			return ARCHIVE_FAILED;
5416b384f39SPeter Avalos 		}
54260b4ad09SPeter Avalos #ifdef DEBUG
5436b384f39SPeter Avalos 		fprintf(stderr, "Header id 0x%04x, length %d\n",
54460b4ad09SPeter Avalos 		    headerid, datasize);
54560b4ad09SPeter Avalos #endif
54660b4ad09SPeter Avalos 		switch (headerid) {
54760b4ad09SPeter Avalos 		case 0x0001:
54860b4ad09SPeter Avalos 			/* Zip64 extended information extra field. */
5496b384f39SPeter Avalos 			zip_entry->flags |= LA_USED_ZIP64;
5506b384f39SPeter Avalos 			if (zip_entry->uncompressed_size == 0xffffffff) {
551e95abc47Szrj 				uint64_t t = 0;
552e95abc47Szrj 				if (datasize < 8
553085658deSDaniel Fojt 				    || (t = archive_le64dec(p + offset)) >
554085658deSDaniel Fojt 				    INT64_MAX) {
555085658deSDaniel Fojt 					archive_set_error(&a->archive,
556085658deSDaniel Fojt 					    ARCHIVE_ERRNO_FILE_FORMAT,
557085658deSDaniel Fojt 					    "Malformed 64-bit "
558085658deSDaniel Fojt 					    "uncompressed size");
559e95abc47Szrj 					return ARCHIVE_FAILED;
560e95abc47Szrj 				}
561e95abc47Szrj 				zip_entry->uncompressed_size = t;
5626b384f39SPeter Avalos 				offset += 8;
5636b384f39SPeter Avalos 				datasize -= 8;
5646b384f39SPeter Avalos 			}
5656b384f39SPeter Avalos 			if (zip_entry->compressed_size == 0xffffffff) {
566e95abc47Szrj 				uint64_t t = 0;
567e95abc47Szrj 				if (datasize < 8
568085658deSDaniel Fojt 				    || (t = archive_le64dec(p + offset)) >
569085658deSDaniel Fojt 				    INT64_MAX) {
570085658deSDaniel Fojt 					archive_set_error(&a->archive,
571085658deSDaniel Fojt 					    ARCHIVE_ERRNO_FILE_FORMAT,
572085658deSDaniel Fojt 					    "Malformed 64-bit "
573085658deSDaniel Fojt 					    "compressed size");
574e95abc47Szrj 					return ARCHIVE_FAILED;
575e95abc47Szrj 				}
576e95abc47Szrj 				zip_entry->compressed_size = t;
5776b384f39SPeter Avalos 				offset += 8;
5786b384f39SPeter Avalos 				datasize -= 8;
5796b384f39SPeter Avalos 			}
5806b384f39SPeter Avalos 			if (zip_entry->local_header_offset == 0xffffffff) {
581e95abc47Szrj 				uint64_t t = 0;
582e95abc47Szrj 				if (datasize < 8
583085658deSDaniel Fojt 				    || (t = archive_le64dec(p + offset)) >
584085658deSDaniel Fojt 				    INT64_MAX) {
585085658deSDaniel Fojt 					archive_set_error(&a->archive,
586085658deSDaniel Fojt 					    ARCHIVE_ERRNO_FILE_FORMAT,
587085658deSDaniel Fojt 					    "Malformed 64-bit "
588085658deSDaniel Fojt 					    "local header offset");
589e95abc47Szrj 					return ARCHIVE_FAILED;
590e95abc47Szrj 				}
591e95abc47Szrj 				zip_entry->local_header_offset = t;
5926b384f39SPeter Avalos 				offset += 8;
5936b384f39SPeter Avalos 				datasize -= 8;
5946b384f39SPeter Avalos 			}
5956b384f39SPeter Avalos 			/* archive_le32dec(p + offset) gives disk
5966b384f39SPeter Avalos 			 * on which file starts, but we don't handle
5976b384f39SPeter Avalos 			 * multi-volume Zip files. */
5986b384f39SPeter Avalos 			break;
5996b384f39SPeter Avalos #ifdef DEBUG
6006b384f39SPeter Avalos 		case 0x0017:
6016b384f39SPeter Avalos 		{
6026b384f39SPeter Avalos 			/* Strong encryption field. */
6036b384f39SPeter Avalos 			if (archive_le16dec(p + offset) == 2) {
6046b384f39SPeter Avalos 				unsigned algId =
6056b384f39SPeter Avalos 					archive_le16dec(p + offset + 2);
6066b384f39SPeter Avalos 				unsigned bitLen =
6076b384f39SPeter Avalos 					archive_le16dec(p + offset + 4);
6086b384f39SPeter Avalos 				int	 flags =
6096b384f39SPeter Avalos 					archive_le16dec(p + offset + 6);
6106b384f39SPeter Avalos 				fprintf(stderr, "algId=0x%04x, bitLen=%u, "
6116b384f39SPeter Avalos 				    "flgas=%d\n", algId, bitLen,flags);
6126b384f39SPeter Avalos 			}
6136b384f39SPeter Avalos 			break;
6146b384f39SPeter Avalos 		}
6156b384f39SPeter Avalos #endif
61660b4ad09SPeter Avalos 		case 0x5455:
61760b4ad09SPeter Avalos 		{
61860b4ad09SPeter Avalos 			/* Extended time field "UT". */
619e95abc47Szrj 			int flags;
620e95abc47Szrj 			if (datasize == 0) {
621085658deSDaniel Fojt 				archive_set_error(&a->archive,
622085658deSDaniel Fojt 				    ARCHIVE_ERRNO_FILE_FORMAT,
623e95abc47Szrj 				    "Incomplete extended time field");
624e95abc47Szrj 				return ARCHIVE_FAILED;
625e95abc47Szrj 			}
626e95abc47Szrj 			flags = p[offset];
62760b4ad09SPeter Avalos 			offset++;
62860b4ad09SPeter Avalos 			datasize--;
62960b4ad09SPeter Avalos 			/* Flag bits indicate which dates are present. */
63060b4ad09SPeter Avalos 			if (flags & 0x01)
63160b4ad09SPeter Avalos 			{
63260b4ad09SPeter Avalos #ifdef DEBUG
63360b4ad09SPeter Avalos 				fprintf(stderr, "mtime: %lld -> %d\n",
634c09f92d2SPeter Avalos 				    (long long)zip_entry->mtime,
63560b4ad09SPeter Avalos 				    archive_le32dec(p + offset));
63660b4ad09SPeter Avalos #endif
63760b4ad09SPeter Avalos 				if (datasize < 4)
63860b4ad09SPeter Avalos 					break;
639c09f92d2SPeter Avalos 				zip_entry->mtime = archive_le32dec(p + offset);
64060b4ad09SPeter Avalos 				offset += 4;
64160b4ad09SPeter Avalos 				datasize -= 4;
64260b4ad09SPeter Avalos 			}
64360b4ad09SPeter Avalos 			if (flags & 0x02)
64460b4ad09SPeter Avalos 			{
64560b4ad09SPeter Avalos 				if (datasize < 4)
64660b4ad09SPeter Avalos 					break;
647c09f92d2SPeter Avalos 				zip_entry->atime = archive_le32dec(p + offset);
64860b4ad09SPeter Avalos 				offset += 4;
64960b4ad09SPeter Avalos 				datasize -= 4;
65060b4ad09SPeter Avalos 			}
65160b4ad09SPeter Avalos 			if (flags & 0x04)
65260b4ad09SPeter Avalos 			{
65360b4ad09SPeter Avalos 				if (datasize < 4)
65460b4ad09SPeter Avalos 					break;
655c09f92d2SPeter Avalos 				zip_entry->ctime = archive_le32dec(p + offset);
65660b4ad09SPeter Avalos 				offset += 4;
65760b4ad09SPeter Avalos 				datasize -= 4;
65860b4ad09SPeter Avalos 			}
65960b4ad09SPeter Avalos 			break;
66060b4ad09SPeter Avalos 		}
661c09f92d2SPeter Avalos 		case 0x5855:
662c09f92d2SPeter Avalos 		{
663c09f92d2SPeter Avalos 			/* Info-ZIP Unix Extra Field (old version) "UX". */
664c09f92d2SPeter Avalos 			if (datasize >= 8) {
665c09f92d2SPeter Avalos 				zip_entry->atime = archive_le32dec(p + offset);
666d4d8193eSPeter Avalos 				zip_entry->mtime =
667d4d8193eSPeter Avalos 				    archive_le32dec(p + offset + 4);
668c09f92d2SPeter Avalos 			}
669c09f92d2SPeter Avalos 			if (datasize >= 12) {
670d4d8193eSPeter Avalos 				zip_entry->uid =
671d4d8193eSPeter Avalos 				    archive_le16dec(p + offset + 8);
672d4d8193eSPeter Avalos 				zip_entry->gid =
673d4d8193eSPeter Avalos 				    archive_le16dec(p + offset + 10);
674c09f92d2SPeter Avalos 			}
675c09f92d2SPeter Avalos 			break;
676c09f92d2SPeter Avalos 		}
6776b384f39SPeter Avalos 		case 0x6c78:
6786b384f39SPeter Avalos 		{
6796b384f39SPeter Avalos 			/* Experimental 'xl' field */
6806b384f39SPeter Avalos 			/*
6816b384f39SPeter Avalos 			 * Introduced Dec 2013 to provide a way to
6826b384f39SPeter Avalos 			 * include external file attributes (and other
6836b384f39SPeter Avalos 			 * fields that ordinarily appear only in
6846b384f39SPeter Avalos 			 * central directory) in local file header.
6856b384f39SPeter Avalos 			 * This provides file type and permission
6866b384f39SPeter Avalos 			 * information necessary to support full
6876b384f39SPeter Avalos 			 * streaming extraction.  Currently being
6886b384f39SPeter Avalos 			 * discussed with other Zip developers
6896b384f39SPeter Avalos 			 * ... subject to change.
6906b384f39SPeter Avalos 			 *
6916b384f39SPeter Avalos 			 * Format:
6926b384f39SPeter Avalos 			 *  The field starts with a bitmap that specifies
6936b384f39SPeter Avalos 			 *  which additional fields are included.  The
6946b384f39SPeter Avalos 			 *  bitmap is variable length and can be extended in
6956b384f39SPeter Avalos 			 *  the future.
6966b384f39SPeter Avalos 			 *
6976b384f39SPeter Avalos 			 *  n bytes - feature bitmap: first byte has low-order
6986b384f39SPeter Avalos 			 *    7 bits.  If high-order bit is set, a subsequent
6996b384f39SPeter Avalos 			 *    byte holds the next 7 bits, etc.
7006b384f39SPeter Avalos 			 *
7016b384f39SPeter Avalos 			 *  if bitmap & 1, 2 byte "version made by"
7026b384f39SPeter Avalos 			 *  if bitmap & 2, 2 byte "internal file attributes"
7036b384f39SPeter Avalos 			 *  if bitmap & 4, 4 byte "external file attributes"
704085658deSDaniel Fojt 			 *  if bitmap & 8, 2 byte comment length + n byte
705085658deSDaniel Fojt 			 *  comment
7066b384f39SPeter Avalos 			 */
7076b384f39SPeter Avalos 			int bitmap, bitmap_last;
7086b384f39SPeter Avalos 
7096b384f39SPeter Avalos 			if (datasize < 1)
7106b384f39SPeter Avalos 				break;
7116b384f39SPeter Avalos 			bitmap_last = bitmap = 0xff & p[offset];
7126b384f39SPeter Avalos 			offset += 1;
7136b384f39SPeter Avalos 			datasize -= 1;
7146b384f39SPeter Avalos 
7156b384f39SPeter Avalos 			/* We only support first 7 bits of bitmap; skip rest. */
7166b384f39SPeter Avalos 			while ((bitmap_last & 0x80) != 0
7176b384f39SPeter Avalos 			    && datasize >= 1) {
7186b384f39SPeter Avalos 				bitmap_last = p[offset];
7196b384f39SPeter Avalos 				offset += 1;
7206b384f39SPeter Avalos 				datasize -= 1;
7216b384f39SPeter Avalos 			}
7226b384f39SPeter Avalos 
7236b384f39SPeter Avalos 			if (bitmap & 1) {
7246b384f39SPeter Avalos 				/* 2 byte "version made by" */
7256b384f39SPeter Avalos 				if (datasize < 2)
7266b384f39SPeter Avalos 					break;
7276b384f39SPeter Avalos 				zip_entry->system
7286b384f39SPeter Avalos 				    = archive_le16dec(p + offset) >> 8;
7296b384f39SPeter Avalos 				offset += 2;
7306b384f39SPeter Avalos 				datasize -= 2;
7316b384f39SPeter Avalos 			}
7326b384f39SPeter Avalos 			if (bitmap & 2) {
7336b384f39SPeter Avalos 				/* 2 byte "internal file attributes" */
7346b384f39SPeter Avalos 				uint32_t internal_attributes;
7356b384f39SPeter Avalos 				if (datasize < 2)
7366b384f39SPeter Avalos 					break;
7376b384f39SPeter Avalos 				internal_attributes
7386b384f39SPeter Avalos 				    = archive_le16dec(p + offset);
7396b384f39SPeter Avalos 				/* Not used by libarchive at present. */
7406b384f39SPeter Avalos 				(void)internal_attributes; /* UNUSED */
7416b384f39SPeter Avalos 				offset += 2;
7426b384f39SPeter Avalos 				datasize -= 2;
7436b384f39SPeter Avalos 			}
7446b384f39SPeter Avalos 			if (bitmap & 4) {
7456b384f39SPeter Avalos 				/* 4 byte "external file attributes" */
7466b384f39SPeter Avalos 				uint32_t external_attributes;
7476b384f39SPeter Avalos 				if (datasize < 4)
7486b384f39SPeter Avalos 					break;
7496b384f39SPeter Avalos 				external_attributes
7506b384f39SPeter Avalos 				    = archive_le32dec(p + offset);
7516b384f39SPeter Avalos 				if (zip_entry->system == 3) {
7526b384f39SPeter Avalos 					zip_entry->mode
7536b384f39SPeter Avalos 					    = external_attributes >> 16;
7546b384f39SPeter Avalos 				} else if (zip_entry->system == 0) {
7556b384f39SPeter Avalos 					// Interpret MSDOS directory bit
756085658deSDaniel Fojt 					if (0x10 == (external_attributes &
757085658deSDaniel Fojt 					    0x10)) {
758085658deSDaniel Fojt 						zip_entry->mode =
759085658deSDaniel Fojt 						    AE_IFDIR | 0775;
7606b384f39SPeter Avalos 					} else {
761085658deSDaniel Fojt 						zip_entry->mode =
762085658deSDaniel Fojt 						    AE_IFREG | 0664;
7636b384f39SPeter Avalos 					}
764085658deSDaniel Fojt 					if (0x01 == (external_attributes &
765085658deSDaniel Fojt 					    0x01)) {
766085658deSDaniel Fojt 						/* Read-only bit;
767085658deSDaniel Fojt 						 * strip write permissions */
7686b384f39SPeter Avalos 						zip_entry->mode &= 0555;
7696b384f39SPeter Avalos 					}
7706b384f39SPeter Avalos 				} else {
7716b384f39SPeter Avalos 					zip_entry->mode = 0;
7726b384f39SPeter Avalos 				}
7736b384f39SPeter Avalos 				offset += 4;
7746b384f39SPeter Avalos 				datasize -= 4;
7756b384f39SPeter Avalos 			}
7766b384f39SPeter Avalos 			if (bitmap & 8) {
7776b384f39SPeter Avalos 				/* 2 byte comment length + comment */
7786b384f39SPeter Avalos 				uint32_t comment_length;
7796b384f39SPeter Avalos 				if (datasize < 2)
7806b384f39SPeter Avalos 					break;
7816b384f39SPeter Avalos 				comment_length
7826b384f39SPeter Avalos 				    = archive_le16dec(p + offset);
7836b384f39SPeter Avalos 				offset += 2;
7846b384f39SPeter Avalos 				datasize -= 2;
7856b384f39SPeter Avalos 
7866b384f39SPeter Avalos 				if (datasize < comment_length)
7876b384f39SPeter Avalos 					break;
7886b384f39SPeter Avalos 				/* Comment is not supported by libarchive */
7896b384f39SPeter Avalos 				offset += comment_length;
7906b384f39SPeter Avalos 				datasize -= comment_length;
7916b384f39SPeter Avalos 			}
7926b384f39SPeter Avalos 			break;
7936b384f39SPeter Avalos 		}
794085658deSDaniel Fojt 		case 0x7075:
795085658deSDaniel Fojt 		{
796085658deSDaniel Fojt 			/* Info-ZIP Unicode Path Extra Field. */
797085658deSDaniel Fojt 			if (datasize < 5 || entry == NULL)
798085658deSDaniel Fojt 				break;
799085658deSDaniel Fojt 			offset += 5;
800085658deSDaniel Fojt 			datasize -= 5;
801085658deSDaniel Fojt 
802085658deSDaniel Fojt 			/* The path name in this field is always encoded
803085658deSDaniel Fojt 			 * in UTF-8. */
804085658deSDaniel Fojt 			if (zip->sconv_utf8 == NULL) {
805085658deSDaniel Fojt 				zip->sconv_utf8 =
806085658deSDaniel Fojt 					archive_string_conversion_from_charset(
807085658deSDaniel Fojt 					&a->archive, "UTF-8", 1);
808085658deSDaniel Fojt 				/* If the converter from UTF-8 is not
809085658deSDaniel Fojt 				 * available, then the path name from the main
810085658deSDaniel Fojt 				 * field will more likely be correct. */
811085658deSDaniel Fojt 				if (zip->sconv_utf8 == NULL)
812085658deSDaniel Fojt 					break;
813085658deSDaniel Fojt 			}
814085658deSDaniel Fojt 
815085658deSDaniel Fojt 			/* Make sure the CRC32 of the filename matches. */
816085658deSDaniel Fojt 			if (!zip->ignore_crc32) {
817085658deSDaniel Fojt 				const char *cp = archive_entry_pathname(entry);
818085658deSDaniel Fojt 				if (cp) {
819085658deSDaniel Fojt 					unsigned long file_crc =
820085658deSDaniel Fojt 					    zip->crc32func(0, cp, strlen(cp));
821085658deSDaniel Fojt 					unsigned long utf_crc =
822085658deSDaniel Fojt 					    archive_le32dec(p + offset - 4);
823085658deSDaniel Fojt 					if (file_crc != utf_crc) {
824085658deSDaniel Fojt #ifdef DEBUG
825085658deSDaniel Fojt 						fprintf(stderr,
826085658deSDaniel Fojt 						    "CRC filename mismatch; "
827085658deSDaniel Fojt 						    "CDE is %lx, but UTF8 "
828085658deSDaniel Fojt 						    "is outdated with %lx\n",
829085658deSDaniel Fojt 						    file_crc, utf_crc);
830085658deSDaniel Fojt #endif
831085658deSDaniel Fojt 						break;
832085658deSDaniel Fojt 					}
833085658deSDaniel Fojt 				}
834085658deSDaniel Fojt 			}
835085658deSDaniel Fojt 
836085658deSDaniel Fojt 			if (archive_entry_copy_pathname_l(entry,
837085658deSDaniel Fojt 			    p + offset, datasize, zip->sconv_utf8) != 0) {
838085658deSDaniel Fojt 				/* Ignore the error, and fallback to the path
839085658deSDaniel Fojt 				 * name from the main field. */
840085658deSDaniel Fojt #ifdef DEBUG
841085658deSDaniel Fojt 				fprintf(stderr, "Failed to read the ZIP "
842085658deSDaniel Fojt 				    "0x7075 extra field path.\n");
843085658deSDaniel Fojt #endif
844085658deSDaniel Fojt 			}
845085658deSDaniel Fojt 			break;
846085658deSDaniel Fojt 		}
84760b4ad09SPeter Avalos 		case 0x7855:
84860b4ad09SPeter Avalos 			/* Info-ZIP Unix Extra Field (type 2) "Ux". */
84960b4ad09SPeter Avalos #ifdef DEBUG
85060b4ad09SPeter Avalos 			fprintf(stderr, "uid %d gid %d\n",
85160b4ad09SPeter Avalos 			    archive_le16dec(p + offset),
85260b4ad09SPeter Avalos 			    archive_le16dec(p + offset + 2));
85360b4ad09SPeter Avalos #endif
85460b4ad09SPeter Avalos 			if (datasize >= 2)
855c09f92d2SPeter Avalos 				zip_entry->uid = archive_le16dec(p + offset);
85660b4ad09SPeter Avalos 			if (datasize >= 4)
857d4d8193eSPeter Avalos 				zip_entry->gid =
858d4d8193eSPeter Avalos 				    archive_le16dec(p + offset + 2);
85960b4ad09SPeter Avalos 			break;
860c09f92d2SPeter Avalos 		case 0x7875:
861c09f92d2SPeter Avalos 		{
862c09f92d2SPeter Avalos 			/* Info-Zip Unix Extra Field (type 3) "ux". */
863c09f92d2SPeter Avalos 			int uidsize = 0, gidsize = 0;
864c09f92d2SPeter Avalos 
8656b384f39SPeter Avalos 			/* TODO: support arbitrary uidsize/gidsize. */
866c09f92d2SPeter Avalos 			if (datasize >= 1 && p[offset] == 1) {/* version=1 */
867c09f92d2SPeter Avalos 				if (datasize >= 4) {
868c09f92d2SPeter Avalos 					/* get a uid size. */
8696b384f39SPeter Avalos 					uidsize = 0xff & (int)p[offset+1];
870c09f92d2SPeter Avalos 					if (uidsize == 2)
871d4d8193eSPeter Avalos 						zip_entry->uid =
872d4d8193eSPeter Avalos 						    archive_le16dec(
873c09f92d2SPeter Avalos 						        p + offset + 2);
874c09f92d2SPeter Avalos 					else if (uidsize == 4 && datasize >= 6)
875d4d8193eSPeter Avalos 						zip_entry->uid =
876d4d8193eSPeter Avalos 						    archive_le32dec(
877c09f92d2SPeter Avalos 						        p + offset + 2);
878c09f92d2SPeter Avalos 				}
879c09f92d2SPeter Avalos 				if (datasize >= (2 + uidsize + 3)) {
880c09f92d2SPeter Avalos 					/* get a gid size. */
881085658deSDaniel Fojt 					gidsize = 0xff &
882085658deSDaniel Fojt 					    (int)p[offset+2+uidsize];
883c09f92d2SPeter Avalos 					if (gidsize == 2)
884d4d8193eSPeter Avalos 						zip_entry->gid =
885d4d8193eSPeter Avalos 						    archive_le16dec(
886c09f92d2SPeter Avalos 						        p+offset+2+uidsize+1);
887c09f92d2SPeter Avalos 					else if (gidsize == 4 &&
888c09f92d2SPeter Avalos 					    datasize >= (2 + uidsize + 5))
889d4d8193eSPeter Avalos 						zip_entry->gid =
890d4d8193eSPeter Avalos 						    archive_le32dec(
891c09f92d2SPeter Avalos 						        p+offset+2+uidsize+1);
892c09f92d2SPeter Avalos 				}
893c09f92d2SPeter Avalos 			}
894c09f92d2SPeter Avalos 			break;
895c09f92d2SPeter Avalos 		}
8966b384f39SPeter Avalos 		case 0x9901:
897e95abc47Szrj 			/* WinZip AES extra data field. */
898e95abc47Szrj 			if (datasize < 6) {
899085658deSDaniel Fojt 				archive_set_error(&a->archive,
900085658deSDaniel Fojt 				    ARCHIVE_ERRNO_FILE_FORMAT,
901e95abc47Szrj 				    "Incomplete AES field");
902e95abc47Szrj 				return ARCHIVE_FAILED;
903e95abc47Szrj 			}
9046b384f39SPeter Avalos 			if (p[offset + 2] == 'A' && p[offset + 3] == 'E') {
9056b384f39SPeter Avalos 				/* Vendor version. */
9066b384f39SPeter Avalos 				zip_entry->aes_extra.vendor =
9076b384f39SPeter Avalos 				    archive_le16dec(p + offset);
9086b384f39SPeter Avalos 				/* AES encryption strength. */
9096b384f39SPeter Avalos 				zip_entry->aes_extra.strength = p[offset + 4];
9106b384f39SPeter Avalos 				/* Actual compression method. */
9116b384f39SPeter Avalos 				zip_entry->aes_extra.compression =
9126b384f39SPeter Avalos 				    p[offset + 5];
9136b384f39SPeter Avalos 			}
9146b384f39SPeter Avalos 			break;
91560b4ad09SPeter Avalos 		default:
91660b4ad09SPeter Avalos 			break;
91760b4ad09SPeter Avalos 		}
91860b4ad09SPeter Avalos 		offset += datasize;
91960b4ad09SPeter Avalos 	}
920e95abc47Szrj 	return ARCHIVE_OK;
92160b4ad09SPeter Avalos }
9226b384f39SPeter Avalos 
9236b384f39SPeter Avalos /*
9246b384f39SPeter Avalos  * Assumes file pointer is at beginning of local file header.
9256b384f39SPeter Avalos  */
9266b384f39SPeter Avalos static int
zip_read_local_file_header(struct archive_read * a,struct archive_entry * entry,struct zip * zip)9276b384f39SPeter Avalos zip_read_local_file_header(struct archive_read *a, struct archive_entry *entry,
9286b384f39SPeter Avalos     struct zip *zip)
9296b384f39SPeter Avalos {
9306b384f39SPeter Avalos 	const char *p;
9316b384f39SPeter Avalos 	const void *h;
9326b384f39SPeter Avalos 	const wchar_t *wp;
9336b384f39SPeter Avalos 	const char *cp;
9346b384f39SPeter Avalos 	size_t len, filename_length, extra_length;
9356b384f39SPeter Avalos 	struct archive_string_conv *sconv;
9366b384f39SPeter Avalos 	struct zip_entry *zip_entry = zip->entry;
9376b384f39SPeter Avalos 	struct zip_entry zip_entry_central_dir;
9386b384f39SPeter Avalos 	int ret = ARCHIVE_OK;
9396b384f39SPeter Avalos 	char version;
9406b384f39SPeter Avalos 
9416b384f39SPeter Avalos 	/* Save a copy of the original for consistency checks. */
9426b384f39SPeter Avalos 	zip_entry_central_dir = *zip_entry;
9436b384f39SPeter Avalos 
9446b384f39SPeter Avalos 	zip->decompress_init = 0;
9456b384f39SPeter Avalos 	zip->end_of_entry = 0;
9466b384f39SPeter Avalos 	zip->entry_uncompressed_bytes_read = 0;
9476b384f39SPeter Avalos 	zip->entry_compressed_bytes_read = 0;
9486b384f39SPeter Avalos 	zip->entry_crc32 = zip->crc32func(0, NULL, 0);
9496b384f39SPeter Avalos 
9506b384f39SPeter Avalos 	/* Setup default conversion. */
9516b384f39SPeter Avalos 	if (zip->sconv == NULL && !zip->init_default_conversion) {
9526b384f39SPeter Avalos 		zip->sconv_default =
9536b384f39SPeter Avalos 		    archive_string_default_conversion_for_read(&(a->archive));
9546b384f39SPeter Avalos 		zip->init_default_conversion = 1;
9556b384f39SPeter Avalos 	}
9566b384f39SPeter Avalos 
9576b384f39SPeter Avalos 	if ((p = __archive_read_ahead(a, 30, NULL)) == NULL) {
9586b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
9596b384f39SPeter Avalos 		    "Truncated ZIP file header");
9606b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
9616b384f39SPeter Avalos 	}
9626b384f39SPeter Avalos 
9636b384f39SPeter Avalos 	if (memcmp(p, "PK\003\004", 4) != 0) {
9646b384f39SPeter Avalos 		archive_set_error(&a->archive, -1, "Damaged Zip archive");
9656b384f39SPeter Avalos 		return ARCHIVE_FATAL;
9666b384f39SPeter Avalos 	}
9676b384f39SPeter Avalos 	version = p[4];
9686b384f39SPeter Avalos 	zip_entry->system = p[5];
9696b384f39SPeter Avalos 	zip_entry->zip_flags = archive_le16dec(p + 6);
9706b384f39SPeter Avalos 	if (zip_entry->zip_flags & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)) {
9716b384f39SPeter Avalos 		zip->has_encrypted_entries = 1;
9726b384f39SPeter Avalos 		archive_entry_set_is_data_encrypted(entry, 1);
9736b384f39SPeter Avalos 		if (zip_entry->zip_flags & ZIP_CENTRAL_DIRECTORY_ENCRYPTED &&
9746b384f39SPeter Avalos 			zip_entry->zip_flags & ZIP_ENCRYPTED &&
9756b384f39SPeter Avalos 			zip_entry->zip_flags & ZIP_STRONG_ENCRYPTED) {
9766b384f39SPeter Avalos 			archive_entry_set_is_metadata_encrypted(entry, 1);
9776b384f39SPeter Avalos 			return ARCHIVE_FATAL;
9786b384f39SPeter Avalos 		}
9796b384f39SPeter Avalos 	}
9806b384f39SPeter Avalos 	zip->init_decryption = (zip_entry->zip_flags & ZIP_ENCRYPTED);
9816b384f39SPeter Avalos 	zip_entry->compression = (char)archive_le16dec(p + 8);
9826b384f39SPeter Avalos 	zip_entry->mtime = zip_time(p + 10);
9836b384f39SPeter Avalos 	zip_entry->crc32 = archive_le32dec(p + 14);
9846b384f39SPeter Avalos 	if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
9856b384f39SPeter Avalos 		zip_entry->decdat = p[11];
9866b384f39SPeter Avalos 	else
9876b384f39SPeter Avalos 		zip_entry->decdat = p[17];
9886b384f39SPeter Avalos 	zip_entry->compressed_size = archive_le32dec(p + 18);
9896b384f39SPeter Avalos 	zip_entry->uncompressed_size = archive_le32dec(p + 22);
9906b384f39SPeter Avalos 	filename_length = archive_le16dec(p + 26);
9916b384f39SPeter Avalos 	extra_length = archive_le16dec(p + 28);
9926b384f39SPeter Avalos 
9936b384f39SPeter Avalos 	__archive_read_consume(a, 30);
9946b384f39SPeter Avalos 
9956b384f39SPeter Avalos 	/* Read the filename. */
9966b384f39SPeter Avalos 	if ((h = __archive_read_ahead(a, filename_length, NULL)) == NULL) {
9976b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
9986b384f39SPeter Avalos 		    "Truncated ZIP file header");
9996b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
10006b384f39SPeter Avalos 	}
10016b384f39SPeter Avalos 	if (zip_entry->zip_flags & ZIP_UTF8_NAME) {
10026b384f39SPeter Avalos 		/* The filename is stored to be UTF-8. */
10036b384f39SPeter Avalos 		if (zip->sconv_utf8 == NULL) {
10046b384f39SPeter Avalos 			zip->sconv_utf8 =
10056b384f39SPeter Avalos 			    archive_string_conversion_from_charset(
10066b384f39SPeter Avalos 				&a->archive, "UTF-8", 1);
10076b384f39SPeter Avalos 			if (zip->sconv_utf8 == NULL)
10086b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
10096b384f39SPeter Avalos 		}
10106b384f39SPeter Avalos 		sconv = zip->sconv_utf8;
10116b384f39SPeter Avalos 	} else if (zip->sconv != NULL)
10126b384f39SPeter Avalos 		sconv = zip->sconv;
10136b384f39SPeter Avalos 	else
10146b384f39SPeter Avalos 		sconv = zip->sconv_default;
10156b384f39SPeter Avalos 
10166b384f39SPeter Avalos 	if (archive_entry_copy_pathname_l(entry,
10176b384f39SPeter Avalos 	    h, filename_length, sconv) != 0) {
10186b384f39SPeter Avalos 		if (errno == ENOMEM) {
10196b384f39SPeter Avalos 			archive_set_error(&a->archive, ENOMEM,
10206b384f39SPeter Avalos 			    "Can't allocate memory for Pathname");
10216b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
10226b384f39SPeter Avalos 		}
10236b384f39SPeter Avalos 		archive_set_error(&a->archive,
10246b384f39SPeter Avalos 		    ARCHIVE_ERRNO_FILE_FORMAT,
10256b384f39SPeter Avalos 		    "Pathname cannot be converted "
10266b384f39SPeter Avalos 		    "from %s to current locale.",
10276b384f39SPeter Avalos 		    archive_string_conversion_charset_name(sconv));
10286b384f39SPeter Avalos 		ret = ARCHIVE_WARN;
10296b384f39SPeter Avalos 	}
10306b384f39SPeter Avalos 	__archive_read_consume(a, filename_length);
10316b384f39SPeter Avalos 
10326b384f39SPeter Avalos 	/* Read the extra data. */
10336b384f39SPeter Avalos 	if ((h = __archive_read_ahead(a, extra_length, NULL)) == NULL) {
10346b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
10356b384f39SPeter Avalos 		    "Truncated ZIP file header");
10366b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
10376b384f39SPeter Avalos 	}
10386b384f39SPeter Avalos 
1039085658deSDaniel Fojt 	if (ARCHIVE_OK != process_extra(a, entry, h, extra_length,
1040085658deSDaniel Fojt 	    zip_entry)) {
1041e95abc47Szrj 		return ARCHIVE_FATAL;
1042e95abc47Szrj 	}
10436b384f39SPeter Avalos 	__archive_read_consume(a, extra_length);
10446b384f39SPeter Avalos 
10456b384f39SPeter Avalos 	/* Work around a bug in Info-Zip: When reading from a pipe, it
10466b384f39SPeter Avalos 	 * stats the pipe instead of synthesizing a file entry. */
10476b384f39SPeter Avalos 	if ((zip_entry->mode & AE_IFMT) == AE_IFIFO) {
10486b384f39SPeter Avalos 		zip_entry->mode &= ~ AE_IFMT;
10496b384f39SPeter Avalos 		zip_entry->mode |= AE_IFREG;
10506b384f39SPeter Avalos 	}
10516b384f39SPeter Avalos 
1052e95abc47Szrj 	/* If the mode is totally empty, set some sane default. */
1053e95abc47Szrj 	if (zip_entry->mode == 0) {
1054e95abc47Szrj 		zip_entry->mode |= 0664;
1055e95abc47Szrj 	}
1056e95abc47Szrj 
1057085658deSDaniel Fojt 	/* Windows archivers sometimes use backslash as the directory
1058085658deSDaniel Fojt 	 * separator. Normalize to slash. */
1059e95abc47Szrj 	if (zip_entry->system == 0 &&
1060e95abc47Szrj 	    (wp = archive_entry_pathname_w(entry)) != NULL) {
1061e95abc47Szrj 		if (wcschr(wp, L'/') == NULL && wcschr(wp, L'\\') != NULL) {
1062e95abc47Szrj 			size_t i;
1063e95abc47Szrj 			struct archive_wstring s;
1064e95abc47Szrj 			archive_string_init(&s);
1065e95abc47Szrj 			archive_wstrcpy(&s, wp);
1066e95abc47Szrj 			for (i = 0; i < archive_strlen(&s); i++) {
1067e95abc47Szrj 				if (s.s[i] == '\\')
1068e95abc47Szrj 					s.s[i] = '/';
1069e95abc47Szrj 			}
1070e95abc47Szrj 			archive_entry_copy_pathname_w(entry, s.s);
1071e95abc47Szrj 			archive_wstring_free(&s);
1072e95abc47Szrj 		}
1073e95abc47Szrj 	}
1074e95abc47Szrj 
1075e95abc47Szrj 	/* Make sure that entries with a trailing '/' are marked as directories
1076e95abc47Szrj 	 * even if the External File Attributes contains bogus values.  If this
1077085658deSDaniel Fojt 	 * is not a directory and there is no type, assume a regular file. */
1078e95abc47Szrj 	if ((zip_entry->mode & AE_IFMT) != AE_IFDIR) {
1079e95abc47Szrj 		int has_slash;
1080e95abc47Szrj 
10816b384f39SPeter Avalos 		wp = archive_entry_pathname_w(entry);
10826b384f39SPeter Avalos 		if (wp != NULL) {
10836b384f39SPeter Avalos 			len = wcslen(wp);
1084e95abc47Szrj 			has_slash = len > 0 && wp[len - 1] == L'/';
10856b384f39SPeter Avalos 		} else {
10866b384f39SPeter Avalos 			cp = archive_entry_pathname(entry);
10876b384f39SPeter Avalos 			len = (cp != NULL)?strlen(cp):0;
1088e95abc47Szrj 			has_slash = len > 0 && cp[len - 1] == '/';
10896b384f39SPeter Avalos 		}
1090e95abc47Szrj 		/* Correct file type as needed. */
1091e95abc47Szrj 		if (has_slash) {
1092e95abc47Szrj 			zip_entry->mode &= ~AE_IFMT;
1093e95abc47Szrj 			zip_entry->mode |= AE_IFDIR;
1094e95abc47Szrj 			zip_entry->mode |= 0111;
1095e95abc47Szrj 		} else if ((zip_entry->mode & AE_IFMT) == 0) {
1096e95abc47Szrj 			zip_entry->mode |= AE_IFREG;
10976b384f39SPeter Avalos 		}
10986b384f39SPeter Avalos 	}
10996b384f39SPeter Avalos 
11006b384f39SPeter Avalos 	/* Make sure directories end in '/' */
11016b384f39SPeter Avalos 	if ((zip_entry->mode & AE_IFMT) == AE_IFDIR) {
11026b384f39SPeter Avalos 		wp = archive_entry_pathname_w(entry);
11036b384f39SPeter Avalos 		if (wp != NULL) {
11046b384f39SPeter Avalos 			len = wcslen(wp);
11056b384f39SPeter Avalos 			if (len > 0 && wp[len - 1] != L'/') {
11066b384f39SPeter Avalos 				struct archive_wstring s;
11076b384f39SPeter Avalos 				archive_string_init(&s);
11086b384f39SPeter Avalos 				archive_wstrcat(&s, wp);
11096b384f39SPeter Avalos 				archive_wstrappend_wchar(&s, L'/');
11106b384f39SPeter Avalos 				archive_entry_copy_pathname_w(entry, s.s);
1111e95abc47Szrj 				archive_wstring_free(&s);
11126b384f39SPeter Avalos 			}
11136b384f39SPeter Avalos 		} else {
11146b384f39SPeter Avalos 			cp = archive_entry_pathname(entry);
11156b384f39SPeter Avalos 			len = (cp != NULL)?strlen(cp):0;
11166b384f39SPeter Avalos 			if (len > 0 && cp[len - 1] != '/') {
11176b384f39SPeter Avalos 				struct archive_string s;
11186b384f39SPeter Avalos 				archive_string_init(&s);
11196b384f39SPeter Avalos 				archive_strcat(&s, cp);
11206b384f39SPeter Avalos 				archive_strappend_char(&s, '/');
11216b384f39SPeter Avalos 				archive_entry_set_pathname(entry, s.s);
1122e95abc47Szrj 				archive_string_free(&s);
11236b384f39SPeter Avalos 			}
11246b384f39SPeter Avalos 		}
11256b384f39SPeter Avalos 	}
11266b384f39SPeter Avalos 
11276b384f39SPeter Avalos 	if (zip_entry->flags & LA_FROM_CENTRAL_DIRECTORY) {
1128085658deSDaniel Fojt 		/* If this came from the central dir, its size info
11296b384f39SPeter Avalos 		 * is definitive, so ignore the length-at-end flag. */
11306b384f39SPeter Avalos 		zip_entry->zip_flags &= ~ZIP_LENGTH_AT_END;
11316b384f39SPeter Avalos 		/* If local header is missing a value, use the one from
11326b384f39SPeter Avalos 		   the central directory.  If both have it, warn about
11336b384f39SPeter Avalos 		   mismatches. */
11346b384f39SPeter Avalos 		if (zip_entry->crc32 == 0) {
11356b384f39SPeter Avalos 			zip_entry->crc32 = zip_entry_central_dir.crc32;
11366b384f39SPeter Avalos 		} else if (!zip->ignore_crc32
11376b384f39SPeter Avalos 		    && zip_entry->crc32 != zip_entry_central_dir.crc32) {
11386b384f39SPeter Avalos 			archive_set_error(&a->archive,
11396b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
11406b384f39SPeter Avalos 			    "Inconsistent CRC32 values");
11416b384f39SPeter Avalos 			ret = ARCHIVE_WARN;
11426b384f39SPeter Avalos 		}
11436b384f39SPeter Avalos 		if (zip_entry->compressed_size == 0) {
11446b384f39SPeter Avalos 			zip_entry->compressed_size
11456b384f39SPeter Avalos 			    = zip_entry_central_dir.compressed_size;
11466b384f39SPeter Avalos 		} else if (zip_entry->compressed_size
11476b384f39SPeter Avalos 		    != zip_entry_central_dir.compressed_size) {
11486b384f39SPeter Avalos 			archive_set_error(&a->archive,
11496b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
11506b384f39SPeter Avalos 			    "Inconsistent compressed size: "
11516b384f39SPeter Avalos 			    "%jd in central directory, %jd in local header",
11526b384f39SPeter Avalos 			    (intmax_t)zip_entry_central_dir.compressed_size,
11536b384f39SPeter Avalos 			    (intmax_t)zip_entry->compressed_size);
11546b384f39SPeter Avalos 			ret = ARCHIVE_WARN;
11556b384f39SPeter Avalos 		}
1156*50f8aa9cSAntonio Huete Jimenez 		if (zip_entry->uncompressed_size == 0 ||
1157*50f8aa9cSAntonio Huete Jimenez 			zip_entry->uncompressed_size == 0xffffffff) {
11586b384f39SPeter Avalos 			zip_entry->uncompressed_size
11596b384f39SPeter Avalos 			    = zip_entry_central_dir.uncompressed_size;
11606b384f39SPeter Avalos 		} else if (zip_entry->uncompressed_size
11616b384f39SPeter Avalos 		    != zip_entry_central_dir.uncompressed_size) {
11626b384f39SPeter Avalos 			archive_set_error(&a->archive,
11636b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
11646b384f39SPeter Avalos 			    "Inconsistent uncompressed size: "
11656b384f39SPeter Avalos 			    "%jd in central directory, %jd in local header",
11666b384f39SPeter Avalos 			    (intmax_t)zip_entry_central_dir.uncompressed_size,
11676b384f39SPeter Avalos 			    (intmax_t)zip_entry->uncompressed_size);
11686b384f39SPeter Avalos 			ret = ARCHIVE_WARN;
11696b384f39SPeter Avalos 		}
11706b384f39SPeter Avalos 	}
11716b384f39SPeter Avalos 
11726b384f39SPeter Avalos 	/* Populate some additional entry fields: */
11736b384f39SPeter Avalos 	archive_entry_set_mode(entry, zip_entry->mode);
11746b384f39SPeter Avalos 	archive_entry_set_uid(entry, zip_entry->uid);
11756b384f39SPeter Avalos 	archive_entry_set_gid(entry, zip_entry->gid);
11766b384f39SPeter Avalos 	archive_entry_set_mtime(entry, zip_entry->mtime, 0);
11776b384f39SPeter Avalos 	archive_entry_set_ctime(entry, zip_entry->ctime, 0);
11786b384f39SPeter Avalos 	archive_entry_set_atime(entry, zip_entry->atime, 0);
11796b384f39SPeter Avalos 
11806b384f39SPeter Avalos 	if ((zip->entry->mode & AE_IFMT) == AE_IFLNK) {
11816b384f39SPeter Avalos 		size_t linkname_length;
11826b384f39SPeter Avalos 
11836b384f39SPeter Avalos 		if (zip_entry->compressed_size > 64 * 1024) {
11846b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
11856b384f39SPeter Avalos 			    "Zip file with oversized link entry");
11866b384f39SPeter Avalos 			return ARCHIVE_FATAL;
11876b384f39SPeter Avalos 		}
11886b384f39SPeter Avalos 
11896b384f39SPeter Avalos 		linkname_length = (size_t)zip_entry->compressed_size;
11906b384f39SPeter Avalos 
11916b384f39SPeter Avalos 		archive_entry_set_size(entry, 0);
1192*50f8aa9cSAntonio Huete Jimenez 
1193*50f8aa9cSAntonio Huete Jimenez 		// take into account link compression if any
1194*50f8aa9cSAntonio Huete Jimenez 		size_t linkname_full_length = linkname_length;
1195*50f8aa9cSAntonio Huete Jimenez 		if (zip->entry->compression != 0)
1196*50f8aa9cSAntonio Huete Jimenez 		{
1197*50f8aa9cSAntonio Huete Jimenez 			// symlink target string appeared to be compressed
1198*50f8aa9cSAntonio Huete Jimenez 			int status = ARCHIVE_FATAL;
1199*50f8aa9cSAntonio Huete Jimenez 			const void *uncompressed_buffer = NULL;
1200*50f8aa9cSAntonio Huete Jimenez 
1201*50f8aa9cSAntonio Huete Jimenez 			switch (zip->entry->compression)
1202*50f8aa9cSAntonio Huete Jimenez 			{
1203*50f8aa9cSAntonio Huete Jimenez #if HAVE_ZLIB_H
1204*50f8aa9cSAntonio Huete Jimenez 				case 8: /* Deflate compression. */
1205*50f8aa9cSAntonio Huete Jimenez 					zip->entry_bytes_remaining = zip_entry->compressed_size;
1206*50f8aa9cSAntonio Huete Jimenez 					status = zip_read_data_deflate(a, &uncompressed_buffer,
1207*50f8aa9cSAntonio Huete Jimenez 						&linkname_full_length, NULL);
1208*50f8aa9cSAntonio Huete Jimenez 					break;
1209*50f8aa9cSAntonio Huete Jimenez #endif
1210*50f8aa9cSAntonio Huete Jimenez #if HAVE_LZMA_H && HAVE_LIBLZMA
1211*50f8aa9cSAntonio Huete Jimenez 				case 14: /* ZIPx LZMA compression. */
1212*50f8aa9cSAntonio Huete Jimenez 					/*(see zip file format specification, section 4.4.5)*/
1213*50f8aa9cSAntonio Huete Jimenez 					zip->entry_bytes_remaining = zip_entry->compressed_size;
1214*50f8aa9cSAntonio Huete Jimenez 					status = zip_read_data_zipx_lzma_alone(a, &uncompressed_buffer,
1215*50f8aa9cSAntonio Huete Jimenez 						&linkname_full_length, NULL);
1216*50f8aa9cSAntonio Huete Jimenez 					break;
1217*50f8aa9cSAntonio Huete Jimenez #endif
1218*50f8aa9cSAntonio Huete Jimenez 				default: /* Unsupported compression. */
1219*50f8aa9cSAntonio Huete Jimenez 					break;
1220*50f8aa9cSAntonio Huete Jimenez 			}
1221*50f8aa9cSAntonio Huete Jimenez 			if (status == ARCHIVE_OK)
1222*50f8aa9cSAntonio Huete Jimenez 			{
1223*50f8aa9cSAntonio Huete Jimenez 				p = uncompressed_buffer;
1224*50f8aa9cSAntonio Huete Jimenez 			}
1225*50f8aa9cSAntonio Huete Jimenez 			else
1226*50f8aa9cSAntonio Huete Jimenez 			{
1227*50f8aa9cSAntonio Huete Jimenez 				archive_set_error(&a->archive,
1228*50f8aa9cSAntonio Huete Jimenez 					ARCHIVE_ERRNO_FILE_FORMAT,
1229*50f8aa9cSAntonio Huete Jimenez 					"Unsupported ZIP compression method "
1230*50f8aa9cSAntonio Huete Jimenez 					"during decompression of link entry (%d: %s)",
1231*50f8aa9cSAntonio Huete Jimenez 					zip->entry->compression,
1232*50f8aa9cSAntonio Huete Jimenez 					compression_name(zip->entry->compression));
1233*50f8aa9cSAntonio Huete Jimenez 				return ARCHIVE_FAILED;
1234*50f8aa9cSAntonio Huete Jimenez 			}
1235*50f8aa9cSAntonio Huete Jimenez 		}
1236*50f8aa9cSAntonio Huete Jimenez 		else
1237*50f8aa9cSAntonio Huete Jimenez 		{
12386b384f39SPeter Avalos 			p = __archive_read_ahead(a, linkname_length, NULL);
1239*50f8aa9cSAntonio Huete Jimenez 		}
1240*50f8aa9cSAntonio Huete Jimenez 
12416b384f39SPeter Avalos 		if (p == NULL) {
12426b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
12436b384f39SPeter Avalos 			    "Truncated Zip file");
12446b384f39SPeter Avalos 			return ARCHIVE_FATAL;
12456b384f39SPeter Avalos 		}
12466b384f39SPeter Avalos 
12476b384f39SPeter Avalos 		sconv = zip->sconv;
12486b384f39SPeter Avalos 		if (sconv == NULL && (zip->entry->zip_flags & ZIP_UTF8_NAME))
12496b384f39SPeter Avalos 			sconv = zip->sconv_utf8;
12506b384f39SPeter Avalos 		if (sconv == NULL)
12516b384f39SPeter Avalos 			sconv = zip->sconv_default;
1252*50f8aa9cSAntonio Huete Jimenez 		if (archive_entry_copy_symlink_l(entry, p, linkname_full_length,
12536b384f39SPeter Avalos 		    sconv) != 0) {
12546b384f39SPeter Avalos 			if (errno != ENOMEM && sconv == zip->sconv_utf8 &&
12556b384f39SPeter Avalos 			    (zip->entry->zip_flags & ZIP_UTF8_NAME))
12566b384f39SPeter Avalos 			    archive_entry_copy_symlink_l(entry, p,
1257*50f8aa9cSAntonio Huete Jimenez 				linkname_full_length, NULL);
12586b384f39SPeter Avalos 			if (errno == ENOMEM) {
12596b384f39SPeter Avalos 				archive_set_error(&a->archive, ENOMEM,
12606b384f39SPeter Avalos 				    "Can't allocate memory for Symlink");
12616b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
12626b384f39SPeter Avalos 			}
12636b384f39SPeter Avalos 			/*
12646b384f39SPeter Avalos 			 * Since there is no character-set regulation for
12656b384f39SPeter Avalos 			 * symlink name, do not report the conversion error
12666b384f39SPeter Avalos 			 * in an automatic conversion.
12676b384f39SPeter Avalos 			 */
12686b384f39SPeter Avalos 			if (sconv != zip->sconv_utf8 ||
12696b384f39SPeter Avalos 			    (zip->entry->zip_flags & ZIP_UTF8_NAME) == 0) {
12706b384f39SPeter Avalos 				archive_set_error(&a->archive,
12716b384f39SPeter Avalos 				    ARCHIVE_ERRNO_FILE_FORMAT,
12726b384f39SPeter Avalos 				    "Symlink cannot be converted "
12736b384f39SPeter Avalos 				    "from %s to current locale.",
12746b384f39SPeter Avalos 				    archive_string_conversion_charset_name(
12756b384f39SPeter Avalos 					sconv));
12766b384f39SPeter Avalos 				ret = ARCHIVE_WARN;
12776b384f39SPeter Avalos 			}
12786b384f39SPeter Avalos 		}
12796b384f39SPeter Avalos 		zip_entry->uncompressed_size = zip_entry->compressed_size = 0;
12806b384f39SPeter Avalos 
12816b384f39SPeter Avalos 		if (__archive_read_consume(a, linkname_length) < 0) {
12826b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
12836b384f39SPeter Avalos 			    "Read error skipping symlink target name");
12846b384f39SPeter Avalos 			return ARCHIVE_FATAL;
12856b384f39SPeter Avalos 		}
12866b384f39SPeter Avalos 	} else if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
12876b384f39SPeter Avalos 	    || zip_entry->uncompressed_size > 0) {
12886b384f39SPeter Avalos 		/* Set the size only if it's meaningful. */
12896b384f39SPeter Avalos 		archive_entry_set_size(entry, zip_entry->uncompressed_size);
12906b384f39SPeter Avalos 	}
12916b384f39SPeter Avalos 	zip->entry_bytes_remaining = zip_entry->compressed_size;
12926b384f39SPeter Avalos 
12936b384f39SPeter Avalos 	/* If there's no body, force read_data() to return EOF immediately. */
12946b384f39SPeter Avalos 	if (0 == (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
12956b384f39SPeter Avalos 	    && zip->entry_bytes_remaining < 1)
12966b384f39SPeter Avalos 		zip->end_of_entry = 1;
12976b384f39SPeter Avalos 
12986b384f39SPeter Avalos 	/* Set up a more descriptive format name. */
1299e95abc47Szrj         archive_string_empty(&zip->format_name);
13006b384f39SPeter Avalos 	archive_string_sprintf(&zip->format_name, "ZIP %d.%d (%s)",
13016b384f39SPeter Avalos 	    version / 10, version % 10,
13026b384f39SPeter Avalos 	    compression_name(zip->entry->compression));
13036b384f39SPeter Avalos 	a->archive.archive_format_name = zip->format_name.s;
13046b384f39SPeter Avalos 
13056b384f39SPeter Avalos 	return (ret);
13066b384f39SPeter Avalos }
13076b384f39SPeter Avalos 
13086b384f39SPeter Avalos static int
check_authentication_code(struct archive_read * a,const void * _p)13096b384f39SPeter Avalos check_authentication_code(struct archive_read *a, const void *_p)
13106b384f39SPeter Avalos {
13116b384f39SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
13126b384f39SPeter Avalos 
13136b384f39SPeter Avalos 	/* Check authentication code. */
13146b384f39SPeter Avalos 	if (zip->hctx_valid) {
13156b384f39SPeter Avalos 		const void *p;
13166b384f39SPeter Avalos 		uint8_t hmac[20];
13176b384f39SPeter Avalos 		size_t hmac_len = 20;
13186b384f39SPeter Avalos 		int cmp;
13196b384f39SPeter Avalos 
13206b384f39SPeter Avalos 		archive_hmac_sha1_final(&zip->hctx, hmac, &hmac_len);
13216b384f39SPeter Avalos 		if (_p == NULL) {
13226b384f39SPeter Avalos 			/* Read authentication code. */
13236b384f39SPeter Avalos 			p = __archive_read_ahead(a, AUTH_CODE_SIZE, NULL);
13246b384f39SPeter Avalos 			if (p == NULL) {
13256b384f39SPeter Avalos 				archive_set_error(&a->archive,
13266b384f39SPeter Avalos 				    ARCHIVE_ERRNO_FILE_FORMAT,
13276b384f39SPeter Avalos 				    "Truncated ZIP file data");
13286b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
13296b384f39SPeter Avalos 			}
13306b384f39SPeter Avalos 		} else {
13316b384f39SPeter Avalos 			p = _p;
13326b384f39SPeter Avalos 		}
13336b384f39SPeter Avalos 		cmp = memcmp(hmac, p, AUTH_CODE_SIZE);
13346b384f39SPeter Avalos 		__archive_read_consume(a, AUTH_CODE_SIZE);
13356b384f39SPeter Avalos 		if (cmp != 0) {
13366b384f39SPeter Avalos 			archive_set_error(&a->archive,
13376b384f39SPeter Avalos 			    ARCHIVE_ERRNO_MISC,
13386b384f39SPeter Avalos 			    "ZIP bad Authentication code");
13396b384f39SPeter Avalos 			return (ARCHIVE_WARN);
13406b384f39SPeter Avalos 		}
13416b384f39SPeter Avalos 	}
13426b384f39SPeter Avalos 	return (ARCHIVE_OK);
13436b384f39SPeter Avalos }
13446b384f39SPeter Avalos 
13456b384f39SPeter Avalos /*
13466b384f39SPeter Avalos  * Read "uncompressed" data.  There are three cases:
13476b384f39SPeter Avalos  *  1) We know the size of the data.  This is always true for the
13486b384f39SPeter Avalos  * seeking reader (we've examined the Central Directory already).
13496b384f39SPeter Avalos  *  2) ZIP_LENGTH_AT_END was set, but only the CRC was deferred.
13506b384f39SPeter Avalos  * Info-ZIP seems to do this; we know the size but have to grab
13516b384f39SPeter Avalos  * the CRC from the data descriptor afterwards.
13526b384f39SPeter Avalos  *  3) We're streaming and ZIP_LENGTH_AT_END was specified and
13536b384f39SPeter Avalos  * we have no size information.  In this case, we can do pretty
13546b384f39SPeter Avalos  * well by watching for the data descriptor record.  The data
13556b384f39SPeter Avalos  * descriptor is 16 bytes and includes a computed CRC that should
13566b384f39SPeter Avalos  * provide a strong check.
13576b384f39SPeter Avalos  *
13586b384f39SPeter Avalos  * TODO: Technically, the PK\007\010 signature is optional.
13596b384f39SPeter Avalos  * In the original spec, the data descriptor contained CRC
13606b384f39SPeter Avalos  * and size fields but had no leading signature.  In practice,
13616b384f39SPeter Avalos  * newer writers seem to provide the signature pretty consistently.
13626b384f39SPeter Avalos  *
13636b384f39SPeter Avalos  * For uncompressed data, the PK\007\010 marker seems essential
13646b384f39SPeter Avalos  * to be sure we've actually seen the end of the entry.
13656b384f39SPeter Avalos  *
13666b384f39SPeter Avalos  * Returns ARCHIVE_OK if successful, ARCHIVE_FATAL otherwise, sets
13676b384f39SPeter Avalos  * zip->end_of_entry if it consumes all of the data.
13686b384f39SPeter Avalos  */
13696b384f39SPeter Avalos static int
zip_read_data_none(struct archive_read * a,const void ** _buff,size_t * size,int64_t * offset)13706b384f39SPeter Avalos zip_read_data_none(struct archive_read *a, const void **_buff,
13716b384f39SPeter Avalos     size_t *size, int64_t *offset)
13726b384f39SPeter Avalos {
13736b384f39SPeter Avalos 	struct zip *zip;
13746b384f39SPeter Avalos 	const char *buff;
13756b384f39SPeter Avalos 	ssize_t bytes_avail;
13766b384f39SPeter Avalos 	int r;
13776b384f39SPeter Avalos 
13786b384f39SPeter Avalos 	(void)offset; /* UNUSED */
13796b384f39SPeter Avalos 
13806b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
13816b384f39SPeter Avalos 
13826b384f39SPeter Avalos 	if (zip->entry->zip_flags & ZIP_LENGTH_AT_END) {
13836b384f39SPeter Avalos 		const char *p;
13846b384f39SPeter Avalos 		ssize_t grabbing_bytes = 24;
13856b384f39SPeter Avalos 
13866b384f39SPeter Avalos 		if (zip->hctx_valid)
13876b384f39SPeter Avalos 			grabbing_bytes += AUTH_CODE_SIZE;
13886b384f39SPeter Avalos 		/* Grab at least 24 bytes. */
13896b384f39SPeter Avalos 		buff = __archive_read_ahead(a, grabbing_bytes, &bytes_avail);
13906b384f39SPeter Avalos 		if (bytes_avail < grabbing_bytes) {
13916b384f39SPeter Avalos 			/* Zip archives have end-of-archive markers
13926b384f39SPeter Avalos 			   that are longer than this, so a failure to get at
13936b384f39SPeter Avalos 			   least 24 bytes really does indicate a truncated
13946b384f39SPeter Avalos 			   file. */
13956b384f39SPeter Avalos 			archive_set_error(&a->archive,
13966b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
13976b384f39SPeter Avalos 			    "Truncated ZIP file data");
13986b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
13996b384f39SPeter Avalos 		}
14006b384f39SPeter Avalos 		/* Check for a complete PK\007\010 signature, followed
14016b384f39SPeter Avalos 		 * by the correct 4-byte CRC. */
14026b384f39SPeter Avalos 		p = buff;
14036b384f39SPeter Avalos 		if (zip->hctx_valid)
14046b384f39SPeter Avalos 			p += AUTH_CODE_SIZE;
14056b384f39SPeter Avalos 		if (p[0] == 'P' && p[1] == 'K'
14066b384f39SPeter Avalos 		    && p[2] == '\007' && p[3] == '\010'
14076b384f39SPeter Avalos 		    && (archive_le32dec(p + 4) == zip->entry_crc32
14086b384f39SPeter Avalos 			|| zip->ignore_crc32
14096b384f39SPeter Avalos 			|| (zip->hctx_valid
14106b384f39SPeter Avalos 			 && zip->entry->aes_extra.vendor == AES_VENDOR_AE_2))) {
14116b384f39SPeter Avalos 			if (zip->entry->flags & LA_USED_ZIP64) {
1412e95abc47Szrj 				uint64_t compressed, uncompressed;
14136b384f39SPeter Avalos 				zip->entry->crc32 = archive_le32dec(p + 4);
1414e95abc47Szrj 				compressed = archive_le64dec(p + 8);
1415e95abc47Szrj 				uncompressed = archive_le64dec(p + 16);
1416085658deSDaniel Fojt 				if (compressed > INT64_MAX || uncompressed >
1417085658deSDaniel Fojt 				    INT64_MAX) {
1418e95abc47Szrj 					archive_set_error(&a->archive,
1419e95abc47Szrj 					    ARCHIVE_ERRNO_FILE_FORMAT,
1420e95abc47Szrj 					    "Overflow of 64-bit file sizes");
1421e95abc47Szrj 					return ARCHIVE_FAILED;
1422e95abc47Szrj 				}
1423e95abc47Szrj 				zip->entry->compressed_size = compressed;
1424e95abc47Szrj 				zip->entry->uncompressed_size = uncompressed;
14256b384f39SPeter Avalos 				zip->unconsumed = 24;
14266b384f39SPeter Avalos 			} else {
14276b384f39SPeter Avalos 				zip->entry->crc32 = archive_le32dec(p + 4);
14286b384f39SPeter Avalos 				zip->entry->compressed_size =
14296b384f39SPeter Avalos 					archive_le32dec(p + 8);
14306b384f39SPeter Avalos 				zip->entry->uncompressed_size =
14316b384f39SPeter Avalos 					archive_le32dec(p + 12);
14326b384f39SPeter Avalos 				zip->unconsumed = 16;
14336b384f39SPeter Avalos 			}
14346b384f39SPeter Avalos 			if (zip->hctx_valid) {
14356b384f39SPeter Avalos 				r = check_authentication_code(a, buff);
14366b384f39SPeter Avalos 				if (r != ARCHIVE_OK)
14376b384f39SPeter Avalos 					return (r);
14386b384f39SPeter Avalos 			}
14396b384f39SPeter Avalos 			zip->end_of_entry = 1;
14406b384f39SPeter Avalos 			return (ARCHIVE_OK);
14416b384f39SPeter Avalos 		}
14426b384f39SPeter Avalos 		/* If not at EOF, ensure we consume at least one byte. */
14436b384f39SPeter Avalos 		++p;
14446b384f39SPeter Avalos 
14456b384f39SPeter Avalos 		/* Scan forward until we see where a PK\007\010 signature
14466b384f39SPeter Avalos 		 * might be. */
14476b384f39SPeter Avalos 		/* Return bytes up until that point.  On the next call,
14486b384f39SPeter Avalos 		 * the code above will verify the data descriptor. */
14496b384f39SPeter Avalos 		while (p < buff + bytes_avail - 4) {
14506b384f39SPeter Avalos 			if (p[3] == 'P') { p += 3; }
14516b384f39SPeter Avalos 			else if (p[3] == 'K') { p += 2; }
14526b384f39SPeter Avalos 			else if (p[3] == '\007') { p += 1; }
14536b384f39SPeter Avalos 			else if (p[3] == '\010' && p[2] == '\007'
14546b384f39SPeter Avalos 			    && p[1] == 'K' && p[0] == 'P') {
14556b384f39SPeter Avalos 				if (zip->hctx_valid)
14566b384f39SPeter Avalos 					p -= AUTH_CODE_SIZE;
14576b384f39SPeter Avalos 				break;
14586b384f39SPeter Avalos 			} else { p += 4; }
14596b384f39SPeter Avalos 		}
14606b384f39SPeter Avalos 		bytes_avail = p - buff;
14616b384f39SPeter Avalos 	} else {
14626b384f39SPeter Avalos 		if (zip->entry_bytes_remaining == 0) {
14636b384f39SPeter Avalos 			zip->end_of_entry = 1;
14646b384f39SPeter Avalos 			if (zip->hctx_valid) {
14656b384f39SPeter Avalos 				r = check_authentication_code(a, NULL);
14666b384f39SPeter Avalos 				if (r != ARCHIVE_OK)
14676b384f39SPeter Avalos 					return (r);
14686b384f39SPeter Avalos 			}
14696b384f39SPeter Avalos 			return (ARCHIVE_OK);
14706b384f39SPeter Avalos 		}
14716b384f39SPeter Avalos 		/* Grab a bunch of bytes. */
14726b384f39SPeter Avalos 		buff = __archive_read_ahead(a, 1, &bytes_avail);
14736b384f39SPeter Avalos 		if (bytes_avail <= 0) {
14746b384f39SPeter Avalos 			archive_set_error(&a->archive,
14756b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
14766b384f39SPeter Avalos 			    "Truncated ZIP file data");
14776b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
14786b384f39SPeter Avalos 		}
14796b384f39SPeter Avalos 		if (bytes_avail > zip->entry_bytes_remaining)
14806b384f39SPeter Avalos 			bytes_avail = (ssize_t)zip->entry_bytes_remaining;
14816b384f39SPeter Avalos 	}
14826b384f39SPeter Avalos 	if (zip->tctx_valid || zip->cctx_valid) {
14836b384f39SPeter Avalos 		size_t dec_size = bytes_avail;
14846b384f39SPeter Avalos 
14856b384f39SPeter Avalos 		if (dec_size > zip->decrypted_buffer_size)
14866b384f39SPeter Avalos 			dec_size = zip->decrypted_buffer_size;
14876b384f39SPeter Avalos 		if (zip->tctx_valid) {
14886b384f39SPeter Avalos 			trad_enc_decrypt_update(&zip->tctx,
14896b384f39SPeter Avalos 			    (const uint8_t *)buff, dec_size,
14906b384f39SPeter Avalos 			    zip->decrypted_buffer, dec_size);
14916b384f39SPeter Avalos 		} else {
14926b384f39SPeter Avalos 			size_t dsize = dec_size;
14936b384f39SPeter Avalos 			archive_hmac_sha1_update(&zip->hctx,
14946b384f39SPeter Avalos 			    (const uint8_t *)buff, dec_size);
14956b384f39SPeter Avalos 			archive_decrypto_aes_ctr_update(&zip->cctx,
14966b384f39SPeter Avalos 			    (const uint8_t *)buff, dec_size,
14976b384f39SPeter Avalos 			    zip->decrypted_buffer, &dsize);
14986b384f39SPeter Avalos 		}
14996b384f39SPeter Avalos 		bytes_avail = dec_size;
15006b384f39SPeter Avalos 		buff = (const char *)zip->decrypted_buffer;
15016b384f39SPeter Avalos 	}
15026b384f39SPeter Avalos 	*size = bytes_avail;
15036b384f39SPeter Avalos 	zip->entry_bytes_remaining -= bytes_avail;
15046b384f39SPeter Avalos 	zip->entry_uncompressed_bytes_read += bytes_avail;
15056b384f39SPeter Avalos 	zip->entry_compressed_bytes_read += bytes_avail;
15066b384f39SPeter Avalos 	zip->unconsumed += bytes_avail;
15076b384f39SPeter Avalos 	*_buff = buff;
15086b384f39SPeter Avalos 	return (ARCHIVE_OK);
15096b384f39SPeter Avalos }
15106b384f39SPeter Avalos 
1511085658deSDaniel Fojt static int
consume_optional_marker(struct archive_read * a,struct zip * zip)1512085658deSDaniel Fojt consume_optional_marker(struct archive_read *a, struct zip *zip)
1513085658deSDaniel Fojt {
1514085658deSDaniel Fojt 	if (zip->end_of_entry && (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) {
1515085658deSDaniel Fojt 		const char *p;
1516085658deSDaniel Fojt 
1517085658deSDaniel Fojt 		if (NULL == (p = __archive_read_ahead(a, 24, NULL))) {
1518085658deSDaniel Fojt 			archive_set_error(&a->archive,
1519085658deSDaniel Fojt 			    ARCHIVE_ERRNO_FILE_FORMAT,
1520085658deSDaniel Fojt 			    "Truncated ZIP end-of-file record");
1521085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
1522085658deSDaniel Fojt 		}
1523085658deSDaniel Fojt 		/* Consume the optional PK\007\010 marker. */
1524085658deSDaniel Fojt 		if (p[0] == 'P' && p[1] == 'K' &&
1525085658deSDaniel Fojt 		    p[2] == '\007' && p[3] == '\010') {
1526085658deSDaniel Fojt 			p += 4;
1527085658deSDaniel Fojt 			zip->unconsumed = 4;
1528085658deSDaniel Fojt 		}
1529085658deSDaniel Fojt 		if (zip->entry->flags & LA_USED_ZIP64) {
1530085658deSDaniel Fojt 			uint64_t compressed, uncompressed;
1531085658deSDaniel Fojt 			zip->entry->crc32 = archive_le32dec(p);
1532085658deSDaniel Fojt 			compressed = archive_le64dec(p + 4);
1533085658deSDaniel Fojt 			uncompressed = archive_le64dec(p + 12);
1534085658deSDaniel Fojt 			if (compressed > INT64_MAX ||
1535085658deSDaniel Fojt 			    uncompressed > INT64_MAX) {
1536085658deSDaniel Fojt 				archive_set_error(&a->archive,
1537085658deSDaniel Fojt 				    ARCHIVE_ERRNO_FILE_FORMAT,
1538085658deSDaniel Fojt 				    "Overflow of 64-bit file sizes");
1539085658deSDaniel Fojt 				return ARCHIVE_FAILED;
1540085658deSDaniel Fojt 			}
1541085658deSDaniel Fojt 			zip->entry->compressed_size = compressed;
1542085658deSDaniel Fojt 			zip->entry->uncompressed_size = uncompressed;
1543085658deSDaniel Fojt 			zip->unconsumed += 20;
1544085658deSDaniel Fojt 		} else {
1545085658deSDaniel Fojt 			zip->entry->crc32 = archive_le32dec(p);
1546085658deSDaniel Fojt 			zip->entry->compressed_size = archive_le32dec(p + 4);
1547085658deSDaniel Fojt 			zip->entry->uncompressed_size = archive_le32dec(p + 8);
1548085658deSDaniel Fojt 			zip->unconsumed += 12;
1549085658deSDaniel Fojt 		}
1550085658deSDaniel Fojt 	}
1551085658deSDaniel Fojt 
1552085658deSDaniel Fojt     return (ARCHIVE_OK);
1553085658deSDaniel Fojt }
1554085658deSDaniel Fojt 
1555085658deSDaniel Fojt #if HAVE_LZMA_H && HAVE_LIBLZMA
1556085658deSDaniel Fojt static int
zipx_xz_init(struct archive_read * a,struct zip * zip)1557085658deSDaniel Fojt zipx_xz_init(struct archive_read *a, struct zip *zip)
1558085658deSDaniel Fojt {
1559085658deSDaniel Fojt 	lzma_ret r;
1560085658deSDaniel Fojt 
1561085658deSDaniel Fojt 	if(zip->zipx_lzma_valid) {
1562085658deSDaniel Fojt 		lzma_end(&zip->zipx_lzma_stream);
1563085658deSDaniel Fojt 		zip->zipx_lzma_valid = 0;
1564085658deSDaniel Fojt 	}
1565085658deSDaniel Fojt 
1566085658deSDaniel Fojt 	memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
1567085658deSDaniel Fojt 	r = lzma_stream_decoder(&zip->zipx_lzma_stream, UINT64_MAX, 0);
1568085658deSDaniel Fojt 	if (r != LZMA_OK) {
1569085658deSDaniel Fojt 		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
1570085658deSDaniel Fojt 		    "xz initialization failed(%d)",
1571085658deSDaniel Fojt 		    r);
1572085658deSDaniel Fojt 
1573085658deSDaniel Fojt 		return (ARCHIVE_FAILED);
1574085658deSDaniel Fojt 	}
1575085658deSDaniel Fojt 
1576085658deSDaniel Fojt 	zip->zipx_lzma_valid = 1;
1577085658deSDaniel Fojt 
1578085658deSDaniel Fojt 	free(zip->uncompressed_buffer);
1579085658deSDaniel Fojt 
1580085658deSDaniel Fojt 	zip->uncompressed_buffer_size = 256 * 1024;
1581085658deSDaniel Fojt 	zip->uncompressed_buffer =
1582085658deSDaniel Fojt 	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
1583085658deSDaniel Fojt 	if (zip->uncompressed_buffer == NULL) {
1584085658deSDaniel Fojt 		archive_set_error(&a->archive, ENOMEM,
1585085658deSDaniel Fojt 		    "No memory for xz decompression");
1586085658deSDaniel Fojt 		    return (ARCHIVE_FATAL);
1587085658deSDaniel Fojt 	}
1588085658deSDaniel Fojt 
1589085658deSDaniel Fojt 	zip->decompress_init = 1;
1590085658deSDaniel Fojt 	return (ARCHIVE_OK);
1591085658deSDaniel Fojt }
1592085658deSDaniel Fojt 
1593085658deSDaniel Fojt static int
zipx_lzma_alone_init(struct archive_read * a,struct zip * zip)1594085658deSDaniel Fojt zipx_lzma_alone_init(struct archive_read *a, struct zip *zip)
1595085658deSDaniel Fojt {
1596085658deSDaniel Fojt 	lzma_ret r;
1597085658deSDaniel Fojt 	const uint8_t* p;
1598085658deSDaniel Fojt 
1599085658deSDaniel Fojt #pragma pack(push)
1600085658deSDaniel Fojt #pragma pack(1)
1601085658deSDaniel Fojt 	struct _alone_header {
1602085658deSDaniel Fojt 	    uint8_t bytes[5];
1603085658deSDaniel Fojt 	    uint64_t uncompressed_size;
1604085658deSDaniel Fojt 	} alone_header;
1605085658deSDaniel Fojt #pragma pack(pop)
1606085658deSDaniel Fojt 
1607085658deSDaniel Fojt 	if(zip->zipx_lzma_valid) {
1608085658deSDaniel Fojt 		lzma_end(&zip->zipx_lzma_stream);
1609085658deSDaniel Fojt 		zip->zipx_lzma_valid = 0;
1610085658deSDaniel Fojt 	}
1611085658deSDaniel Fojt 
1612085658deSDaniel Fojt 	/* To unpack ZIPX's "LZMA" (id 14) stream we can use standard liblzma
1613085658deSDaniel Fojt 	 * that is a part of XZ Utils. The stream format stored inside ZIPX
1614085658deSDaniel Fojt 	 * file is a modified "lzma alone" file format, that was used by the
1615*50f8aa9cSAntonio Huete Jimenez 	 * `lzma` utility which was later deprecated in favour of `xz` utility.
1616*50f8aa9cSAntonio Huete Jimenez  	 * Since those formats are nearly the same, we can use a standard
1617085658deSDaniel Fojt 	 * "lzma alone" decoder from XZ Utils. */
1618085658deSDaniel Fojt 
1619085658deSDaniel Fojt 	memset(&zip->zipx_lzma_stream, 0, sizeof(zip->zipx_lzma_stream));
1620085658deSDaniel Fojt 	r = lzma_alone_decoder(&zip->zipx_lzma_stream, UINT64_MAX);
1621085658deSDaniel Fojt 	if (r != LZMA_OK) {
1622085658deSDaniel Fojt 		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
1623085658deSDaniel Fojt 		    "lzma initialization failed(%d)", r);
1624085658deSDaniel Fojt 
1625085658deSDaniel Fojt 		return (ARCHIVE_FAILED);
1626085658deSDaniel Fojt 	}
1627085658deSDaniel Fojt 
1628085658deSDaniel Fojt 	/* Flag the cleanup function that we want our lzma-related structures
1629085658deSDaniel Fojt 	 * to be freed later. */
1630085658deSDaniel Fojt 	zip->zipx_lzma_valid = 1;
1631085658deSDaniel Fojt 
1632085658deSDaniel Fojt 	/* The "lzma alone" file format and the stream format inside ZIPx are
1633085658deSDaniel Fojt 	 * almost the same. Here's an example of a structure of "lzma alone"
1634085658deSDaniel Fojt 	 * format:
1635085658deSDaniel Fojt 	 *
1636085658deSDaniel Fojt 	 * $ cat /bin/ls | lzma | xxd | head -n 1
1637085658deSDaniel Fojt 	 * 00000000: 5d00 0080 00ff ffff ffff ffff ff00 2814
1638085658deSDaniel Fojt 	 *
1639085658deSDaniel Fojt 	 *    5 bytes        8 bytes        n bytes
1640085658deSDaniel Fojt 	 * <lzma_params><uncompressed_size><data...>
1641085658deSDaniel Fojt 	 *
1642085658deSDaniel Fojt 	 * lzma_params is a 5-byte blob that has to be decoded to extract
1643085658deSDaniel Fojt 	 * parameters of this LZMA stream. The uncompressed_size field is an
1644085658deSDaniel Fojt 	 * uint64_t value that contains information about the size of the
1645085658deSDaniel Fojt 	 * uncompressed file, or UINT64_MAX if this value is unknown.
1646085658deSDaniel Fojt 	 * The <data...> part is the actual lzma-compressed data stream.
1647085658deSDaniel Fojt 	 *
1648085658deSDaniel Fojt 	 * Now here's the structure of the stream inside the ZIPX file:
1649085658deSDaniel Fojt 	 *
1650085658deSDaniel Fojt 	 * $ cat stream_inside_zipx | xxd | head -n 1
1651085658deSDaniel Fojt 	 * 00000000: 0914 0500 5d00 8000 0000 2814 .... ....
1652085658deSDaniel Fojt 	 *
1653085658deSDaniel Fojt 	 *  2byte   2byte    5 bytes     n bytes
1654085658deSDaniel Fojt 	 * <magic1><magic2><lzma_params><data...>
1655085658deSDaniel Fojt 	 *
1656085658deSDaniel Fojt 	 * This means that the ZIPX file contains an additional magic1 and
1657085658deSDaniel Fojt 	 * magic2 headers, the lzma_params field contains the same parameter
1658085658deSDaniel Fojt 	 * set as in the "lzma alone" format, and the <data...> field is the
1659085658deSDaniel Fojt 	 * same as in the "lzma alone" format as well. Note that also the zipx
1660085658deSDaniel Fojt 	 * format is missing the uncompressed_size field.
1661085658deSDaniel Fojt 	 *
1662085658deSDaniel Fojt 	 * So, in order to use the "lzma alone" decoder for the zipx lzma
1663085658deSDaniel Fojt 	 * stream, we simply need to shuffle around some fields, prepare a new
1664085658deSDaniel Fojt 	 * lzma alone header, feed it into lzma alone decoder so it will
1665085658deSDaniel Fojt 	 * initialize itself properly, and then we can start feeding normal
1666085658deSDaniel Fojt 	 * zipx lzma stream into the decoder.
1667085658deSDaniel Fojt 	 */
1668085658deSDaniel Fojt 
1669085658deSDaniel Fojt 	/* Read magic1,magic2,lzma_params from the ZIPX stream. */
1670*50f8aa9cSAntonio Huete Jimenez 	if(zip->entry_bytes_remaining < 9 || (p = __archive_read_ahead(a, 9, NULL)) == NULL) {
1671085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1672085658deSDaniel Fojt 		    "Truncated lzma data");
1673085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1674085658deSDaniel Fojt 	}
1675085658deSDaniel Fojt 
1676085658deSDaniel Fojt 	if(p[2] != 0x05 || p[3] != 0x00) {
1677085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1678085658deSDaniel Fojt 		    "Invalid lzma data");
1679085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1680085658deSDaniel Fojt 	}
1681085658deSDaniel Fojt 
1682085658deSDaniel Fojt 	/* Prepare an lzma alone header: copy the lzma_params blob into
1683085658deSDaniel Fojt 	 * a proper place into the lzma alone header. */
1684085658deSDaniel Fojt 	memcpy(&alone_header.bytes[0], p + 4, 5);
1685085658deSDaniel Fojt 
1686085658deSDaniel Fojt 	/* Initialize the 'uncompressed size' field to unknown; we'll manually
1687085658deSDaniel Fojt 	 * monitor how many bytes there are still to be uncompressed. */
1688085658deSDaniel Fojt 	alone_header.uncompressed_size = UINT64_MAX;
1689085658deSDaniel Fojt 
1690085658deSDaniel Fojt 	if(!zip->uncompressed_buffer) {
1691085658deSDaniel Fojt 		zip->uncompressed_buffer_size = 256 * 1024;
1692085658deSDaniel Fojt 		zip->uncompressed_buffer =
1693085658deSDaniel Fojt 			(uint8_t*) malloc(zip->uncompressed_buffer_size);
1694085658deSDaniel Fojt 
1695085658deSDaniel Fojt 		if (zip->uncompressed_buffer == NULL) {
1696085658deSDaniel Fojt 			archive_set_error(&a->archive, ENOMEM,
1697085658deSDaniel Fojt 			    "No memory for lzma decompression");
1698085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
1699085658deSDaniel Fojt 		}
1700085658deSDaniel Fojt 	}
1701085658deSDaniel Fojt 
1702085658deSDaniel Fojt 	zip->zipx_lzma_stream.next_in = (void*) &alone_header;
1703085658deSDaniel Fojt 	zip->zipx_lzma_stream.avail_in = sizeof(alone_header);
1704085658deSDaniel Fojt 	zip->zipx_lzma_stream.total_in = 0;
1705085658deSDaniel Fojt 	zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
1706085658deSDaniel Fojt 	zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size;
1707085658deSDaniel Fojt 	zip->zipx_lzma_stream.total_out = 0;
1708085658deSDaniel Fojt 
1709085658deSDaniel Fojt 	/* Feed only the header into the lzma alone decoder. This will
1710085658deSDaniel Fojt 	 * effectively initialize the decoder, and will not produce any
1711085658deSDaniel Fojt 	 * output bytes yet. */
1712085658deSDaniel Fojt 	r = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
1713085658deSDaniel Fojt 	if (r != LZMA_OK) {
1714085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
1715085658deSDaniel Fojt 		    "lzma stream initialization error");
1716085658deSDaniel Fojt 		return ARCHIVE_FATAL;
1717085658deSDaniel Fojt 	}
1718085658deSDaniel Fojt 
1719085658deSDaniel Fojt 	/* We've already consumed some bytes, so take this into account. */
1720085658deSDaniel Fojt 	__archive_read_consume(a, 9);
1721085658deSDaniel Fojt 	zip->entry_bytes_remaining -= 9;
1722085658deSDaniel Fojt 	zip->entry_compressed_bytes_read += 9;
1723085658deSDaniel Fojt 
1724085658deSDaniel Fojt 	zip->decompress_init = 1;
1725085658deSDaniel Fojt 	return (ARCHIVE_OK);
1726085658deSDaniel Fojt }
1727085658deSDaniel Fojt 
1728085658deSDaniel Fojt static int
zip_read_data_zipx_xz(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)1729085658deSDaniel Fojt zip_read_data_zipx_xz(struct archive_read *a, const void **buff,
1730085658deSDaniel Fojt 	size_t *size, int64_t *offset)
1731085658deSDaniel Fojt {
1732085658deSDaniel Fojt 	struct zip* zip = (struct zip *)(a->format->data);
1733085658deSDaniel Fojt 	int ret;
1734085658deSDaniel Fojt 	lzma_ret lz_ret;
1735085658deSDaniel Fojt 	const void* compressed_buf;
1736085658deSDaniel Fojt 	ssize_t bytes_avail, in_bytes, to_consume = 0;
1737085658deSDaniel Fojt 
1738085658deSDaniel Fojt 	(void) offset; /* UNUSED */
1739085658deSDaniel Fojt 
1740085658deSDaniel Fojt 	/* Initialize decompressor if not yet initialized. */
1741085658deSDaniel Fojt 	if (!zip->decompress_init) {
1742085658deSDaniel Fojt 		ret = zipx_xz_init(a, zip);
1743085658deSDaniel Fojt 		if (ret != ARCHIVE_OK)
1744085658deSDaniel Fojt 			return (ret);
1745085658deSDaniel Fojt 	}
1746085658deSDaniel Fojt 
1747085658deSDaniel Fojt 	compressed_buf = __archive_read_ahead(a, 1, &bytes_avail);
1748085658deSDaniel Fojt 	if (bytes_avail < 0) {
1749085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1750085658deSDaniel Fojt 		    "Truncated xz file body");
1751085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1752085658deSDaniel Fojt 	}
1753085658deSDaniel Fojt 
1754085658deSDaniel Fojt 	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
1755085658deSDaniel Fojt 	zip->zipx_lzma_stream.next_in = compressed_buf;
1756085658deSDaniel Fojt 	zip->zipx_lzma_stream.avail_in = in_bytes;
1757085658deSDaniel Fojt 	zip->zipx_lzma_stream.total_in = 0;
1758085658deSDaniel Fojt 	zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
1759085658deSDaniel Fojt 	zip->zipx_lzma_stream.avail_out = zip->uncompressed_buffer_size;
1760085658deSDaniel Fojt 	zip->zipx_lzma_stream.total_out = 0;
1761085658deSDaniel Fojt 
1762085658deSDaniel Fojt 	/* Perform the decompression. */
1763085658deSDaniel Fojt 	lz_ret = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
1764085658deSDaniel Fojt 	switch(lz_ret) {
1765085658deSDaniel Fojt 		case LZMA_DATA_ERROR:
1766085658deSDaniel Fojt 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1767085658deSDaniel Fojt 			    "xz data error (error %d)", (int) lz_ret);
1768085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
1769085658deSDaniel Fojt 
1770085658deSDaniel Fojt 		case LZMA_NO_CHECK:
1771085658deSDaniel Fojt 		case LZMA_OK:
1772085658deSDaniel Fojt 			break;
1773085658deSDaniel Fojt 
1774085658deSDaniel Fojt 		default:
1775085658deSDaniel Fojt 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1776085658deSDaniel Fojt 			    "xz unknown error %d", (int) lz_ret);
1777085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
1778085658deSDaniel Fojt 
1779085658deSDaniel Fojt 		case LZMA_STREAM_END:
1780085658deSDaniel Fojt 			lzma_end(&zip->zipx_lzma_stream);
1781085658deSDaniel Fojt 			zip->zipx_lzma_valid = 0;
1782085658deSDaniel Fojt 
1783085658deSDaniel Fojt 			if((int64_t) zip->zipx_lzma_stream.total_in !=
1784085658deSDaniel Fojt 			    zip->entry_bytes_remaining)
1785085658deSDaniel Fojt 			{
1786085658deSDaniel Fojt 				archive_set_error(&a->archive,
1787085658deSDaniel Fojt 				    ARCHIVE_ERRNO_MISC,
1788085658deSDaniel Fojt 				    "xz premature end of stream");
1789085658deSDaniel Fojt 				return (ARCHIVE_FATAL);
1790085658deSDaniel Fojt 			}
1791085658deSDaniel Fojt 
1792085658deSDaniel Fojt 			zip->end_of_entry = 1;
1793085658deSDaniel Fojt 			break;
1794085658deSDaniel Fojt 	}
1795085658deSDaniel Fojt 
1796085658deSDaniel Fojt 	to_consume = zip->zipx_lzma_stream.total_in;
1797085658deSDaniel Fojt 
1798085658deSDaniel Fojt 	__archive_read_consume(a, to_consume);
1799085658deSDaniel Fojt 	zip->entry_bytes_remaining -= to_consume;
1800085658deSDaniel Fojt 	zip->entry_compressed_bytes_read += to_consume;
1801085658deSDaniel Fojt 	zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out;
1802085658deSDaniel Fojt 
1803085658deSDaniel Fojt 	*size = zip->zipx_lzma_stream.total_out;
1804085658deSDaniel Fojt 	*buff = zip->uncompressed_buffer;
1805085658deSDaniel Fojt 
1806085658deSDaniel Fojt 	ret = consume_optional_marker(a, zip);
1807085658deSDaniel Fojt 	if (ret != ARCHIVE_OK)
1808085658deSDaniel Fojt 		return (ret);
1809085658deSDaniel Fojt 
1810085658deSDaniel Fojt 	return (ARCHIVE_OK);
1811085658deSDaniel Fojt }
1812085658deSDaniel Fojt 
1813085658deSDaniel Fojt static int
zip_read_data_zipx_lzma_alone(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)1814085658deSDaniel Fojt zip_read_data_zipx_lzma_alone(struct archive_read *a, const void **buff,
1815085658deSDaniel Fojt     size_t *size, int64_t *offset)
1816085658deSDaniel Fojt {
1817085658deSDaniel Fojt 	struct zip* zip = (struct zip *)(a->format->data);
1818085658deSDaniel Fojt 	int ret;
1819085658deSDaniel Fojt 	lzma_ret lz_ret;
1820085658deSDaniel Fojt 	const void* compressed_buf;
1821085658deSDaniel Fojt 	ssize_t bytes_avail, in_bytes, to_consume;
1822085658deSDaniel Fojt 
1823085658deSDaniel Fojt 	(void) offset; /* UNUSED */
1824085658deSDaniel Fojt 
1825085658deSDaniel Fojt 	/* Initialize decompressor if not yet initialized. */
1826085658deSDaniel Fojt 	if (!zip->decompress_init) {
1827085658deSDaniel Fojt 		ret = zipx_lzma_alone_init(a, zip);
1828085658deSDaniel Fojt 		if (ret != ARCHIVE_OK)
1829085658deSDaniel Fojt 			return (ret);
1830085658deSDaniel Fojt 	}
1831085658deSDaniel Fojt 
1832085658deSDaniel Fojt 	/* Fetch more compressed data. The same note as in deflate handler
1833085658deSDaniel Fojt 	 * applies here as well:
1834085658deSDaniel Fojt 	 *
1835085658deSDaniel Fojt 	 * Note: '1' here is a performance optimization. Recall that the
1836085658deSDaniel Fojt 	 * decompression layer returns a count of available bytes; asking for
1837085658deSDaniel Fojt 	 * more than that forces the decompressor to combine reads by copying
1838085658deSDaniel Fojt 	 * data.
1839085658deSDaniel Fojt 	 */
1840085658deSDaniel Fojt 	compressed_buf = __archive_read_ahead(a, 1, &bytes_avail);
1841085658deSDaniel Fojt 	if (bytes_avail < 0) {
1842085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1843085658deSDaniel Fojt 		    "Truncated lzma file body");
1844085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1845085658deSDaniel Fojt 	}
1846085658deSDaniel Fojt 
1847085658deSDaniel Fojt 	/* Set decompressor parameters. */
1848085658deSDaniel Fojt 	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
1849085658deSDaniel Fojt 
1850085658deSDaniel Fojt 	zip->zipx_lzma_stream.next_in = compressed_buf;
1851085658deSDaniel Fojt 	zip->zipx_lzma_stream.avail_in = in_bytes;
1852085658deSDaniel Fojt 	zip->zipx_lzma_stream.total_in = 0;
1853085658deSDaniel Fojt 	zip->zipx_lzma_stream.next_out = zip->uncompressed_buffer;
1854085658deSDaniel Fojt 	zip->zipx_lzma_stream.avail_out =
1855085658deSDaniel Fojt 		/* These lzma_alone streams lack end of stream marker, so let's
1856085658deSDaniel Fojt 		 * make sure the unpacker won't try to unpack more than it's
1857085658deSDaniel Fojt 		 * supposed to. */
1858085658deSDaniel Fojt 		zipmin((int64_t) zip->uncompressed_buffer_size,
1859085658deSDaniel Fojt 		    zip->entry->uncompressed_size -
1860085658deSDaniel Fojt 		    zip->entry_uncompressed_bytes_read);
1861085658deSDaniel Fojt 	zip->zipx_lzma_stream.total_out = 0;
1862085658deSDaniel Fojt 
1863085658deSDaniel Fojt 	/* Perform the decompression. */
1864085658deSDaniel Fojt 	lz_ret = lzma_code(&zip->zipx_lzma_stream, LZMA_RUN);
1865085658deSDaniel Fojt 	switch(lz_ret) {
1866085658deSDaniel Fojt 		case LZMA_DATA_ERROR:
1867085658deSDaniel Fojt 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1868085658deSDaniel Fojt 			    "lzma data error (error %d)", (int) lz_ret);
1869085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
1870085658deSDaniel Fojt 
1871085658deSDaniel Fojt 		/* This case is optional in lzma alone format. It can happen,
1872085658deSDaniel Fojt 		 * but most of the files don't have it. (GitHub #1257) */
1873085658deSDaniel Fojt 		case LZMA_STREAM_END:
1874085658deSDaniel Fojt 			lzma_end(&zip->zipx_lzma_stream);
1875085658deSDaniel Fojt 			zip->zipx_lzma_valid = 0;
1876085658deSDaniel Fojt 			if((int64_t) zip->zipx_lzma_stream.total_in !=
1877085658deSDaniel Fojt 			    zip->entry_bytes_remaining)
1878085658deSDaniel Fojt 			{
1879085658deSDaniel Fojt 				archive_set_error(&a->archive,
1880085658deSDaniel Fojt 				    ARCHIVE_ERRNO_MISC,
1881085658deSDaniel Fojt 				    "lzma alone premature end of stream");
1882085658deSDaniel Fojt 				return (ARCHIVE_FATAL);
1883085658deSDaniel Fojt 			}
1884085658deSDaniel Fojt 
1885085658deSDaniel Fojt 			zip->end_of_entry = 1;
1886085658deSDaniel Fojt 			break;
1887085658deSDaniel Fojt 
1888085658deSDaniel Fojt 		case LZMA_OK:
1889085658deSDaniel Fojt 			break;
1890085658deSDaniel Fojt 
1891085658deSDaniel Fojt 		default:
1892085658deSDaniel Fojt 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
1893085658deSDaniel Fojt 			    "lzma unknown error %d", (int) lz_ret);
1894085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
1895085658deSDaniel Fojt 	}
1896085658deSDaniel Fojt 
1897085658deSDaniel Fojt 	to_consume = zip->zipx_lzma_stream.total_in;
1898085658deSDaniel Fojt 
1899085658deSDaniel Fojt 	/* Update pointers. */
1900085658deSDaniel Fojt 	__archive_read_consume(a, to_consume);
1901085658deSDaniel Fojt 	zip->entry_bytes_remaining -= to_consume;
1902085658deSDaniel Fojt 	zip->entry_compressed_bytes_read += to_consume;
1903085658deSDaniel Fojt 	zip->entry_uncompressed_bytes_read += zip->zipx_lzma_stream.total_out;
1904085658deSDaniel Fojt 
1905085658deSDaniel Fojt 	if(zip->entry_bytes_remaining == 0) {
1906085658deSDaniel Fojt 		zip->end_of_entry = 1;
1907085658deSDaniel Fojt 	}
1908085658deSDaniel Fojt 
1909085658deSDaniel Fojt 	/* Return values. */
1910085658deSDaniel Fojt 	*size = zip->zipx_lzma_stream.total_out;
1911085658deSDaniel Fojt 	*buff = zip->uncompressed_buffer;
1912085658deSDaniel Fojt 
1913085658deSDaniel Fojt 	/* Behave the same way as during deflate decompression. */
1914085658deSDaniel Fojt 	ret = consume_optional_marker(a, zip);
1915085658deSDaniel Fojt 	if (ret != ARCHIVE_OK)
1916085658deSDaniel Fojt 		return (ret);
1917085658deSDaniel Fojt 
1918085658deSDaniel Fojt 	/* Free lzma decoder handle because we'll no longer need it. */
1919085658deSDaniel Fojt 	if(zip->end_of_entry) {
1920085658deSDaniel Fojt 		lzma_end(&zip->zipx_lzma_stream);
1921085658deSDaniel Fojt 		zip->zipx_lzma_valid = 0;
1922085658deSDaniel Fojt 	}
1923085658deSDaniel Fojt 
1924085658deSDaniel Fojt 	/* If we're here, then we're good! */
1925085658deSDaniel Fojt 	return (ARCHIVE_OK);
1926085658deSDaniel Fojt }
1927085658deSDaniel Fojt #endif /* HAVE_LZMA_H && HAVE_LIBLZMA */
1928085658deSDaniel Fojt 
1929085658deSDaniel Fojt static int
zipx_ppmd8_init(struct archive_read * a,struct zip * zip)1930085658deSDaniel Fojt zipx_ppmd8_init(struct archive_read *a, struct zip *zip)
1931085658deSDaniel Fojt {
1932085658deSDaniel Fojt 	const void* p;
1933085658deSDaniel Fojt 	uint32_t val;
1934085658deSDaniel Fojt 	uint32_t order;
1935085658deSDaniel Fojt 	uint32_t mem;
1936085658deSDaniel Fojt 	uint32_t restore_method;
1937085658deSDaniel Fojt 
1938085658deSDaniel Fojt 	/* Remove previous decompression context if it exists. */
1939085658deSDaniel Fojt 	if(zip->ppmd8_valid) {
1940085658deSDaniel Fojt 		__archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8);
1941085658deSDaniel Fojt 		zip->ppmd8_valid = 0;
1942085658deSDaniel Fojt 	}
1943085658deSDaniel Fojt 
1944085658deSDaniel Fojt 	/* Create a new decompression context. */
1945085658deSDaniel Fojt 	__archive_ppmd8_functions.Ppmd8_Construct(&zip->ppmd8);
1946085658deSDaniel Fojt 	zip->ppmd8_stream_failed = 0;
1947085658deSDaniel Fojt 
1948085658deSDaniel Fojt 	/* Setup function pointers required by Ppmd8 decompressor. The
1949085658deSDaniel Fojt 	 * 'ppmd_read' function will feed new bytes to the decompressor,
1950085658deSDaniel Fojt 	 * and will increment the 'zip->zipx_ppmd_read_compressed' counter. */
1951085658deSDaniel Fojt 	zip->ppmd8.Stream.In = &zip->zipx_ppmd_stream;
1952085658deSDaniel Fojt 	zip->zipx_ppmd_stream.a = a;
1953085658deSDaniel Fojt 	zip->zipx_ppmd_stream.Read = &ppmd_read;
1954085658deSDaniel Fojt 
1955085658deSDaniel Fojt 	/* Reset number of read bytes to 0. */
1956085658deSDaniel Fojt 	zip->zipx_ppmd_read_compressed = 0;
1957085658deSDaniel Fojt 
1958085658deSDaniel Fojt 	/* Read Ppmd8 header (2 bytes). */
1959085658deSDaniel Fojt 	p = __archive_read_ahead(a, 2, NULL);
1960085658deSDaniel Fojt 	if(!p) {
1961085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1962085658deSDaniel Fojt 		    "Truncated file data in PPMd8 stream");
1963085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1964085658deSDaniel Fojt 	}
1965085658deSDaniel Fojt 	__archive_read_consume(a, 2);
1966085658deSDaniel Fojt 
1967085658deSDaniel Fojt 	/* Decode the stream's compression parameters. */
1968085658deSDaniel Fojt 	val = archive_le16dec(p);
1969085658deSDaniel Fojt 	order = (val & 15) + 1;
1970085658deSDaniel Fojt 	mem = ((val >> 4) & 0xff) + 1;
1971085658deSDaniel Fojt 	restore_method = (val >> 12);
1972085658deSDaniel Fojt 
1973085658deSDaniel Fojt 	if(order < 2 || restore_method > 2) {
1974085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
1975*50f8aa9cSAntonio Huete Jimenez 		    "Invalid parameter set in PPMd8 stream (order=%" PRId32 ", "
1976*50f8aa9cSAntonio Huete Jimenez 		    "restore=%" PRId32 ")", order, restore_method);
1977085658deSDaniel Fojt 		return (ARCHIVE_FAILED);
1978085658deSDaniel Fojt 	}
1979085658deSDaniel Fojt 
1980085658deSDaniel Fojt 	/* Allocate the memory needed to properly decompress the file. */
1981085658deSDaniel Fojt 	if(!__archive_ppmd8_functions.Ppmd8_Alloc(&zip->ppmd8, mem << 20)) {
1982085658deSDaniel Fojt 		archive_set_error(&a->archive, ENOMEM,
1983*50f8aa9cSAntonio Huete Jimenez 		    "Unable to allocate memory for PPMd8 stream: %" PRId32 " bytes",
1984085658deSDaniel Fojt 		    mem << 20);
1985085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1986085658deSDaniel Fojt 	}
1987085658deSDaniel Fojt 
1988085658deSDaniel Fojt 	/* Signal the cleanup function to release Ppmd8 context in the
1989085658deSDaniel Fojt 	 * cleanup phase. */
1990085658deSDaniel Fojt 	zip->ppmd8_valid = 1;
1991085658deSDaniel Fojt 
1992085658deSDaniel Fojt 	/* Perform further Ppmd8 initialization. */
1993085658deSDaniel Fojt 	if(!__archive_ppmd8_functions.Ppmd8_RangeDec_Init(&zip->ppmd8)) {
1994085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_PROGRAMMER,
1995085658deSDaniel Fojt 		    "PPMd8 stream range decoder initialization error");
1996085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
1997085658deSDaniel Fojt 	}
1998085658deSDaniel Fojt 
1999085658deSDaniel Fojt 	__archive_ppmd8_functions.Ppmd8_Init(&zip->ppmd8, order,
2000085658deSDaniel Fojt 	    restore_method);
2001085658deSDaniel Fojt 
2002085658deSDaniel Fojt 	/* Allocate the buffer that will hold uncompressed data. */
2003085658deSDaniel Fojt 	free(zip->uncompressed_buffer);
2004085658deSDaniel Fojt 
2005085658deSDaniel Fojt 	zip->uncompressed_buffer_size = 256 * 1024;
2006085658deSDaniel Fojt 	zip->uncompressed_buffer =
2007085658deSDaniel Fojt 	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
2008085658deSDaniel Fojt 
2009085658deSDaniel Fojt 	if(zip->uncompressed_buffer == NULL) {
2010085658deSDaniel Fojt 		archive_set_error(&a->archive, ENOMEM,
2011085658deSDaniel Fojt 		    "No memory for PPMd8 decompression");
2012085658deSDaniel Fojt 		return ARCHIVE_FATAL;
2013085658deSDaniel Fojt 	}
2014085658deSDaniel Fojt 
2015085658deSDaniel Fojt 	/* Ppmd8 initialization is done. */
2016085658deSDaniel Fojt 	zip->decompress_init = 1;
2017085658deSDaniel Fojt 
2018085658deSDaniel Fojt 	/* We've already read 2 bytes in the output stream. Additionally,
2019085658deSDaniel Fojt 	 * Ppmd8 initialization code could read some data as well. So we
2020085658deSDaniel Fojt 	 * are advancing the stream by 2 bytes plus whatever number of
2021085658deSDaniel Fojt 	 * bytes Ppmd8 init function used. */
2022085658deSDaniel Fojt 	zip->entry_compressed_bytes_read += 2 + zip->zipx_ppmd_read_compressed;
2023085658deSDaniel Fojt 
2024085658deSDaniel Fojt 	return ARCHIVE_OK;
2025085658deSDaniel Fojt }
2026085658deSDaniel Fojt 
2027085658deSDaniel Fojt static int
zip_read_data_zipx_ppmd(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)2028085658deSDaniel Fojt zip_read_data_zipx_ppmd(struct archive_read *a, const void **buff,
2029085658deSDaniel Fojt     size_t *size, int64_t *offset)
2030085658deSDaniel Fojt {
2031085658deSDaniel Fojt 	struct zip* zip = (struct zip *)(a->format->data);
2032085658deSDaniel Fojt 	int ret;
2033085658deSDaniel Fojt 	size_t consumed_bytes = 0;
2034085658deSDaniel Fojt 	ssize_t bytes_avail = 0;
2035085658deSDaniel Fojt 
2036085658deSDaniel Fojt 	(void) offset; /* UNUSED */
2037085658deSDaniel Fojt 
2038085658deSDaniel Fojt 	/* If we're here for the first time, initialize Ppmd8 decompression
2039085658deSDaniel Fojt 	 * context first. */
2040085658deSDaniel Fojt 	if(!zip->decompress_init) {
2041085658deSDaniel Fojt 		ret = zipx_ppmd8_init(a, zip);
2042085658deSDaniel Fojt 		if(ret != ARCHIVE_OK)
2043085658deSDaniel Fojt 			return ret;
2044085658deSDaniel Fojt 	}
2045085658deSDaniel Fojt 
2046085658deSDaniel Fojt 	/* Fetch for more data. We're reading 1 byte here, but libarchive
2047085658deSDaniel Fojt 	 * should prefetch more bytes. */
2048085658deSDaniel Fojt 	(void) __archive_read_ahead(a, 1, &bytes_avail);
2049085658deSDaniel Fojt 	if(bytes_avail < 0) {
2050085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2051085658deSDaniel Fojt 		    "Truncated PPMd8 file body");
2052085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
2053085658deSDaniel Fojt 	}
2054085658deSDaniel Fojt 
2055085658deSDaniel Fojt 	/* This counter will be updated inside ppmd_read(), which at one
2056085658deSDaniel Fojt 	 * point will be called by Ppmd8_DecodeSymbol. */
2057085658deSDaniel Fojt 	zip->zipx_ppmd_read_compressed = 0;
2058085658deSDaniel Fojt 
2059085658deSDaniel Fojt 	/* Decompression loop. */
2060085658deSDaniel Fojt 	do {
2061085658deSDaniel Fojt 		int sym = __archive_ppmd8_functions.Ppmd8_DecodeSymbol(
2062085658deSDaniel Fojt 		    &zip->ppmd8);
2063085658deSDaniel Fojt 		if(sym < 0) {
2064085658deSDaniel Fojt 			zip->end_of_entry = 1;
2065085658deSDaniel Fojt 			break;
2066085658deSDaniel Fojt 		}
2067085658deSDaniel Fojt 
2068085658deSDaniel Fojt 		/* This field is set by ppmd_read() when there was no more data
2069085658deSDaniel Fojt 		 * to be read. */
2070085658deSDaniel Fojt 		if(zip->ppmd8_stream_failed) {
2071085658deSDaniel Fojt 			archive_set_error(&a->archive,
2072085658deSDaniel Fojt 			    ARCHIVE_ERRNO_FILE_FORMAT,
2073085658deSDaniel Fojt 			    "Truncated PPMd8 file body");
2074085658deSDaniel Fojt 			return (ARCHIVE_FATAL);
2075085658deSDaniel Fojt 		}
2076085658deSDaniel Fojt 
2077085658deSDaniel Fojt 		zip->uncompressed_buffer[consumed_bytes] = (uint8_t) sym;
2078085658deSDaniel Fojt 		++consumed_bytes;
2079085658deSDaniel Fojt 	} while(consumed_bytes < zip->uncompressed_buffer_size);
2080085658deSDaniel Fojt 
2081085658deSDaniel Fojt 	/* Update pointers for libarchive. */
2082085658deSDaniel Fojt 	*buff = zip->uncompressed_buffer;
2083085658deSDaniel Fojt 	*size = consumed_bytes;
2084085658deSDaniel Fojt 
2085085658deSDaniel Fojt 	/* Update pointers so we can continue decompression in another call. */
2086085658deSDaniel Fojt 	zip->entry_bytes_remaining -= zip->zipx_ppmd_read_compressed;
2087085658deSDaniel Fojt 	zip->entry_compressed_bytes_read += zip->zipx_ppmd_read_compressed;
2088085658deSDaniel Fojt 	zip->entry_uncompressed_bytes_read += consumed_bytes;
2089085658deSDaniel Fojt 
2090085658deSDaniel Fojt 	/* If we're at the end of stream, deinitialize Ppmd8 context. */
2091085658deSDaniel Fojt 	if(zip->end_of_entry) {
2092085658deSDaniel Fojt 		__archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8);
2093085658deSDaniel Fojt 		zip->ppmd8_valid = 0;
2094085658deSDaniel Fojt 	}
2095085658deSDaniel Fojt 
2096085658deSDaniel Fojt 	/* Seek for optional marker, same way as in each zip entry. */
2097085658deSDaniel Fojt 	ret = consume_optional_marker(a, zip);
2098085658deSDaniel Fojt 	if (ret != ARCHIVE_OK)
2099085658deSDaniel Fojt 		return ret;
2100085658deSDaniel Fojt 
2101085658deSDaniel Fojt 	return ARCHIVE_OK;
2102085658deSDaniel Fojt }
2103085658deSDaniel Fojt 
2104085658deSDaniel Fojt #ifdef HAVE_BZLIB_H
2105085658deSDaniel Fojt static int
zipx_bzip2_init(struct archive_read * a,struct zip * zip)2106085658deSDaniel Fojt zipx_bzip2_init(struct archive_read *a, struct zip *zip)
2107085658deSDaniel Fojt {
2108085658deSDaniel Fojt 	int r;
2109085658deSDaniel Fojt 
2110085658deSDaniel Fojt 	/* Deallocate already existing BZ2 decompression context if it
2111085658deSDaniel Fojt 	 * exists. */
2112085658deSDaniel Fojt 	if(zip->bzstream_valid) {
2113085658deSDaniel Fojt 		BZ2_bzDecompressEnd(&zip->bzstream);
2114085658deSDaniel Fojt 		zip->bzstream_valid = 0;
2115085658deSDaniel Fojt 	}
2116085658deSDaniel Fojt 
2117085658deSDaniel Fojt 	/* Allocate a new BZ2 decompression context. */
2118085658deSDaniel Fojt 	memset(&zip->bzstream, 0, sizeof(bz_stream));
2119085658deSDaniel Fojt 	r = BZ2_bzDecompressInit(&zip->bzstream, 0, 1);
2120085658deSDaniel Fojt 	if(r != BZ_OK) {
2121085658deSDaniel Fojt 		archive_set_error(&(a->archive), ARCHIVE_ERRNO_MISC,
2122085658deSDaniel Fojt 		    "bzip2 initialization failed(%d)",
2123085658deSDaniel Fojt 		    r);
2124085658deSDaniel Fojt 
2125085658deSDaniel Fojt 		return ARCHIVE_FAILED;
2126085658deSDaniel Fojt 	}
2127085658deSDaniel Fojt 
2128085658deSDaniel Fojt 	/* Mark the bzstream field to be released in cleanup phase. */
2129085658deSDaniel Fojt 	zip->bzstream_valid = 1;
2130085658deSDaniel Fojt 
2131085658deSDaniel Fojt 	/* (Re)allocate the buffer that will contain decompressed bytes. */
2132085658deSDaniel Fojt 	free(zip->uncompressed_buffer);
2133085658deSDaniel Fojt 
2134085658deSDaniel Fojt 	zip->uncompressed_buffer_size = 256 * 1024;
2135085658deSDaniel Fojt 	zip->uncompressed_buffer =
2136085658deSDaniel Fojt 	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
2137085658deSDaniel Fojt 	if (zip->uncompressed_buffer == NULL) {
2138085658deSDaniel Fojt 		archive_set_error(&a->archive, ENOMEM,
2139085658deSDaniel Fojt 		    "No memory for bzip2 decompression");
2140085658deSDaniel Fojt 		    return ARCHIVE_FATAL;
2141085658deSDaniel Fojt 	}
2142085658deSDaniel Fojt 
2143085658deSDaniel Fojt 	/* Initialization done. */
2144085658deSDaniel Fojt 	zip->decompress_init = 1;
2145085658deSDaniel Fojt 	return ARCHIVE_OK;
2146085658deSDaniel Fojt }
2147085658deSDaniel Fojt 
2148085658deSDaniel Fojt static int
zip_read_data_zipx_bzip2(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)2149085658deSDaniel Fojt zip_read_data_zipx_bzip2(struct archive_read *a, const void **buff,
2150085658deSDaniel Fojt     size_t *size, int64_t *offset)
2151085658deSDaniel Fojt {
2152085658deSDaniel Fojt 	struct zip *zip = (struct zip *)(a->format->data);
2153085658deSDaniel Fojt 	ssize_t bytes_avail = 0, in_bytes, to_consume;
2154085658deSDaniel Fojt 	const void *compressed_buff;
2155085658deSDaniel Fojt 	int r;
2156085658deSDaniel Fojt 	uint64_t total_out;
2157085658deSDaniel Fojt 
2158085658deSDaniel Fojt 	(void) offset; /* UNUSED */
2159085658deSDaniel Fojt 
2160085658deSDaniel Fojt 	/* Initialize decompression context if we're here for the first time. */
2161085658deSDaniel Fojt 	if(!zip->decompress_init) {
2162085658deSDaniel Fojt 		r = zipx_bzip2_init(a, zip);
2163085658deSDaniel Fojt 		if(r != ARCHIVE_OK)
2164085658deSDaniel Fojt 			return r;
2165085658deSDaniel Fojt 	}
2166085658deSDaniel Fojt 
2167085658deSDaniel Fojt 	/* Fetch more compressed bytes. */
2168085658deSDaniel Fojt 	compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
2169085658deSDaniel Fojt 	if(bytes_avail < 0) {
2170085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2171085658deSDaniel Fojt 		    "Truncated bzip2 file body");
2172085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
2173085658deSDaniel Fojt 	}
2174085658deSDaniel Fojt 
2175085658deSDaniel Fojt 	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
2176085658deSDaniel Fojt 	if(in_bytes < 1) {
2177085658deSDaniel Fojt 		/* libbz2 doesn't complain when caller feeds avail_in == 0.
2178085658deSDaniel Fojt 		 * It will actually return success in this case, which is
2179085658deSDaniel Fojt 		 * undesirable. This is why we need to make this check
2180085658deSDaniel Fojt 		 * manually. */
2181085658deSDaniel Fojt 
2182085658deSDaniel Fojt 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2183085658deSDaniel Fojt 		    "Truncated bzip2 file body");
2184085658deSDaniel Fojt 		return (ARCHIVE_FATAL);
2185085658deSDaniel Fojt 	}
2186085658deSDaniel Fojt 
2187085658deSDaniel Fojt 	/* Setup buffer boundaries. */
2188085658deSDaniel Fojt 	zip->bzstream.next_in = (char*)(uintptr_t) compressed_buff;
2189085658deSDaniel Fojt 	zip->bzstream.avail_in = in_bytes;
2190085658deSDaniel Fojt 	zip->bzstream.total_in_hi32 = 0;
2191085658deSDaniel Fojt 	zip->bzstream.total_in_lo32 = 0;
2192085658deSDaniel Fojt 	zip->bzstream.next_out = (char*) zip->uncompressed_buffer;
2193085658deSDaniel Fojt 	zip->bzstream.avail_out = zip->uncompressed_buffer_size;
2194085658deSDaniel Fojt 	zip->bzstream.total_out_hi32 = 0;
2195085658deSDaniel Fojt 	zip->bzstream.total_out_lo32 = 0;
2196085658deSDaniel Fojt 
2197085658deSDaniel Fojt 	/* Perform the decompression. */
2198085658deSDaniel Fojt 	r = BZ2_bzDecompress(&zip->bzstream);
2199085658deSDaniel Fojt 	switch(r) {
2200085658deSDaniel Fojt 		case BZ_STREAM_END:
2201085658deSDaniel Fojt 			/* If we're at the end of the stream, deinitialize the
2202085658deSDaniel Fojt 			 * decompression context now. */
2203085658deSDaniel Fojt 			switch(BZ2_bzDecompressEnd(&zip->bzstream)) {
2204085658deSDaniel Fojt 				case BZ_OK:
2205085658deSDaniel Fojt 					break;
2206085658deSDaniel Fojt 				default:
2207085658deSDaniel Fojt 					archive_set_error(&a->archive,
2208085658deSDaniel Fojt 					    ARCHIVE_ERRNO_MISC,
2209085658deSDaniel Fojt 					    "Failed to clean up bzip2 "
2210085658deSDaniel Fojt 					    "decompressor");
2211085658deSDaniel Fojt 					return ARCHIVE_FATAL;
2212085658deSDaniel Fojt 			}
2213085658deSDaniel Fojt 
2214085658deSDaniel Fojt 			zip->end_of_entry = 1;
2215085658deSDaniel Fojt 			break;
2216085658deSDaniel Fojt 		case BZ_OK:
2217085658deSDaniel Fojt 			/* The decompressor has successfully decoded this
2218085658deSDaniel Fojt 			 * chunk of data, but more data is still in queue. */
2219085658deSDaniel Fojt 			break;
2220085658deSDaniel Fojt 		default:
2221085658deSDaniel Fojt 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2222085658deSDaniel Fojt 			    "bzip2 decompression failed");
2223085658deSDaniel Fojt 			return ARCHIVE_FATAL;
2224085658deSDaniel Fojt 	}
2225085658deSDaniel Fojt 
2226085658deSDaniel Fojt 	/* Update the pointers so decompressor can continue decoding. */
2227085658deSDaniel Fojt 	to_consume = zip->bzstream.total_in_lo32;
2228085658deSDaniel Fojt 	__archive_read_consume(a, to_consume);
2229085658deSDaniel Fojt 
2230085658deSDaniel Fojt 	total_out = ((uint64_t) zip->bzstream.total_out_hi32 << 32) +
2231085658deSDaniel Fojt 	    zip->bzstream.total_out_lo32;
2232085658deSDaniel Fojt 
2233085658deSDaniel Fojt 	zip->entry_bytes_remaining -= to_consume;
2234085658deSDaniel Fojt 	zip->entry_compressed_bytes_read += to_consume;
2235085658deSDaniel Fojt 	zip->entry_uncompressed_bytes_read += total_out;
2236085658deSDaniel Fojt 
2237085658deSDaniel Fojt 	/* Give libarchive its due. */
2238085658deSDaniel Fojt 	*size = total_out;
2239085658deSDaniel Fojt 	*buff = zip->uncompressed_buffer;
2240085658deSDaniel Fojt 
2241085658deSDaniel Fojt 	/* Seek for optional marker, like in other entries. */
2242085658deSDaniel Fojt 	r = consume_optional_marker(a, zip);
2243085658deSDaniel Fojt 	if(r != ARCHIVE_OK)
2244085658deSDaniel Fojt 		return r;
2245085658deSDaniel Fojt 
2246085658deSDaniel Fojt 	return ARCHIVE_OK;
2247085658deSDaniel Fojt }
2248085658deSDaniel Fojt 
2249085658deSDaniel Fojt #endif
2250085658deSDaniel Fojt 
2251*50f8aa9cSAntonio Huete Jimenez #if HAVE_ZSTD_H && HAVE_LIBZSTD
2252*50f8aa9cSAntonio Huete Jimenez static int
zipx_zstd_init(struct archive_read * a,struct zip * zip)2253*50f8aa9cSAntonio Huete Jimenez zipx_zstd_init(struct archive_read *a, struct zip *zip)
2254*50f8aa9cSAntonio Huete Jimenez {
2255*50f8aa9cSAntonio Huete Jimenez 	size_t r;
2256*50f8aa9cSAntonio Huete Jimenez 
2257*50f8aa9cSAntonio Huete Jimenez 	/* Deallocate already existing Zstd decompression context if it
2258*50f8aa9cSAntonio Huete Jimenez 	 * exists. */
2259*50f8aa9cSAntonio Huete Jimenez 	if(zip->zstdstream_valid) {
2260*50f8aa9cSAntonio Huete Jimenez 		ZSTD_freeDStream(zip->zstdstream);
2261*50f8aa9cSAntonio Huete Jimenez 		zip->zstdstream_valid = 0;
2262*50f8aa9cSAntonio Huete Jimenez 	}
2263*50f8aa9cSAntonio Huete Jimenez 
2264*50f8aa9cSAntonio Huete Jimenez 	/* Allocate a new Zstd decompression context. */
2265*50f8aa9cSAntonio Huete Jimenez 	zip->zstdstream = ZSTD_createDStream();
2266*50f8aa9cSAntonio Huete Jimenez 
2267*50f8aa9cSAntonio Huete Jimenez 	r = ZSTD_initDStream(zip->zstdstream);
2268*50f8aa9cSAntonio Huete Jimenez 	if (ZSTD_isError(r)) {
2269*50f8aa9cSAntonio Huete Jimenez 		 archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2270*50f8aa9cSAntonio Huete Jimenez 			"Error initializing zstd decompressor: %s",
2271*50f8aa9cSAntonio Huete Jimenez 			ZSTD_getErrorName(r));
2272*50f8aa9cSAntonio Huete Jimenez 
2273*50f8aa9cSAntonio Huete Jimenez 		return ARCHIVE_FAILED;
2274*50f8aa9cSAntonio Huete Jimenez 	}
2275*50f8aa9cSAntonio Huete Jimenez 
2276*50f8aa9cSAntonio Huete Jimenez 	/* Mark the zstdstream field to be released in cleanup phase. */
2277*50f8aa9cSAntonio Huete Jimenez 	zip->zstdstream_valid = 1;
2278*50f8aa9cSAntonio Huete Jimenez 
2279*50f8aa9cSAntonio Huete Jimenez 	/* (Re)allocate the buffer that will contain decompressed bytes. */
2280*50f8aa9cSAntonio Huete Jimenez 	free(zip->uncompressed_buffer);
2281*50f8aa9cSAntonio Huete Jimenez 
2282*50f8aa9cSAntonio Huete Jimenez 	zip->uncompressed_buffer_size = ZSTD_DStreamOutSize();
2283*50f8aa9cSAntonio Huete Jimenez 	zip->uncompressed_buffer =
2284*50f8aa9cSAntonio Huete Jimenez 	    (uint8_t*) malloc(zip->uncompressed_buffer_size);
2285*50f8aa9cSAntonio Huete Jimenez 	if (zip->uncompressed_buffer == NULL) {
2286*50f8aa9cSAntonio Huete Jimenez 		archive_set_error(&a->archive, ENOMEM,
2287*50f8aa9cSAntonio Huete Jimenez 			"No memory for Zstd decompression");
2288*50f8aa9cSAntonio Huete Jimenez 
2289*50f8aa9cSAntonio Huete Jimenez 		return ARCHIVE_FATAL;
2290*50f8aa9cSAntonio Huete Jimenez 	}
2291*50f8aa9cSAntonio Huete Jimenez 
2292*50f8aa9cSAntonio Huete Jimenez 	/* Initialization done. */
2293*50f8aa9cSAntonio Huete Jimenez 	zip->decompress_init = 1;
2294*50f8aa9cSAntonio Huete Jimenez 	return ARCHIVE_OK;
2295*50f8aa9cSAntonio Huete Jimenez }
2296*50f8aa9cSAntonio Huete Jimenez 
2297*50f8aa9cSAntonio Huete Jimenez static int
zip_read_data_zipx_zstd(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)2298*50f8aa9cSAntonio Huete Jimenez zip_read_data_zipx_zstd(struct archive_read *a, const void **buff,
2299*50f8aa9cSAntonio Huete Jimenez     size_t *size, int64_t *offset)
2300*50f8aa9cSAntonio Huete Jimenez {
2301*50f8aa9cSAntonio Huete Jimenez 	struct zip *zip = (struct zip *)(a->format->data);
2302*50f8aa9cSAntonio Huete Jimenez 	ssize_t bytes_avail = 0, in_bytes, to_consume;
2303*50f8aa9cSAntonio Huete Jimenez 	const void *compressed_buff;
2304*50f8aa9cSAntonio Huete Jimenez 	int r;
2305*50f8aa9cSAntonio Huete Jimenez 	size_t ret;
2306*50f8aa9cSAntonio Huete Jimenez 	uint64_t total_out;
2307*50f8aa9cSAntonio Huete Jimenez 	ZSTD_outBuffer out;
2308*50f8aa9cSAntonio Huete Jimenez 	ZSTD_inBuffer in;
2309*50f8aa9cSAntonio Huete Jimenez 
2310*50f8aa9cSAntonio Huete Jimenez 	(void) offset; /* UNUSED */
2311*50f8aa9cSAntonio Huete Jimenez 
2312*50f8aa9cSAntonio Huete Jimenez 	/* Initialize decompression context if we're here for the first time. */
2313*50f8aa9cSAntonio Huete Jimenez 	if(!zip->decompress_init) {
2314*50f8aa9cSAntonio Huete Jimenez 		r = zipx_zstd_init(a, zip);
2315*50f8aa9cSAntonio Huete Jimenez 		if(r != ARCHIVE_OK)
2316*50f8aa9cSAntonio Huete Jimenez 			return r;
2317*50f8aa9cSAntonio Huete Jimenez 	}
2318*50f8aa9cSAntonio Huete Jimenez 
2319*50f8aa9cSAntonio Huete Jimenez 	/* Fetch more compressed bytes */
2320*50f8aa9cSAntonio Huete Jimenez 	compressed_buff = __archive_read_ahead(a, 1, &bytes_avail);
2321*50f8aa9cSAntonio Huete Jimenez 	if(bytes_avail < 0) {
2322*50f8aa9cSAntonio Huete Jimenez 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2323*50f8aa9cSAntonio Huete Jimenez 		    "Truncated zstd file body");
2324*50f8aa9cSAntonio Huete Jimenez 		return (ARCHIVE_FATAL);
2325*50f8aa9cSAntonio Huete Jimenez 	}
2326*50f8aa9cSAntonio Huete Jimenez 
2327*50f8aa9cSAntonio Huete Jimenez 	in_bytes = zipmin(zip->entry_bytes_remaining, bytes_avail);
2328*50f8aa9cSAntonio Huete Jimenez 	if(in_bytes < 1) {
2329*50f8aa9cSAntonio Huete Jimenez 		/* zstd doesn't complain when caller feeds avail_in == 0.
2330*50f8aa9cSAntonio Huete Jimenez 		 * It will actually return success in this case, which is
2331*50f8aa9cSAntonio Huete Jimenez 		 * undesirable. This is why we need to make this check
2332*50f8aa9cSAntonio Huete Jimenez 		 * manually. */
2333*50f8aa9cSAntonio Huete Jimenez 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
2334*50f8aa9cSAntonio Huete Jimenez 		    "Truncated zstd file body");
2335*50f8aa9cSAntonio Huete Jimenez 		return (ARCHIVE_FATAL);
2336*50f8aa9cSAntonio Huete Jimenez 	}
2337*50f8aa9cSAntonio Huete Jimenez 
2338*50f8aa9cSAntonio Huete Jimenez 	/* Setup buffer boundaries */
2339*50f8aa9cSAntonio Huete Jimenez 	in.src = compressed_buff;
2340*50f8aa9cSAntonio Huete Jimenez 	in.size = in_bytes;
2341*50f8aa9cSAntonio Huete Jimenez 	in.pos = 0;
2342*50f8aa9cSAntonio Huete Jimenez 	out = (ZSTD_outBuffer) { zip->uncompressed_buffer, zip->uncompressed_buffer_size, 0 };
2343*50f8aa9cSAntonio Huete Jimenez 
2344*50f8aa9cSAntonio Huete Jimenez 	/* Perform the decompression. */
2345*50f8aa9cSAntonio Huete Jimenez 	ret = ZSTD_decompressStream(zip->zstdstream, &out, &in);
2346*50f8aa9cSAntonio Huete Jimenez 	if (ZSTD_isError(ret)) {
2347*50f8aa9cSAntonio Huete Jimenez 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
2348*50f8aa9cSAntonio Huete Jimenez 			"Error during zstd decompression: %s",
2349*50f8aa9cSAntonio Huete Jimenez 			ZSTD_getErrorName(ret));
2350*50f8aa9cSAntonio Huete Jimenez 		return (ARCHIVE_FATAL);
2351*50f8aa9cSAntonio Huete Jimenez 	}
2352*50f8aa9cSAntonio Huete Jimenez 
2353*50f8aa9cSAntonio Huete Jimenez 	/* Check end of the stream. */
2354*50f8aa9cSAntonio Huete Jimenez 	if (ret == 0) {
2355*50f8aa9cSAntonio Huete Jimenez 		if ((in.pos == in.size) && (out.pos < out.size)) {
2356*50f8aa9cSAntonio Huete Jimenez 			zip->end_of_entry = 1;
2357*50f8aa9cSAntonio Huete Jimenez 			ZSTD_freeDStream(zip->zstdstream);
2358*50f8aa9cSAntonio Huete Jimenez 			zip->zstdstream_valid = 0;
2359*50f8aa9cSAntonio Huete Jimenez 		}
2360*50f8aa9cSAntonio Huete Jimenez 	}
2361*50f8aa9cSAntonio Huete Jimenez 
2362*50f8aa9cSAntonio Huete Jimenez 	/* Update the pointers so decompressor can continue decoding. */
2363*50f8aa9cSAntonio Huete Jimenez 	to_consume = in.pos;
2364*50f8aa9cSAntonio Huete Jimenez 	__archive_read_consume(a, to_consume);
2365*50f8aa9cSAntonio Huete Jimenez 
2366*50f8aa9cSAntonio Huete Jimenez 	total_out = out.pos;
2367*50f8aa9cSAntonio Huete Jimenez 
2368*50f8aa9cSAntonio Huete Jimenez 	zip->entry_bytes_remaining -= to_consume;
2369*50f8aa9cSAntonio Huete Jimenez 	zip->entry_compressed_bytes_read += to_consume;
2370*50f8aa9cSAntonio Huete Jimenez 	zip->entry_uncompressed_bytes_read += total_out;
2371*50f8aa9cSAntonio Huete Jimenez 
2372*50f8aa9cSAntonio Huete Jimenez 	/* Give libarchive its due. */
2373*50f8aa9cSAntonio Huete Jimenez 	*size = total_out;
2374*50f8aa9cSAntonio Huete Jimenez 	*buff = zip->uncompressed_buffer;
2375*50f8aa9cSAntonio Huete Jimenez 
2376*50f8aa9cSAntonio Huete Jimenez 	/* Seek for optional marker, like in other entries. */
2377*50f8aa9cSAntonio Huete Jimenez 	r = consume_optional_marker(a, zip);
2378*50f8aa9cSAntonio Huete Jimenez 	if(r != ARCHIVE_OK)
2379*50f8aa9cSAntonio Huete Jimenez 		return r;
2380*50f8aa9cSAntonio Huete Jimenez 
2381*50f8aa9cSAntonio Huete Jimenez 	return ARCHIVE_OK;
2382*50f8aa9cSAntonio Huete Jimenez }
2383*50f8aa9cSAntonio Huete Jimenez #endif
2384*50f8aa9cSAntonio Huete Jimenez 
23856b384f39SPeter Avalos #ifdef HAVE_ZLIB_H
23866b384f39SPeter Avalos static int
zip_deflate_init(struct archive_read * a,struct zip * zip)23876b384f39SPeter Avalos zip_deflate_init(struct archive_read *a, struct zip *zip)
23886b384f39SPeter Avalos {
23896b384f39SPeter Avalos 	int r;
23906b384f39SPeter Avalos 
23916b384f39SPeter Avalos 	/* If we haven't yet read any data, initialize the decompressor. */
23926b384f39SPeter Avalos 	if (!zip->decompress_init) {
23936b384f39SPeter Avalos 		if (zip->stream_valid)
23946b384f39SPeter Avalos 			r = inflateReset(&zip->stream);
23956b384f39SPeter Avalos 		else
23966b384f39SPeter Avalos 			r = inflateInit2(&zip->stream,
23976b384f39SPeter Avalos 			    -15 /* Don't check for zlib header */);
23986b384f39SPeter Avalos 		if (r != Z_OK) {
23996b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
24006b384f39SPeter Avalos 			    "Can't initialize ZIP decompression.");
24016b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
24026b384f39SPeter Avalos 		}
24036b384f39SPeter Avalos 		/* Stream structure has been set up. */
24046b384f39SPeter Avalos 		zip->stream_valid = 1;
24056b384f39SPeter Avalos 		/* We've initialized decompression for this stream. */
24066b384f39SPeter Avalos 		zip->decompress_init = 1;
24076b384f39SPeter Avalos 	}
24086b384f39SPeter Avalos 	return (ARCHIVE_OK);
24096b384f39SPeter Avalos }
24106b384f39SPeter Avalos 
24116b384f39SPeter Avalos static int
zip_read_data_deflate(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)24126b384f39SPeter Avalos zip_read_data_deflate(struct archive_read *a, const void **buff,
24136b384f39SPeter Avalos     size_t *size, int64_t *offset)
24146b384f39SPeter Avalos {
24156b384f39SPeter Avalos 	struct zip *zip;
24166b384f39SPeter Avalos 	ssize_t bytes_avail;
24176b384f39SPeter Avalos 	const void *compressed_buff, *sp;
24186b384f39SPeter Avalos 	int r;
24196b384f39SPeter Avalos 
24206b384f39SPeter Avalos 	(void)offset; /* UNUSED */
24216b384f39SPeter Avalos 
24226b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
24236b384f39SPeter Avalos 
24246b384f39SPeter Avalos 	/* If the buffer hasn't been allocated, allocate it now. */
24256b384f39SPeter Avalos 	if (zip->uncompressed_buffer == NULL) {
24266b384f39SPeter Avalos 		zip->uncompressed_buffer_size = 256 * 1024;
24276b384f39SPeter Avalos 		zip->uncompressed_buffer
24286b384f39SPeter Avalos 		    = (unsigned char *)malloc(zip->uncompressed_buffer_size);
24296b384f39SPeter Avalos 		if (zip->uncompressed_buffer == NULL) {
24306b384f39SPeter Avalos 			archive_set_error(&a->archive, ENOMEM,
24316b384f39SPeter Avalos 			    "No memory for ZIP decompression");
24326b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
24336b384f39SPeter Avalos 		}
24346b384f39SPeter Avalos 	}
24356b384f39SPeter Avalos 
24366b384f39SPeter Avalos 	r = zip_deflate_init(a, zip);
24376b384f39SPeter Avalos 	if (r != ARCHIVE_OK)
24386b384f39SPeter Avalos 		return (r);
24396b384f39SPeter Avalos 
24406b384f39SPeter Avalos 	/*
24416b384f39SPeter Avalos 	 * Note: '1' here is a performance optimization.
24426b384f39SPeter Avalos 	 * Recall that the decompression layer returns a count of
24436b384f39SPeter Avalos 	 * available bytes; asking for more than that forces the
24446b384f39SPeter Avalos 	 * decompressor to combine reads by copying data.
24456b384f39SPeter Avalos 	 */
24466b384f39SPeter Avalos 	compressed_buff = sp = __archive_read_ahead(a, 1, &bytes_avail);
24476b384f39SPeter Avalos 	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
24486b384f39SPeter Avalos 	    && bytes_avail > zip->entry_bytes_remaining) {
24496b384f39SPeter Avalos 		bytes_avail = (ssize_t)zip->entry_bytes_remaining;
24506b384f39SPeter Avalos 	}
2451e95abc47Szrj 	if (bytes_avail < 0) {
24526b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
24536b384f39SPeter Avalos 		    "Truncated ZIP file body");
24546b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
24556b384f39SPeter Avalos 	}
24566b384f39SPeter Avalos 
24576b384f39SPeter Avalos 	if (zip->tctx_valid || zip->cctx_valid) {
24586b384f39SPeter Avalos 		if (zip->decrypted_bytes_remaining < (size_t)bytes_avail) {
2459e95abc47Szrj 			size_t buff_remaining =
2460085658deSDaniel Fojt 			    (zip->decrypted_buffer +
2461085658deSDaniel Fojt 			    zip->decrypted_buffer_size)
2462085658deSDaniel Fojt 			    - (zip->decrypted_ptr +
2463085658deSDaniel Fojt 			    zip->decrypted_bytes_remaining);
24646b384f39SPeter Avalos 
24656b384f39SPeter Avalos 			if (buff_remaining > (size_t)bytes_avail)
24666b384f39SPeter Avalos 				buff_remaining = (size_t)bytes_avail;
24676b384f39SPeter Avalos 
24686b384f39SPeter Avalos 			if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END) &&
24696b384f39SPeter Avalos 			      zip->entry_bytes_remaining > 0) {
24706b384f39SPeter Avalos 				if ((int64_t)(zip->decrypted_bytes_remaining
24716b384f39SPeter Avalos 				    + buff_remaining)
24726b384f39SPeter Avalos 				      > zip->entry_bytes_remaining) {
24736b384f39SPeter Avalos 					if (zip->entry_bytes_remaining <
24746b384f39SPeter Avalos 					    (int64_t)zip->decrypted_bytes_remaining)
24756b384f39SPeter Avalos 						buff_remaining = 0;
24766b384f39SPeter Avalos 					else
24776b384f39SPeter Avalos 						buff_remaining =
24786b384f39SPeter Avalos 						    (size_t)zip->entry_bytes_remaining
24796b384f39SPeter Avalos 						    - zip->decrypted_bytes_remaining;
24806b384f39SPeter Avalos 				}
24816b384f39SPeter Avalos 			}
24826b384f39SPeter Avalos 			if (buff_remaining > 0) {
24836b384f39SPeter Avalos 				if (zip->tctx_valid) {
24846b384f39SPeter Avalos 					trad_enc_decrypt_update(&zip->tctx,
24856b384f39SPeter Avalos 					    compressed_buff, buff_remaining,
24866b384f39SPeter Avalos 					    zip->decrypted_ptr
24876b384f39SPeter Avalos 					      + zip->decrypted_bytes_remaining,
24886b384f39SPeter Avalos 					    buff_remaining);
24896b384f39SPeter Avalos 				} else {
24906b384f39SPeter Avalos 					size_t dsize = buff_remaining;
24916b384f39SPeter Avalos 					archive_decrypto_aes_ctr_update(
24926b384f39SPeter Avalos 					    &zip->cctx,
24936b384f39SPeter Avalos 					    compressed_buff, buff_remaining,
24946b384f39SPeter Avalos 					    zip->decrypted_ptr
24956b384f39SPeter Avalos 					      + zip->decrypted_bytes_remaining,
24966b384f39SPeter Avalos 					    &dsize);
24976b384f39SPeter Avalos 				}
2498085658deSDaniel Fojt 				zip->decrypted_bytes_remaining +=
2499085658deSDaniel Fojt 				    buff_remaining;
25006b384f39SPeter Avalos 			}
25016b384f39SPeter Avalos 		}
25026b384f39SPeter Avalos 		bytes_avail = zip->decrypted_bytes_remaining;
25036b384f39SPeter Avalos 		compressed_buff = (const char *)zip->decrypted_ptr;
25046b384f39SPeter Avalos 	}
25056b384f39SPeter Avalos 
25066b384f39SPeter Avalos 	/*
25076b384f39SPeter Avalos 	 * A bug in zlib.h: stream.next_in should be marked 'const'
25086b384f39SPeter Avalos 	 * but isn't (the library never alters data through the
25096b384f39SPeter Avalos 	 * next_in pointer, only reads it).  The result: this ugly
25106b384f39SPeter Avalos 	 * cast to remove 'const'.
25116b384f39SPeter Avalos 	 */
25126b384f39SPeter Avalos 	zip->stream.next_in = (Bytef *)(uintptr_t)(const void *)compressed_buff;
25136b384f39SPeter Avalos 	zip->stream.avail_in = (uInt)bytes_avail;
25146b384f39SPeter Avalos 	zip->stream.total_in = 0;
25156b384f39SPeter Avalos 	zip->stream.next_out = zip->uncompressed_buffer;
25166b384f39SPeter Avalos 	zip->stream.avail_out = (uInt)zip->uncompressed_buffer_size;
25176b384f39SPeter Avalos 	zip->stream.total_out = 0;
25186b384f39SPeter Avalos 
25196b384f39SPeter Avalos 	r = inflate(&zip->stream, 0);
25206b384f39SPeter Avalos 	switch (r) {
25216b384f39SPeter Avalos 	case Z_OK:
25226b384f39SPeter Avalos 		break;
25236b384f39SPeter Avalos 	case Z_STREAM_END:
25246b384f39SPeter Avalos 		zip->end_of_entry = 1;
25256b384f39SPeter Avalos 		break;
25266b384f39SPeter Avalos 	case Z_MEM_ERROR:
25276b384f39SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
25286b384f39SPeter Avalos 		    "Out of memory for ZIP decompression");
25296b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
25306b384f39SPeter Avalos 	default:
25316b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
25326b384f39SPeter Avalos 		    "ZIP decompression failed (%d)", r);
25336b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
25346b384f39SPeter Avalos 	}
25356b384f39SPeter Avalos 
25366b384f39SPeter Avalos 	/* Consume as much as the compressor actually used. */
25376b384f39SPeter Avalos 	bytes_avail = zip->stream.total_in;
25386b384f39SPeter Avalos 	if (zip->tctx_valid || zip->cctx_valid) {
25396b384f39SPeter Avalos 		zip->decrypted_bytes_remaining -= bytes_avail;
25406b384f39SPeter Avalos 		if (zip->decrypted_bytes_remaining == 0)
25416b384f39SPeter Avalos 			zip->decrypted_ptr = zip->decrypted_buffer;
25426b384f39SPeter Avalos 		else
25436b384f39SPeter Avalos 			zip->decrypted_ptr += bytes_avail;
25446b384f39SPeter Avalos 	}
25456b384f39SPeter Avalos 	/* Calculate compressed data as much as we used.*/
25466b384f39SPeter Avalos 	if (zip->hctx_valid)
25476b384f39SPeter Avalos 		archive_hmac_sha1_update(&zip->hctx, sp, bytes_avail);
25486b384f39SPeter Avalos 	__archive_read_consume(a, bytes_avail);
25496b384f39SPeter Avalos 	zip->entry_bytes_remaining -= bytes_avail;
25506b384f39SPeter Avalos 	zip->entry_compressed_bytes_read += bytes_avail;
25516b384f39SPeter Avalos 
25526b384f39SPeter Avalos 	*size = zip->stream.total_out;
25536b384f39SPeter Avalos 	zip->entry_uncompressed_bytes_read += zip->stream.total_out;
25546b384f39SPeter Avalos 	*buff = zip->uncompressed_buffer;
25556b384f39SPeter Avalos 
25566b384f39SPeter Avalos 	if (zip->end_of_entry && zip->hctx_valid) {
25576b384f39SPeter Avalos 		r = check_authentication_code(a, NULL);
25586b384f39SPeter Avalos 		if (r != ARCHIVE_OK)
25596b384f39SPeter Avalos 			return (r);
25606b384f39SPeter Avalos 	}
25616b384f39SPeter Avalos 
2562085658deSDaniel Fojt 	r = consume_optional_marker(a, zip);
2563085658deSDaniel Fojt 	if (r != ARCHIVE_OK)
2564085658deSDaniel Fojt 		return (r);
25656b384f39SPeter Avalos 
25666b384f39SPeter Avalos 	return (ARCHIVE_OK);
25676b384f39SPeter Avalos }
25686b384f39SPeter Avalos #endif
25696b384f39SPeter Avalos 
25706b384f39SPeter Avalos static int
read_decryption_header(struct archive_read * a)25716b384f39SPeter Avalos read_decryption_header(struct archive_read *a)
25726b384f39SPeter Avalos {
25736b384f39SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
25746b384f39SPeter Avalos 	const char *p;
25756b384f39SPeter Avalos 	unsigned int remaining_size;
25766b384f39SPeter Avalos 	unsigned int ts;
25776b384f39SPeter Avalos 
25786b384f39SPeter Avalos 	/*
25796b384f39SPeter Avalos 	 * Read an initialization vector data field.
25806b384f39SPeter Avalos 	 */
25816b384f39SPeter Avalos 	p = __archive_read_ahead(a, 2, NULL);
25826b384f39SPeter Avalos 	if (p == NULL)
25836b384f39SPeter Avalos 		goto truncated;
25846b384f39SPeter Avalos 	ts = zip->iv_size;
25856b384f39SPeter Avalos 	zip->iv_size = archive_le16dec(p);
25866b384f39SPeter Avalos 	__archive_read_consume(a, 2);
25876b384f39SPeter Avalos 	if (ts < zip->iv_size) {
25886b384f39SPeter Avalos 		free(zip->iv);
25896b384f39SPeter Avalos 		zip->iv = NULL;
25906b384f39SPeter Avalos 	}
25916b384f39SPeter Avalos 	p = __archive_read_ahead(a, zip->iv_size, NULL);
25926b384f39SPeter Avalos 	if (p == NULL)
25936b384f39SPeter Avalos 		goto truncated;
25946b384f39SPeter Avalos 	if (zip->iv == NULL) {
25956b384f39SPeter Avalos 		zip->iv = malloc(zip->iv_size);
25966b384f39SPeter Avalos 		if (zip->iv == NULL)
25976b384f39SPeter Avalos 			goto nomem;
25986b384f39SPeter Avalos 	}
25996b384f39SPeter Avalos 	memcpy(zip->iv, p, zip->iv_size);
26006b384f39SPeter Avalos 	__archive_read_consume(a, zip->iv_size);
26016b384f39SPeter Avalos 
26026b384f39SPeter Avalos 	/*
26036b384f39SPeter Avalos 	 * Read a size of remaining decryption header field.
26046b384f39SPeter Avalos 	 */
26056b384f39SPeter Avalos 	p = __archive_read_ahead(a, 14, NULL);
26066b384f39SPeter Avalos 	if (p == NULL)
26076b384f39SPeter Avalos 		goto truncated;
26086b384f39SPeter Avalos 	remaining_size = archive_le32dec(p);
26096b384f39SPeter Avalos 	if (remaining_size < 16 || remaining_size > (1 << 18))
26106b384f39SPeter Avalos 		goto corrupted;
26116b384f39SPeter Avalos 
26126b384f39SPeter Avalos 	/* Check if format version is supported. */
26136b384f39SPeter Avalos 	if (archive_le16dec(p+4) != 3) {
26146b384f39SPeter Avalos 		archive_set_error(&a->archive,
26156b384f39SPeter Avalos 		    ARCHIVE_ERRNO_FILE_FORMAT,
26166b384f39SPeter Avalos 		    "Unsupported encryption format version: %u",
26176b384f39SPeter Avalos 		    archive_le16dec(p+4));
26186b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
26196b384f39SPeter Avalos 	}
26206b384f39SPeter Avalos 
26216b384f39SPeter Avalos 	/*
26226b384f39SPeter Avalos 	 * Read an encryption algorithm field.
26236b384f39SPeter Avalos 	 */
26246b384f39SPeter Avalos 	zip->alg_id = archive_le16dec(p+6);
26256b384f39SPeter Avalos 	switch (zip->alg_id) {
26266b384f39SPeter Avalos 	case 0x6601:/* DES */
26276b384f39SPeter Avalos 	case 0x6602:/* RC2 */
26286b384f39SPeter Avalos 	case 0x6603:/* 3DES 168 */
26296b384f39SPeter Avalos 	case 0x6609:/* 3DES 112 */
26306b384f39SPeter Avalos 	case 0x660E:/* AES 128 */
26316b384f39SPeter Avalos 	case 0x660F:/* AES 192 */
26326b384f39SPeter Avalos 	case 0x6610:/* AES 256 */
26336b384f39SPeter Avalos 	case 0x6702:/* RC2 (version >= 5.2) */
26346b384f39SPeter Avalos 	case 0x6720:/* Blowfish */
26356b384f39SPeter Avalos 	case 0x6721:/* Twofish */
26366b384f39SPeter Avalos 	case 0x6801:/* RC4 */
2637e95abc47Szrj 		/* Supported encryption algorithm. */
26386b384f39SPeter Avalos 		break;
26396b384f39SPeter Avalos 	default:
26406b384f39SPeter Avalos 		archive_set_error(&a->archive,
26416b384f39SPeter Avalos 		    ARCHIVE_ERRNO_FILE_FORMAT,
26426b384f39SPeter Avalos 		    "Unknown encryption algorithm: %u", zip->alg_id);
26436b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
26446b384f39SPeter Avalos 	}
26456b384f39SPeter Avalos 
26466b384f39SPeter Avalos 	/*
26476b384f39SPeter Avalos 	 * Read a bit length field.
26486b384f39SPeter Avalos 	 */
26496b384f39SPeter Avalos 	zip->bit_len = archive_le16dec(p+8);
26506b384f39SPeter Avalos 
26516b384f39SPeter Avalos 	/*
26526b384f39SPeter Avalos 	 * Read a flags field.
26536b384f39SPeter Avalos 	 */
26546b384f39SPeter Avalos 	zip->flags = archive_le16dec(p+10);
26556b384f39SPeter Avalos 	switch (zip->flags & 0xf000) {
26566b384f39SPeter Avalos 	case 0x0001: /* Password is required to decrypt. */
26576b384f39SPeter Avalos 	case 0x0002: /* Certificates only. */
26586b384f39SPeter Avalos 	case 0x0003: /* Password or certificate required to decrypt. */
26596b384f39SPeter Avalos 		break;
26606b384f39SPeter Avalos 	default:
26616b384f39SPeter Avalos 		archive_set_error(&a->archive,
26626b384f39SPeter Avalos 		    ARCHIVE_ERRNO_FILE_FORMAT,
26636b384f39SPeter Avalos 		    "Unknown encryption flag: %u", zip->flags);
26646b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
26656b384f39SPeter Avalos 	}
26666b384f39SPeter Avalos 	if ((zip->flags & 0xf000) == 0 ||
26676b384f39SPeter Avalos 	    (zip->flags & 0xf000) == 0x4000) {
26686b384f39SPeter Avalos 		archive_set_error(&a->archive,
26696b384f39SPeter Avalos 		    ARCHIVE_ERRNO_FILE_FORMAT,
26706b384f39SPeter Avalos 		    "Unknown encryption flag: %u", zip->flags);
26716b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
26726b384f39SPeter Avalos 	}
26736b384f39SPeter Avalos 
26746b384f39SPeter Avalos 	/*
26756b384f39SPeter Avalos 	 * Read an encrypted random data field.
26766b384f39SPeter Avalos 	 */
26776b384f39SPeter Avalos 	ts = zip->erd_size;
26786b384f39SPeter Avalos 	zip->erd_size = archive_le16dec(p+12);
26796b384f39SPeter Avalos 	__archive_read_consume(a, 14);
26806b384f39SPeter Avalos 	if ((zip->erd_size & 0xf) != 0 ||
26816b384f39SPeter Avalos 	    (zip->erd_size + 16) > remaining_size ||
26826b384f39SPeter Avalos 	    (zip->erd_size + 16) < zip->erd_size)
26836b384f39SPeter Avalos 		goto corrupted;
26846b384f39SPeter Avalos 
26856b384f39SPeter Avalos 	if (ts < zip->erd_size) {
26866b384f39SPeter Avalos 		free(zip->erd);
26876b384f39SPeter Avalos 		zip->erd = NULL;
26886b384f39SPeter Avalos 	}
26896b384f39SPeter Avalos 	p = __archive_read_ahead(a, zip->erd_size, NULL);
26906b384f39SPeter Avalos 	if (p == NULL)
26916b384f39SPeter Avalos 		goto truncated;
26926b384f39SPeter Avalos 	if (zip->erd == NULL) {
26936b384f39SPeter Avalos 		zip->erd = malloc(zip->erd_size);
26946b384f39SPeter Avalos 		if (zip->erd == NULL)
26956b384f39SPeter Avalos 			goto nomem;
26966b384f39SPeter Avalos 	}
26976b384f39SPeter Avalos 	memcpy(zip->erd, p, zip->erd_size);
26986b384f39SPeter Avalos 	__archive_read_consume(a, zip->erd_size);
26996b384f39SPeter Avalos 
27006b384f39SPeter Avalos 	/*
27016b384f39SPeter Avalos 	 * Read a reserved data field.
27026b384f39SPeter Avalos 	 */
27036b384f39SPeter Avalos 	p = __archive_read_ahead(a, 4, NULL);
27046b384f39SPeter Avalos 	if (p == NULL)
27056b384f39SPeter Avalos 		goto truncated;
27066b384f39SPeter Avalos 	/* Reserved data size should be zero. */
27076b384f39SPeter Avalos 	if (archive_le32dec(p) != 0)
27086b384f39SPeter Avalos 		goto corrupted;
27096b384f39SPeter Avalos 	__archive_read_consume(a, 4);
27106b384f39SPeter Avalos 
27116b384f39SPeter Avalos 	/*
27126b384f39SPeter Avalos 	 * Read a password validation data field.
27136b384f39SPeter Avalos 	 */
27146b384f39SPeter Avalos 	p = __archive_read_ahead(a, 2, NULL);
27156b384f39SPeter Avalos 	if (p == NULL)
27166b384f39SPeter Avalos 		goto truncated;
27176b384f39SPeter Avalos 	ts = zip->v_size;
27186b384f39SPeter Avalos 	zip->v_size = archive_le16dec(p);
27196b384f39SPeter Avalos 	__archive_read_consume(a, 2);
27206b384f39SPeter Avalos 	if ((zip->v_size & 0x0f) != 0 ||
27216b384f39SPeter Avalos 	    (zip->erd_size + zip->v_size + 16) > remaining_size ||
27226b384f39SPeter Avalos 	    (zip->erd_size + zip->v_size + 16) < (zip->erd_size + zip->v_size))
27236b384f39SPeter Avalos 		goto corrupted;
27246b384f39SPeter Avalos 	if (ts < zip->v_size) {
27256b384f39SPeter Avalos 		free(zip->v_data);
27266b384f39SPeter Avalos 		zip->v_data = NULL;
27276b384f39SPeter Avalos 	}
27286b384f39SPeter Avalos 	p = __archive_read_ahead(a, zip->v_size, NULL);
27296b384f39SPeter Avalos 	if (p == NULL)
27306b384f39SPeter Avalos 		goto truncated;
27316b384f39SPeter Avalos 	if (zip->v_data == NULL) {
27326b384f39SPeter Avalos 		zip->v_data = malloc(zip->v_size);
27336b384f39SPeter Avalos 		if (zip->v_data == NULL)
27346b384f39SPeter Avalos 			goto nomem;
27356b384f39SPeter Avalos 	}
27366b384f39SPeter Avalos 	memcpy(zip->v_data, p, zip->v_size);
27376b384f39SPeter Avalos 	__archive_read_consume(a, zip->v_size);
27386b384f39SPeter Avalos 
27396b384f39SPeter Avalos 	p = __archive_read_ahead(a, 4, NULL);
27406b384f39SPeter Avalos 	if (p == NULL)
27416b384f39SPeter Avalos 		goto truncated;
27426b384f39SPeter Avalos 	zip->v_crc32 = archive_le32dec(p);
27436b384f39SPeter Avalos 	__archive_read_consume(a, 4);
27446b384f39SPeter Avalos 
27456b384f39SPeter Avalos 	/*return (ARCHIVE_OK);
2746e95abc47Szrj 	 * This is not fully implemented yet.*/
27476b384f39SPeter Avalos 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
27486b384f39SPeter Avalos 	    "Encrypted file is unsupported");
27496b384f39SPeter Avalos 	return (ARCHIVE_FAILED);
27506b384f39SPeter Avalos truncated:
27516b384f39SPeter Avalos 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
27526b384f39SPeter Avalos 	    "Truncated ZIP file data");
27536b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
27546b384f39SPeter Avalos corrupted:
27556b384f39SPeter Avalos 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
27566b384f39SPeter Avalos 	    "Corrupted ZIP file data");
27576b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
27586b384f39SPeter Avalos nomem:
27596b384f39SPeter Avalos 	archive_set_error(&a->archive, ENOMEM,
27606b384f39SPeter Avalos 	    "No memory for ZIP decryption");
27616b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
27626b384f39SPeter Avalos }
27636b384f39SPeter Avalos 
27646b384f39SPeter Avalos static int
zip_alloc_decryption_buffer(struct archive_read * a)27656b384f39SPeter Avalos zip_alloc_decryption_buffer(struct archive_read *a)
27666b384f39SPeter Avalos {
27676b384f39SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
27686b384f39SPeter Avalos 	size_t bs = 256 * 1024;
27696b384f39SPeter Avalos 
27706b384f39SPeter Avalos 	if (zip->decrypted_buffer == NULL) {
27716b384f39SPeter Avalos 		zip->decrypted_buffer_size = bs;
27726b384f39SPeter Avalos 		zip->decrypted_buffer = malloc(bs);
27736b384f39SPeter Avalos 		if (zip->decrypted_buffer == NULL) {
27746b384f39SPeter Avalos 			archive_set_error(&a->archive, ENOMEM,
27756b384f39SPeter Avalos 			    "No memory for ZIP decryption");
27766b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
27776b384f39SPeter Avalos 		}
27786b384f39SPeter Avalos 	}
27796b384f39SPeter Avalos 	zip->decrypted_ptr = zip->decrypted_buffer;
27806b384f39SPeter Avalos 	return (ARCHIVE_OK);
27816b384f39SPeter Avalos }
27826b384f39SPeter Avalos 
27836b384f39SPeter Avalos static int
init_traditional_PKWARE_decryption(struct archive_read * a)27846b384f39SPeter Avalos init_traditional_PKWARE_decryption(struct archive_read *a)
27856b384f39SPeter Avalos {
27866b384f39SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
27876b384f39SPeter Avalos 	const void *p;
27886b384f39SPeter Avalos 	int retry;
27896b384f39SPeter Avalos 	int r;
27906b384f39SPeter Avalos 
27916b384f39SPeter Avalos 	if (zip->tctx_valid)
27926b384f39SPeter Avalos 		return (ARCHIVE_OK);
27936b384f39SPeter Avalos 
27946b384f39SPeter Avalos 	/*
27956b384f39SPeter Avalos 	   Read the 12 bytes encryption header stored at
27966b384f39SPeter Avalos 	   the start of the data area.
27976b384f39SPeter Avalos 	 */
27986b384f39SPeter Avalos #define ENC_HEADER_SIZE	12
27996b384f39SPeter Avalos 	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
28006b384f39SPeter Avalos 	    && zip->entry_bytes_remaining < ENC_HEADER_SIZE) {
28016b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
28026b384f39SPeter Avalos 		    "Truncated Zip encrypted body: only %jd bytes available",
28036b384f39SPeter Avalos 		    (intmax_t)zip->entry_bytes_remaining);
28046b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
28056b384f39SPeter Avalos 	}
28066b384f39SPeter Avalos 
28076b384f39SPeter Avalos 	p = __archive_read_ahead(a, ENC_HEADER_SIZE, NULL);
28086b384f39SPeter Avalos 	if (p == NULL) {
28096b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
28106b384f39SPeter Avalos 		    "Truncated ZIP file data");
28116b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
28126b384f39SPeter Avalos 	}
28136b384f39SPeter Avalos 
28146b384f39SPeter Avalos 	for (retry = 0;; retry++) {
28156b384f39SPeter Avalos 		const char *passphrase;
28166b384f39SPeter Avalos 		uint8_t crcchk;
28176b384f39SPeter Avalos 
28186b384f39SPeter Avalos 		passphrase = __archive_read_next_passphrase(a);
28196b384f39SPeter Avalos 		if (passphrase == NULL) {
28206b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
28216b384f39SPeter Avalos 			    (retry > 0)?
28226b384f39SPeter Avalos 				"Incorrect passphrase":
28236b384f39SPeter Avalos 				"Passphrase required for this entry");
28246b384f39SPeter Avalos 			return (ARCHIVE_FAILED);
28256b384f39SPeter Avalos 		}
28266b384f39SPeter Avalos 
28276b384f39SPeter Avalos 		/*
2828e95abc47Szrj 		 * Initialize ctx for Traditional PKWARE Decryption.
28296b384f39SPeter Avalos 		 */
28306b384f39SPeter Avalos 		r = trad_enc_init(&zip->tctx, passphrase, strlen(passphrase),
28316b384f39SPeter Avalos 			p, ENC_HEADER_SIZE, &crcchk);
28326b384f39SPeter Avalos 		if (r == 0 && crcchk == zip->entry->decdat)
28336b384f39SPeter Avalos 			break;/* The passphrase is OK. */
28346b384f39SPeter Avalos 		if (retry > 10000) {
28356b384f39SPeter Avalos 			/* Avoid infinity loop. */
28366b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
28376b384f39SPeter Avalos 			    "Too many incorrect passphrases");
28386b384f39SPeter Avalos 			return (ARCHIVE_FAILED);
28396b384f39SPeter Avalos 		}
28406b384f39SPeter Avalos 	}
28416b384f39SPeter Avalos 
28426b384f39SPeter Avalos 	__archive_read_consume(a, ENC_HEADER_SIZE);
28436b384f39SPeter Avalos 	zip->tctx_valid = 1;
28446b384f39SPeter Avalos 	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)) {
28456b384f39SPeter Avalos 	    zip->entry_bytes_remaining -= ENC_HEADER_SIZE;
28466b384f39SPeter Avalos 	}
28476b384f39SPeter Avalos 	/*zip->entry_uncompressed_bytes_read += ENC_HEADER_SIZE;*/
28486b384f39SPeter Avalos 	zip->entry_compressed_bytes_read += ENC_HEADER_SIZE;
28496b384f39SPeter Avalos 	zip->decrypted_bytes_remaining = 0;
28506b384f39SPeter Avalos 
28516b384f39SPeter Avalos 	return (zip_alloc_decryption_buffer(a));
28526b384f39SPeter Avalos #undef ENC_HEADER_SIZE
28536b384f39SPeter Avalos }
28546b384f39SPeter Avalos 
28556b384f39SPeter Avalos static int
init_WinZip_AES_decryption(struct archive_read * a)28566b384f39SPeter Avalos init_WinZip_AES_decryption(struct archive_read *a)
28576b384f39SPeter Avalos {
28586b384f39SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
28596b384f39SPeter Avalos 	const void *p;
28606b384f39SPeter Avalos 	const uint8_t *pv;
28616b384f39SPeter Avalos 	size_t key_len, salt_len;
28626b384f39SPeter Avalos 	uint8_t derived_key[MAX_DERIVED_KEY_BUF_SIZE];
28636b384f39SPeter Avalos 	int retry;
28646b384f39SPeter Avalos 	int r;
28656b384f39SPeter Avalos 
28666b384f39SPeter Avalos 	if (zip->cctx_valid || zip->hctx_valid)
28676b384f39SPeter Avalos 		return (ARCHIVE_OK);
28686b384f39SPeter Avalos 
28696b384f39SPeter Avalos 	switch (zip->entry->aes_extra.strength) {
28706b384f39SPeter Avalos 	case 1: salt_len = 8;  key_len = 16; break;
28716b384f39SPeter Avalos 	case 2: salt_len = 12; key_len = 24; break;
28726b384f39SPeter Avalos 	case 3: salt_len = 16; key_len = 32; break;
28736b384f39SPeter Avalos 	default: goto corrupted;
28746b384f39SPeter Avalos 	}
28756b384f39SPeter Avalos 	p = __archive_read_ahead(a, salt_len + 2, NULL);
28766b384f39SPeter Avalos 	if (p == NULL)
28776b384f39SPeter Avalos 		goto truncated;
28786b384f39SPeter Avalos 
28796b384f39SPeter Avalos 	for (retry = 0;; retry++) {
28806b384f39SPeter Avalos 		const char *passphrase;
28816b384f39SPeter Avalos 
28826b384f39SPeter Avalos 		passphrase = __archive_read_next_passphrase(a);
28836b384f39SPeter Avalos 		if (passphrase == NULL) {
28846b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
28856b384f39SPeter Avalos 			    (retry > 0)?
28866b384f39SPeter Avalos 				"Incorrect passphrase":
28876b384f39SPeter Avalos 				"Passphrase required for this entry");
28886b384f39SPeter Avalos 			return (ARCHIVE_FAILED);
28896b384f39SPeter Avalos 		}
28906b384f39SPeter Avalos 		memset(derived_key, 0, sizeof(derived_key));
28916b384f39SPeter Avalos 		r = archive_pbkdf2_sha1(passphrase, strlen(passphrase),
28926b384f39SPeter Avalos 		    p, salt_len, 1000, derived_key, key_len * 2 + 2);
28936b384f39SPeter Avalos 		if (r != 0) {
28946b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
28956b384f39SPeter Avalos 			    "Decryption is unsupported due to lack of "
28966b384f39SPeter Avalos 			    "crypto library");
28976b384f39SPeter Avalos 			return (ARCHIVE_FAILED);
28986b384f39SPeter Avalos 		}
28996b384f39SPeter Avalos 
29006b384f39SPeter Avalos 		/* Check password verification value. */
29016b384f39SPeter Avalos 		pv = ((const uint8_t *)p) + salt_len;
29026b384f39SPeter Avalos 		if (derived_key[key_len * 2] == pv[0] &&
29036b384f39SPeter Avalos 		    derived_key[key_len * 2 + 1] == pv[1])
29046b384f39SPeter Avalos 			break;/* The passphrase is OK. */
29056b384f39SPeter Avalos 		if (retry > 10000) {
29066b384f39SPeter Avalos 			/* Avoid infinity loop. */
29076b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
29086b384f39SPeter Avalos 			    "Too many incorrect passphrases");
29096b384f39SPeter Avalos 			return (ARCHIVE_FAILED);
29106b384f39SPeter Avalos 		}
29116b384f39SPeter Avalos 	}
29126b384f39SPeter Avalos 
29136b384f39SPeter Avalos 	r = archive_decrypto_aes_ctr_init(&zip->cctx, derived_key, key_len);
29146b384f39SPeter Avalos 	if (r != 0) {
29156b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
29166b384f39SPeter Avalos 		    "Decryption is unsupported due to lack of crypto library");
29176b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
29186b384f39SPeter Avalos 	}
29196b384f39SPeter Avalos 	r = archive_hmac_sha1_init(&zip->hctx, derived_key + key_len, key_len);
29206b384f39SPeter Avalos 	if (r != 0) {
29216b384f39SPeter Avalos 		archive_decrypto_aes_ctr_release(&zip->cctx);
29226b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
29236b384f39SPeter Avalos 		    "Failed to initialize HMAC-SHA1");
29246b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
29256b384f39SPeter Avalos 	}
29266b384f39SPeter Avalos 	zip->cctx_valid = zip->hctx_valid = 1;
29276b384f39SPeter Avalos 	__archive_read_consume(a, salt_len + 2);
29286b384f39SPeter Avalos 	zip->entry_bytes_remaining -= salt_len + 2 + AUTH_CODE_SIZE;
29296b384f39SPeter Avalos 	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
29306b384f39SPeter Avalos 	    && zip->entry_bytes_remaining < 0)
29316b384f39SPeter Avalos 		goto corrupted;
29326b384f39SPeter Avalos 	zip->entry_compressed_bytes_read += salt_len + 2 + AUTH_CODE_SIZE;
29336b384f39SPeter Avalos 	zip->decrypted_bytes_remaining = 0;
29346b384f39SPeter Avalos 
29356b384f39SPeter Avalos 	zip->entry->compression = zip->entry->aes_extra.compression;
29366b384f39SPeter Avalos 	return (zip_alloc_decryption_buffer(a));
29376b384f39SPeter Avalos 
29386b384f39SPeter Avalos truncated:
29396b384f39SPeter Avalos 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
29406b384f39SPeter Avalos 	    "Truncated ZIP file data");
29416b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
29426b384f39SPeter Avalos corrupted:
29436b384f39SPeter Avalos 	archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
29446b384f39SPeter Avalos 	    "Corrupted ZIP file data");
29456b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
29466b384f39SPeter Avalos }
29476b384f39SPeter Avalos 
29486b384f39SPeter Avalos static int
archive_read_format_zip_read_data(struct archive_read * a,const void ** buff,size_t * size,int64_t * offset)29496b384f39SPeter Avalos archive_read_format_zip_read_data(struct archive_read *a,
29506b384f39SPeter Avalos     const void **buff, size_t *size, int64_t *offset)
29516b384f39SPeter Avalos {
29526b384f39SPeter Avalos 	int r;
29536b384f39SPeter Avalos 	struct zip *zip = (struct zip *)(a->format->data);
29546b384f39SPeter Avalos 
29556b384f39SPeter Avalos 	if (zip->has_encrypted_entries ==
29566b384f39SPeter Avalos 			ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW) {
29576b384f39SPeter Avalos 		zip->has_encrypted_entries = 0;
29586b384f39SPeter Avalos 	}
29596b384f39SPeter Avalos 
29606b384f39SPeter Avalos 	*offset = zip->entry_uncompressed_bytes_read;
29616b384f39SPeter Avalos 	*size = 0;
29626b384f39SPeter Avalos 	*buff = NULL;
29636b384f39SPeter Avalos 
29646b384f39SPeter Avalos 	/* If we hit end-of-entry last time, return ARCHIVE_EOF. */
29656b384f39SPeter Avalos 	if (zip->end_of_entry)
29666b384f39SPeter Avalos 		return (ARCHIVE_EOF);
29676b384f39SPeter Avalos 
29686b384f39SPeter Avalos 	/* Return EOF immediately if this is a non-regular file. */
29696b384f39SPeter Avalos 	if (AE_IFREG != (zip->entry->mode & AE_IFMT))
29706b384f39SPeter Avalos 		return (ARCHIVE_EOF);
29716b384f39SPeter Avalos 
29726b384f39SPeter Avalos 	__archive_read_consume(a, zip->unconsumed);
29736b384f39SPeter Avalos 	zip->unconsumed = 0;
29746b384f39SPeter Avalos 
29756b384f39SPeter Avalos 	if (zip->init_decryption) {
29766b384f39SPeter Avalos 		zip->has_encrypted_entries = 1;
29776b384f39SPeter Avalos 		if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED)
29786b384f39SPeter Avalos 			r = read_decryption_header(a);
29796b384f39SPeter Avalos 		else if (zip->entry->compression == WINZIP_AES_ENCRYPTION)
29806b384f39SPeter Avalos 			r = init_WinZip_AES_decryption(a);
29816b384f39SPeter Avalos 		else
29826b384f39SPeter Avalos 			r = init_traditional_PKWARE_decryption(a);
29836b384f39SPeter Avalos 		if (r != ARCHIVE_OK)
29846b384f39SPeter Avalos 			return (r);
29856b384f39SPeter Avalos 		zip->init_decryption = 0;
29866b384f39SPeter Avalos 	}
29876b384f39SPeter Avalos 
29886b384f39SPeter Avalos 	switch(zip->entry->compression) {
29896b384f39SPeter Avalos 	case 0:  /* No compression. */
29906b384f39SPeter Avalos 		r =  zip_read_data_none(a, buff, size, offset);
29916b384f39SPeter Avalos 		break;
2992085658deSDaniel Fojt #ifdef HAVE_BZLIB_H
2993085658deSDaniel Fojt 	case 12: /* ZIPx bzip2 compression. */
2994085658deSDaniel Fojt 		r = zip_read_data_zipx_bzip2(a, buff, size, offset);
2995085658deSDaniel Fojt 		break;
2996085658deSDaniel Fojt #endif
2997085658deSDaniel Fojt #if HAVE_LZMA_H && HAVE_LIBLZMA
2998085658deSDaniel Fojt 	case 14: /* ZIPx LZMA compression. */
2999085658deSDaniel Fojt 		r = zip_read_data_zipx_lzma_alone(a, buff, size, offset);
3000085658deSDaniel Fojt 		break;
3001085658deSDaniel Fojt 	case 95: /* ZIPx XZ compression. */
3002085658deSDaniel Fojt 		r = zip_read_data_zipx_xz(a, buff, size, offset);
3003085658deSDaniel Fojt 		break;
3004085658deSDaniel Fojt #endif
3005*50f8aa9cSAntonio Huete Jimenez #if HAVE_ZSTD_H && HAVE_LIBZSTD
3006*50f8aa9cSAntonio Huete Jimenez 	case 93: /* ZIPx Zstd compression. */
3007*50f8aa9cSAntonio Huete Jimenez 		r = zip_read_data_zipx_zstd(a, buff, size, offset);
3008*50f8aa9cSAntonio Huete Jimenez 		break;
3009*50f8aa9cSAntonio Huete Jimenez #endif
3010085658deSDaniel Fojt 	/* PPMd support is built-in, so we don't need any #if guards. */
3011085658deSDaniel Fojt 	case 98: /* ZIPx PPMd compression. */
3012085658deSDaniel Fojt 		r = zip_read_data_zipx_ppmd(a, buff, size, offset);
3013085658deSDaniel Fojt 		break;
3014085658deSDaniel Fojt 
30156b384f39SPeter Avalos #ifdef HAVE_ZLIB_H
30166b384f39SPeter Avalos 	case 8: /* Deflate compression. */
30176b384f39SPeter Avalos 		r =  zip_read_data_deflate(a, buff, size, offset);
30186b384f39SPeter Avalos 		break;
30196b384f39SPeter Avalos #endif
30206b384f39SPeter Avalos 	default: /* Unsupported compression. */
30216b384f39SPeter Avalos 		/* Return a warning. */
30226b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
3023085658deSDaniel Fojt 		    "Unsupported ZIP compression method (%d: %s)",
3024085658deSDaniel Fojt 		    zip->entry->compression, compression_name(zip->entry->compression));
30256b384f39SPeter Avalos 		/* We can't decompress this entry, but we will
30266b384f39SPeter Avalos 		 * be able to skip() it and try the next entry. */
30276b384f39SPeter Avalos 		return (ARCHIVE_FAILED);
30286b384f39SPeter Avalos 		break;
30296b384f39SPeter Avalos 	}
30306b384f39SPeter Avalos 	if (r != ARCHIVE_OK)
30316b384f39SPeter Avalos 		return (r);
30326b384f39SPeter Avalos 	/* Update checksum */
30336b384f39SPeter Avalos 	if (*size)
30346b384f39SPeter Avalos 		zip->entry_crc32 = zip->crc32func(zip->entry_crc32, *buff,
30356b384f39SPeter Avalos 		    (unsigned)*size);
30366b384f39SPeter Avalos 	/* If we hit the end, swallow any end-of-data marker. */
30376b384f39SPeter Avalos 	if (zip->end_of_entry) {
30386b384f39SPeter Avalos 		/* Check file size, CRC against these values. */
30396b384f39SPeter Avalos 		if (zip->entry->compressed_size !=
30406b384f39SPeter Avalos 		    zip->entry_compressed_bytes_read) {
30416b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
30426b384f39SPeter Avalos 			    "ZIP compressed data is wrong size "
30436b384f39SPeter Avalos 			    "(read %jd, expected %jd)",
30446b384f39SPeter Avalos 			    (intmax_t)zip->entry_compressed_bytes_read,
30456b384f39SPeter Avalos 			    (intmax_t)zip->entry->compressed_size);
30466b384f39SPeter Avalos 			return (ARCHIVE_WARN);
30476b384f39SPeter Avalos 		}
30486b384f39SPeter Avalos 		/* Size field only stores the lower 32 bits of the actual
30496b384f39SPeter Avalos 		 * size. */
30506b384f39SPeter Avalos 		if ((zip->entry->uncompressed_size & UINT32_MAX)
30516b384f39SPeter Avalos 		    != (zip->entry_uncompressed_bytes_read & UINT32_MAX)) {
30526b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
30536b384f39SPeter Avalos 			    "ZIP uncompressed data is wrong size "
30546b384f39SPeter Avalos 			    "(read %jd, expected %jd)\n",
30556b384f39SPeter Avalos 			    (intmax_t)zip->entry_uncompressed_bytes_read,
30566b384f39SPeter Avalos 			    (intmax_t)zip->entry->uncompressed_size);
30576b384f39SPeter Avalos 			return (ARCHIVE_WARN);
30586b384f39SPeter Avalos 		}
30596b384f39SPeter Avalos 		/* Check computed CRC against header */
30606b384f39SPeter Avalos 		if ((!zip->hctx_valid ||
30616b384f39SPeter Avalos 		      zip->entry->aes_extra.vendor != AES_VENDOR_AE_2) &&
30626b384f39SPeter Avalos 		   zip->entry->crc32 != zip->entry_crc32
30636b384f39SPeter Avalos 		    && !zip->ignore_crc32) {
30646b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
30656b384f39SPeter Avalos 			    "ZIP bad CRC: 0x%lx should be 0x%lx",
30666b384f39SPeter Avalos 			    (unsigned long)zip->entry_crc32,
30676b384f39SPeter Avalos 			    (unsigned long)zip->entry->crc32);
30686b384f39SPeter Avalos 			return (ARCHIVE_WARN);
30696b384f39SPeter Avalos 		}
30706b384f39SPeter Avalos 	}
30716b384f39SPeter Avalos 
30726b384f39SPeter Avalos 	return (ARCHIVE_OK);
30736b384f39SPeter Avalos }
30746b384f39SPeter Avalos 
30756b384f39SPeter Avalos static int
archive_read_format_zip_cleanup(struct archive_read * a)30766b384f39SPeter Avalos archive_read_format_zip_cleanup(struct archive_read *a)
30776b384f39SPeter Avalos {
30786b384f39SPeter Avalos 	struct zip *zip;
30796b384f39SPeter Avalos 	struct zip_entry *zip_entry, *next_zip_entry;
30806b384f39SPeter Avalos 
30816b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
3082085658deSDaniel Fojt 
30836b384f39SPeter Avalos #ifdef HAVE_ZLIB_H
30846b384f39SPeter Avalos 	if (zip->stream_valid)
30856b384f39SPeter Avalos 		inflateEnd(&zip->stream);
30866b384f39SPeter Avalos #endif
3087085658deSDaniel Fojt 
3088085658deSDaniel Fojt #if HAVE_LZMA_H && HAVE_LIBLZMA
3089085658deSDaniel Fojt     if (zip->zipx_lzma_valid) {
3090085658deSDaniel Fojt 		lzma_end(&zip->zipx_lzma_stream);
3091085658deSDaniel Fojt 	}
3092085658deSDaniel Fojt #endif
3093085658deSDaniel Fojt 
3094085658deSDaniel Fojt #ifdef HAVE_BZLIB_H
3095085658deSDaniel Fojt 	if (zip->bzstream_valid) {
3096085658deSDaniel Fojt 		BZ2_bzDecompressEnd(&zip->bzstream);
3097085658deSDaniel Fojt 	}
3098085658deSDaniel Fojt #endif
3099085658deSDaniel Fojt 
3100*50f8aa9cSAntonio Huete Jimenez #if HAVE_ZSTD_H && HAVE_LIBZSTD
3101*50f8aa9cSAntonio Huete Jimenez 	if (zip->zstdstream_valid) {
3102*50f8aa9cSAntonio Huete Jimenez 		ZSTD_freeDStream(zip->zstdstream);
3103*50f8aa9cSAntonio Huete Jimenez 	}
3104*50f8aa9cSAntonio Huete Jimenez #endif
3105*50f8aa9cSAntonio Huete Jimenez 
3106085658deSDaniel Fojt 	free(zip->uncompressed_buffer);
3107085658deSDaniel Fojt 
3108085658deSDaniel Fojt 	if (zip->ppmd8_valid)
3109085658deSDaniel Fojt 		__archive_ppmd8_functions.Ppmd8_Free(&zip->ppmd8);
3110085658deSDaniel Fojt 
31116b384f39SPeter Avalos 	if (zip->zip_entries) {
31126b384f39SPeter Avalos 		zip_entry = zip->zip_entries;
31136b384f39SPeter Avalos 		while (zip_entry != NULL) {
31146b384f39SPeter Avalos 			next_zip_entry = zip_entry->next;
31156b384f39SPeter Avalos 			archive_string_free(&zip_entry->rsrcname);
31166b384f39SPeter Avalos 			free(zip_entry);
31176b384f39SPeter Avalos 			zip_entry = next_zip_entry;
31186b384f39SPeter Avalos 		}
31196b384f39SPeter Avalos 	}
31206b384f39SPeter Avalos 	free(zip->decrypted_buffer);
31216b384f39SPeter Avalos 	if (zip->cctx_valid)
31226b384f39SPeter Avalos 		archive_decrypto_aes_ctr_release(&zip->cctx);
31236b384f39SPeter Avalos 	if (zip->hctx_valid)
31246b384f39SPeter Avalos 		archive_hmac_sha1_cleanup(&zip->hctx);
31256b384f39SPeter Avalos 	free(zip->iv);
31266b384f39SPeter Avalos 	free(zip->erd);
31276b384f39SPeter Avalos 	free(zip->v_data);
31286b384f39SPeter Avalos 	archive_string_free(&zip->format_name);
31296b384f39SPeter Avalos 	free(zip);
31306b384f39SPeter Avalos 	(a->format->data) = NULL;
31316b384f39SPeter Avalos 	return (ARCHIVE_OK);
31326b384f39SPeter Avalos }
31336b384f39SPeter Avalos 
31346b384f39SPeter Avalos static int
archive_read_format_zip_has_encrypted_entries(struct archive_read * _a)31356b384f39SPeter Avalos archive_read_format_zip_has_encrypted_entries(struct archive_read *_a)
31366b384f39SPeter Avalos {
31376b384f39SPeter Avalos 	if (_a && _a->format) {
31386b384f39SPeter Avalos 		struct zip * zip = (struct zip *)_a->format->data;
31396b384f39SPeter Avalos 		if (zip) {
31406b384f39SPeter Avalos 			return zip->has_encrypted_entries;
31416b384f39SPeter Avalos 		}
31426b384f39SPeter Avalos 	}
31436b384f39SPeter Avalos 	return ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
31446b384f39SPeter Avalos }
31456b384f39SPeter Avalos 
31466b384f39SPeter Avalos static int
archive_read_format_zip_options(struct archive_read * a,const char * key,const char * val)31476b384f39SPeter Avalos archive_read_format_zip_options(struct archive_read *a,
31486b384f39SPeter Avalos     const char *key, const char *val)
31496b384f39SPeter Avalos {
31506b384f39SPeter Avalos 	struct zip *zip;
31516b384f39SPeter Avalos 	int ret = ARCHIVE_FAILED;
31526b384f39SPeter Avalos 
31536b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
31546b384f39SPeter Avalos 	if (strcmp(key, "compat-2x")  == 0) {
31556b384f39SPeter Avalos 		/* Handle filenames as libarchive 2.x */
31566b384f39SPeter Avalos 		zip->init_default_conversion = (val != NULL) ? 1 : 0;
31576b384f39SPeter Avalos 		return (ARCHIVE_OK);
31586b384f39SPeter Avalos 	} else if (strcmp(key, "hdrcharset")  == 0) {
31596b384f39SPeter Avalos 		if (val == NULL || val[0] == 0)
31606b384f39SPeter Avalos 			archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
31616b384f39SPeter Avalos 			    "zip: hdrcharset option needs a character-set name"
31626b384f39SPeter Avalos 			);
31636b384f39SPeter Avalos 		else {
31646b384f39SPeter Avalos 			zip->sconv = archive_string_conversion_from_charset(
31656b384f39SPeter Avalos 			    &a->archive, val, 0);
31666b384f39SPeter Avalos 			if (zip->sconv != NULL) {
31676b384f39SPeter Avalos 				if (strcmp(val, "UTF-8") == 0)
31686b384f39SPeter Avalos 					zip->sconv_utf8 = zip->sconv;
31696b384f39SPeter Avalos 				ret = ARCHIVE_OK;
31706b384f39SPeter Avalos 			} else
31716b384f39SPeter Avalos 				ret = ARCHIVE_FATAL;
31726b384f39SPeter Avalos 		}
31736b384f39SPeter Avalos 		return (ret);
31746b384f39SPeter Avalos 	} else if (strcmp(key, "ignorecrc32") == 0) {
31756b384f39SPeter Avalos 		/* Mostly useful for testing. */
31766b384f39SPeter Avalos 		if (val == NULL || val[0] == 0) {
31776b384f39SPeter Avalos 			zip->crc32func = real_crc32;
31786b384f39SPeter Avalos 			zip->ignore_crc32 = 0;
31796b384f39SPeter Avalos 		} else {
31806b384f39SPeter Avalos 			zip->crc32func = fake_crc32;
31816b384f39SPeter Avalos 			zip->ignore_crc32 = 1;
31826b384f39SPeter Avalos 		}
31836b384f39SPeter Avalos 		return (ARCHIVE_OK);
31846b384f39SPeter Avalos 	} else if (strcmp(key, "mac-ext") == 0) {
31856b384f39SPeter Avalos 		zip->process_mac_extensions = (val != NULL && val[0] != 0);
31866b384f39SPeter Avalos 		return (ARCHIVE_OK);
31876b384f39SPeter Avalos 	}
31886b384f39SPeter Avalos 
31896b384f39SPeter Avalos 	/* Note: The "warn" return is just to inform the options
31906b384f39SPeter Avalos 	 * supervisor that we didn't handle it.  It will generate
31916b384f39SPeter Avalos 	 * a suitable error if no one used this option. */
31926b384f39SPeter Avalos 	return (ARCHIVE_WARN);
31936b384f39SPeter Avalos }
31946b384f39SPeter Avalos 
31956b384f39SPeter Avalos int
archive_read_support_format_zip(struct archive * a)31966b384f39SPeter Avalos archive_read_support_format_zip(struct archive *a)
31976b384f39SPeter Avalos {
31986b384f39SPeter Avalos 	int r;
31996b384f39SPeter Avalos 	r = archive_read_support_format_zip_streamable(a);
32006b384f39SPeter Avalos 	if (r != ARCHIVE_OK)
32016b384f39SPeter Avalos 		return r;
32026b384f39SPeter Avalos 	return (archive_read_support_format_zip_seekable(a));
32036b384f39SPeter Avalos }
32046b384f39SPeter Avalos 
32056b384f39SPeter Avalos /* ------------------------------------------------------------------------ */
32066b384f39SPeter Avalos 
32076b384f39SPeter Avalos /*
32086b384f39SPeter Avalos  * Streaming-mode support
32096b384f39SPeter Avalos  */
32106b384f39SPeter Avalos 
32116b384f39SPeter Avalos 
32126b384f39SPeter Avalos static int
archive_read_support_format_zip_capabilities_streamable(struct archive_read * a)32136b384f39SPeter Avalos archive_read_support_format_zip_capabilities_streamable(struct archive_read * a)
32146b384f39SPeter Avalos {
32156b384f39SPeter Avalos 	(void)a; /* UNUSED */
32166b384f39SPeter Avalos 	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
32176b384f39SPeter Avalos 		ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
32186b384f39SPeter Avalos }
32196b384f39SPeter Avalos 
32206b384f39SPeter Avalos static int
archive_read_format_zip_streamable_bid(struct archive_read * a,int best_bid)32216b384f39SPeter Avalos archive_read_format_zip_streamable_bid(struct archive_read *a, int best_bid)
32226b384f39SPeter Avalos {
32236b384f39SPeter Avalos 	const char *p;
32246b384f39SPeter Avalos 
32256b384f39SPeter Avalos 	(void)best_bid; /* UNUSED */
32266b384f39SPeter Avalos 
32276b384f39SPeter Avalos 	if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
32286b384f39SPeter Avalos 		return (-1);
32296b384f39SPeter Avalos 
32306b384f39SPeter Avalos 	/*
32316b384f39SPeter Avalos 	 * Bid of 29 here comes from:
32326b384f39SPeter Avalos 	 *  + 16 bits for "PK",
32336b384f39SPeter Avalos 	 *  + next 16-bit field has 6 options so contributes
32346b384f39SPeter Avalos 	 *    about 16 - log_2(6) ~= 16 - 2.6 ~= 13 bits
32356b384f39SPeter Avalos 	 *
32366b384f39SPeter Avalos 	 * So we've effectively verified ~29 total bits of check data.
32376b384f39SPeter Avalos 	 */
32386b384f39SPeter Avalos 	if (p[0] == 'P' && p[1] == 'K') {
32396b384f39SPeter Avalos 		if ((p[2] == '\001' && p[3] == '\002')
32406b384f39SPeter Avalos 		    || (p[2] == '\003' && p[3] == '\004')
32416b384f39SPeter Avalos 		    || (p[2] == '\005' && p[3] == '\006')
32426b384f39SPeter Avalos 		    || (p[2] == '\006' && p[3] == '\006')
32436b384f39SPeter Avalos 		    || (p[2] == '\007' && p[3] == '\010')
32446b384f39SPeter Avalos 		    || (p[2] == '0' && p[3] == '0'))
32456b384f39SPeter Avalos 			return (29);
32466b384f39SPeter Avalos 	}
32476b384f39SPeter Avalos 
32486b384f39SPeter Avalos 	/* TODO: It's worth looking ahead a little bit for a valid
32496b384f39SPeter Avalos 	 * PK signature.  In particular, that would make it possible
32506b384f39SPeter Avalos 	 * to read some UUEncoded SFX files or SFX files coming from
32516b384f39SPeter Avalos 	 * a network socket. */
32526b384f39SPeter Avalos 
32536b384f39SPeter Avalos 	return (0);
32546b384f39SPeter Avalos }
32556b384f39SPeter Avalos 
32566b384f39SPeter Avalos static int
archive_read_format_zip_streamable_read_header(struct archive_read * a,struct archive_entry * entry)32576b384f39SPeter Avalos archive_read_format_zip_streamable_read_header(struct archive_read *a,
32586b384f39SPeter Avalos     struct archive_entry *entry)
32596b384f39SPeter Avalos {
32606b384f39SPeter Avalos 	struct zip *zip;
32616b384f39SPeter Avalos 
32626b384f39SPeter Avalos 	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
32636b384f39SPeter Avalos 	if (a->archive.archive_format_name == NULL)
32646b384f39SPeter Avalos 		a->archive.archive_format_name = "ZIP";
32656b384f39SPeter Avalos 
32666b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
32676b384f39SPeter Avalos 
32686b384f39SPeter Avalos 	/*
32696b384f39SPeter Avalos 	 * It should be sufficient to call archive_read_next_header() for
32706b384f39SPeter Avalos 	 * a reader to determine if an entry is encrypted or not. If the
32716b384f39SPeter Avalos 	 * encryption of an entry is only detectable when calling
32726b384f39SPeter Avalos 	 * archive_read_data(), so be it. We'll do the same check there
32736b384f39SPeter Avalos 	 * as well.
32746b384f39SPeter Avalos 	 */
32756b384f39SPeter Avalos 	if (zip->has_encrypted_entries ==
32766b384f39SPeter Avalos 			ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW)
32776b384f39SPeter Avalos 		zip->has_encrypted_entries = 0;
32786b384f39SPeter Avalos 
32796b384f39SPeter Avalos 	/* Make sure we have a zip_entry structure to use. */
32806b384f39SPeter Avalos 	if (zip->zip_entries == NULL) {
32816b384f39SPeter Avalos 		zip->zip_entries = malloc(sizeof(struct zip_entry));
32826b384f39SPeter Avalos 		if (zip->zip_entries == NULL) {
32836b384f39SPeter Avalos 			archive_set_error(&a->archive, ENOMEM,
32846b384f39SPeter Avalos 			    "Out  of memory");
32856b384f39SPeter Avalos 			return ARCHIVE_FATAL;
32866b384f39SPeter Avalos 		}
32876b384f39SPeter Avalos 	}
32886b384f39SPeter Avalos 	zip->entry = zip->zip_entries;
32896b384f39SPeter Avalos 	memset(zip->entry, 0, sizeof(struct zip_entry));
32906b384f39SPeter Avalos 
32916b384f39SPeter Avalos 	if (zip->cctx_valid)
32926b384f39SPeter Avalos 		archive_decrypto_aes_ctr_release(&zip->cctx);
32936b384f39SPeter Avalos 	if (zip->hctx_valid)
32946b384f39SPeter Avalos 		archive_hmac_sha1_cleanup(&zip->hctx);
32956b384f39SPeter Avalos 	zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0;
32966b384f39SPeter Avalos 	__archive_read_reset_passphrase(a);
32976b384f39SPeter Avalos 
32986b384f39SPeter Avalos 	/* Search ahead for the next local file header. */
32996b384f39SPeter Avalos 	__archive_read_consume(a, zip->unconsumed);
33006b384f39SPeter Avalos 	zip->unconsumed = 0;
33016b384f39SPeter Avalos 	for (;;) {
33026b384f39SPeter Avalos 		int64_t skipped = 0;
33036b384f39SPeter Avalos 		const char *p, *end;
33046b384f39SPeter Avalos 		ssize_t bytes;
33056b384f39SPeter Avalos 
33066b384f39SPeter Avalos 		p = __archive_read_ahead(a, 4, &bytes);
33076b384f39SPeter Avalos 		if (p == NULL)
33086b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
33096b384f39SPeter Avalos 		end = p + bytes;
33106b384f39SPeter Avalos 
33116b384f39SPeter Avalos 		while (p + 4 <= end) {
33126b384f39SPeter Avalos 			if (p[0] == 'P' && p[1] == 'K') {
33136b384f39SPeter Avalos 				if (p[2] == '\003' && p[3] == '\004') {
33146b384f39SPeter Avalos 					/* Regular file entry. */
33156b384f39SPeter Avalos 					__archive_read_consume(a, skipped);
33166b384f39SPeter Avalos 					return zip_read_local_file_header(a,
33176b384f39SPeter Avalos 					    entry, zip);
33186b384f39SPeter Avalos 				}
33196b384f39SPeter Avalos 
33206b384f39SPeter Avalos                               /*
33216b384f39SPeter Avalos                                * TODO: We cannot restore permissions
33226b384f39SPeter Avalos                                * based only on the local file headers.
33236b384f39SPeter Avalos                                * Consider scanning the central
33246b384f39SPeter Avalos                                * directory and returning additional
33256b384f39SPeter Avalos                                * entries for at least directories.
33266b384f39SPeter Avalos                                * This would allow us to properly set
33276b384f39SPeter Avalos                                * directory permissions.
33286b384f39SPeter Avalos 			       *
33296b384f39SPeter Avalos 			       * This won't help us fix symlinks
33306b384f39SPeter Avalos 			       * and may not help with regular file
33316b384f39SPeter Avalos 			       * permissions, either.  <sigh>
33326b384f39SPeter Avalos                                */
33336b384f39SPeter Avalos                               if (p[2] == '\001' && p[3] == '\002') {
33346b384f39SPeter Avalos                                       return (ARCHIVE_EOF);
33356b384f39SPeter Avalos                               }
33366b384f39SPeter Avalos 
33376b384f39SPeter Avalos                               /* End of central directory?  Must be an
33386b384f39SPeter Avalos                                * empty archive. */
33396b384f39SPeter Avalos                               if ((p[2] == '\005' && p[3] == '\006')
33406b384f39SPeter Avalos                                   || (p[2] == '\006' && p[3] == '\006'))
33416b384f39SPeter Avalos                                       return (ARCHIVE_EOF);
33426b384f39SPeter Avalos 			}
33436b384f39SPeter Avalos 			++p;
33446b384f39SPeter Avalos 			++skipped;
33456b384f39SPeter Avalos 		}
33466b384f39SPeter Avalos 		__archive_read_consume(a, skipped);
33476b384f39SPeter Avalos 	}
33486b384f39SPeter Avalos }
33496b384f39SPeter Avalos 
33506b384f39SPeter Avalos static int
archive_read_format_zip_read_data_skip_streamable(struct archive_read * a)33516b384f39SPeter Avalos archive_read_format_zip_read_data_skip_streamable(struct archive_read *a)
33526b384f39SPeter Avalos {
33536b384f39SPeter Avalos 	struct zip *zip;
33546b384f39SPeter Avalos 	int64_t bytes_skipped;
33556b384f39SPeter Avalos 
33566b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
33576b384f39SPeter Avalos 	bytes_skipped = __archive_read_consume(a, zip->unconsumed);
33586b384f39SPeter Avalos 	zip->unconsumed = 0;
33596b384f39SPeter Avalos 	if (bytes_skipped < 0)
33606b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
33616b384f39SPeter Avalos 
33626b384f39SPeter Avalos 	/* If we've already read to end of data, we're done. */
33636b384f39SPeter Avalos 	if (zip->end_of_entry)
33646b384f39SPeter Avalos 		return (ARCHIVE_OK);
33656b384f39SPeter Avalos 
33666b384f39SPeter Avalos 	/* So we know we're streaming... */
33676b384f39SPeter Avalos 	if (0 == (zip->entry->zip_flags & ZIP_LENGTH_AT_END)
33686b384f39SPeter Avalos 	    || zip->entry->compressed_size > 0) {
33696b384f39SPeter Avalos 		/* We know the compressed length, so we can just skip. */
33706b384f39SPeter Avalos 		bytes_skipped = __archive_read_consume(a,
33716b384f39SPeter Avalos 					zip->entry_bytes_remaining);
33726b384f39SPeter Avalos 		if (bytes_skipped < 0)
33736b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
33746b384f39SPeter Avalos 		return (ARCHIVE_OK);
33756b384f39SPeter Avalos 	}
33766b384f39SPeter Avalos 
33776b384f39SPeter Avalos 	if (zip->init_decryption) {
33786b384f39SPeter Avalos 		int r;
33796b384f39SPeter Avalos 
33806b384f39SPeter Avalos 		zip->has_encrypted_entries = 1;
33816b384f39SPeter Avalos 		if (zip->entry->zip_flags & ZIP_STRONG_ENCRYPTED)
33826b384f39SPeter Avalos 			r = read_decryption_header(a);
33836b384f39SPeter Avalos 		else if (zip->entry->compression == WINZIP_AES_ENCRYPTION)
33846b384f39SPeter Avalos 			r = init_WinZip_AES_decryption(a);
33856b384f39SPeter Avalos 		else
33866b384f39SPeter Avalos 			r = init_traditional_PKWARE_decryption(a);
33876b384f39SPeter Avalos 		if (r != ARCHIVE_OK)
33886b384f39SPeter Avalos 			return (r);
33896b384f39SPeter Avalos 		zip->init_decryption = 0;
33906b384f39SPeter Avalos 	}
33916b384f39SPeter Avalos 
33926b384f39SPeter Avalos 	/* We're streaming and we don't know the length. */
33936b384f39SPeter Avalos 	/* If the body is compressed and we know the format, we can
33946b384f39SPeter Avalos 	 * find an exact end-of-entry by decompressing it. */
33956b384f39SPeter Avalos 	switch (zip->entry->compression) {
33966b384f39SPeter Avalos #ifdef HAVE_ZLIB_H
33976b384f39SPeter Avalos 	case 8: /* Deflate compression. */
33986b384f39SPeter Avalos 		while (!zip->end_of_entry) {
33996b384f39SPeter Avalos 			int64_t offset = 0;
34006b384f39SPeter Avalos 			const void *buff = NULL;
34016b384f39SPeter Avalos 			size_t size = 0;
34026b384f39SPeter Avalos 			int r;
34036b384f39SPeter Avalos 			r =  zip_read_data_deflate(a, &buff, &size, &offset);
34046b384f39SPeter Avalos 			if (r != ARCHIVE_OK)
34056b384f39SPeter Avalos 				return (r);
34066b384f39SPeter Avalos 		}
34076b384f39SPeter Avalos 		return ARCHIVE_OK;
34086b384f39SPeter Avalos #endif
34096b384f39SPeter Avalos 	default: /* Uncompressed or unknown. */
34106b384f39SPeter Avalos 		/* Scan for a PK\007\010 signature. */
34116b384f39SPeter Avalos 		for (;;) {
34126b384f39SPeter Avalos 			const char *p, *buff;
34136b384f39SPeter Avalos 			ssize_t bytes_avail;
34146b384f39SPeter Avalos 			buff = __archive_read_ahead(a, 16, &bytes_avail);
34156b384f39SPeter Avalos 			if (bytes_avail < 16) {
34166b384f39SPeter Avalos 				archive_set_error(&a->archive,
34176b384f39SPeter Avalos 				    ARCHIVE_ERRNO_FILE_FORMAT,
34186b384f39SPeter Avalos 				    "Truncated ZIP file data");
34196b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
34206b384f39SPeter Avalos 			}
34216b384f39SPeter Avalos 			p = buff;
34226b384f39SPeter Avalos 			while (p <= buff + bytes_avail - 16) {
34236b384f39SPeter Avalos 				if (p[3] == 'P') { p += 3; }
34246b384f39SPeter Avalos 				else if (p[3] == 'K') { p += 2; }
34256b384f39SPeter Avalos 				else if (p[3] == '\007') { p += 1; }
34266b384f39SPeter Avalos 				else if (p[3] == '\010' && p[2] == '\007'
34276b384f39SPeter Avalos 				    && p[1] == 'K' && p[0] == 'P') {
34286b384f39SPeter Avalos 					if (zip->entry->flags & LA_USED_ZIP64)
34296b384f39SPeter Avalos 						__archive_read_consume(a,
34306b384f39SPeter Avalos 						    p - buff + 24);
34316b384f39SPeter Avalos 					else
34326b384f39SPeter Avalos 						__archive_read_consume(a,
34336b384f39SPeter Avalos 						    p - buff + 16);
34346b384f39SPeter Avalos 					return ARCHIVE_OK;
34356b384f39SPeter Avalos 				} else { p += 4; }
34366b384f39SPeter Avalos 			}
34376b384f39SPeter Avalos 			__archive_read_consume(a, p - buff);
34386b384f39SPeter Avalos 		}
34396b384f39SPeter Avalos 	}
34406b384f39SPeter Avalos }
34416b384f39SPeter Avalos 
34426b384f39SPeter Avalos int
archive_read_support_format_zip_streamable(struct archive * _a)34436b384f39SPeter Avalos archive_read_support_format_zip_streamable(struct archive *_a)
34446b384f39SPeter Avalos {
34456b384f39SPeter Avalos 	struct archive_read *a = (struct archive_read *)_a;
34466b384f39SPeter Avalos 	struct zip *zip;
34476b384f39SPeter Avalos 	int r;
34486b384f39SPeter Avalos 
34496b384f39SPeter Avalos 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
34506b384f39SPeter Avalos 	    ARCHIVE_STATE_NEW, "archive_read_support_format_zip");
34516b384f39SPeter Avalos 
34526b384f39SPeter Avalos 	zip = (struct zip *)calloc(1, sizeof(*zip));
34536b384f39SPeter Avalos 	if (zip == NULL) {
34546b384f39SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
34556b384f39SPeter Avalos 		    "Can't allocate zip data");
34566b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
34576b384f39SPeter Avalos 	}
34586b384f39SPeter Avalos 
34596b384f39SPeter Avalos 	/* Streamable reader doesn't support mac extensions. */
34606b384f39SPeter Avalos 	zip->process_mac_extensions = 0;
34616b384f39SPeter Avalos 
34626b384f39SPeter Avalos 	/*
34636b384f39SPeter Avalos 	 * Until enough data has been read, we cannot tell about
34646b384f39SPeter Avalos 	 * any encrypted entries yet.
34656b384f39SPeter Avalos 	 */
34666b384f39SPeter Avalos 	zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
34676b384f39SPeter Avalos 	zip->crc32func = real_crc32;
34686b384f39SPeter Avalos 
34696b384f39SPeter Avalos 	r = __archive_read_register_format(a,
34706b384f39SPeter Avalos 	    zip,
34716b384f39SPeter Avalos 	    "zip",
34726b384f39SPeter Avalos 	    archive_read_format_zip_streamable_bid,
34736b384f39SPeter Avalos 	    archive_read_format_zip_options,
34746b384f39SPeter Avalos 	    archive_read_format_zip_streamable_read_header,
34756b384f39SPeter Avalos 	    archive_read_format_zip_read_data,
34766b384f39SPeter Avalos 	    archive_read_format_zip_read_data_skip_streamable,
34776b384f39SPeter Avalos 	    NULL,
34786b384f39SPeter Avalos 	    archive_read_format_zip_cleanup,
34796b384f39SPeter Avalos 	    archive_read_support_format_zip_capabilities_streamable,
34806b384f39SPeter Avalos 	    archive_read_format_zip_has_encrypted_entries);
34816b384f39SPeter Avalos 
34826b384f39SPeter Avalos 	if (r != ARCHIVE_OK)
34836b384f39SPeter Avalos 		free(zip);
34846b384f39SPeter Avalos 	return (ARCHIVE_OK);
34856b384f39SPeter Avalos }
34866b384f39SPeter Avalos 
34876b384f39SPeter Avalos /* ------------------------------------------------------------------------ */
34886b384f39SPeter Avalos 
34896b384f39SPeter Avalos /*
34906b384f39SPeter Avalos  * Seeking-mode support
34916b384f39SPeter Avalos  */
34926b384f39SPeter Avalos 
34936b384f39SPeter Avalos static int
archive_read_support_format_zip_capabilities_seekable(struct archive_read * a)34946b384f39SPeter Avalos archive_read_support_format_zip_capabilities_seekable(struct archive_read * a)
34956b384f39SPeter Avalos {
34966b384f39SPeter Avalos 	(void)a; /* UNUSED */
34976b384f39SPeter Avalos 	return (ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_DATA |
34986b384f39SPeter Avalos 		ARCHIVE_READ_FORMAT_CAPS_ENCRYPT_METADATA);
34996b384f39SPeter Avalos }
35006b384f39SPeter Avalos 
35016b384f39SPeter Avalos /*
35026b384f39SPeter Avalos  * TODO: This is a performance sink because it forces the read core to
35036b384f39SPeter Avalos  * drop buffered data from the start of file, which will then have to
35046b384f39SPeter Avalos  * be re-read again if this bidder loses.
35056b384f39SPeter Avalos  *
35066b384f39SPeter Avalos  * We workaround this a little by passing in the best bid so far so
35076b384f39SPeter Avalos  * that later bidders can do nothing if they know they'll never
35086b384f39SPeter Avalos  * outbid.  But we can certainly do better...
35096b384f39SPeter Avalos  */
35106b384f39SPeter Avalos static int
read_eocd(struct zip * zip,const char * p,int64_t current_offset)35116b384f39SPeter Avalos read_eocd(struct zip *zip, const char *p, int64_t current_offset)
35126b384f39SPeter Avalos {
3513*50f8aa9cSAntonio Huete Jimenez 	uint16_t disk_num;
3514*50f8aa9cSAntonio Huete Jimenez 	uint32_t cd_size, cd_offset;
3515*50f8aa9cSAntonio Huete Jimenez 
3516*50f8aa9cSAntonio Huete Jimenez 	disk_num = archive_le16dec(p + 4);
3517*50f8aa9cSAntonio Huete Jimenez 	cd_size = archive_le32dec(p + 12);
3518*50f8aa9cSAntonio Huete Jimenez 	cd_offset = archive_le32dec(p + 16);
3519*50f8aa9cSAntonio Huete Jimenez 
35206b384f39SPeter Avalos 	/* Sanity-check the EOCD we've found. */
35216b384f39SPeter Avalos 
35226b384f39SPeter Avalos 	/* This must be the first volume. */
3523*50f8aa9cSAntonio Huete Jimenez 	if (disk_num != 0)
35246b384f39SPeter Avalos 		return 0;
35256b384f39SPeter Avalos 	/* Central directory must be on this volume. */
3526*50f8aa9cSAntonio Huete Jimenez 	if (disk_num != archive_le16dec(p + 6))
35276b384f39SPeter Avalos 		return 0;
35286b384f39SPeter Avalos 	/* All central directory entries must be on this volume. */
35296b384f39SPeter Avalos 	if (archive_le16dec(p + 10) != archive_le16dec(p + 8))
35306b384f39SPeter Avalos 		return 0;
35316b384f39SPeter Avalos 	/* Central directory can't extend beyond start of EOCD record. */
3532*50f8aa9cSAntonio Huete Jimenez 	if (cd_offset + cd_size > current_offset)
35336b384f39SPeter Avalos 		return 0;
35346b384f39SPeter Avalos 
35356b384f39SPeter Avalos 	/* Save the central directory location for later use. */
3536*50f8aa9cSAntonio Huete Jimenez 	zip->central_directory_offset = cd_offset;
3537*50f8aa9cSAntonio Huete Jimenez 	zip->central_directory_offset_adjusted = current_offset - cd_size;
35386b384f39SPeter Avalos 
35396b384f39SPeter Avalos 	/* This is just a tiny bit higher than the maximum
35406b384f39SPeter Avalos 	   returned by the streaming Zip bidder.  This ensures
35416b384f39SPeter Avalos 	   that the more accurate seeking Zip parser wins
35426b384f39SPeter Avalos 	   whenever seek is available. */
35436b384f39SPeter Avalos 	return 32;
35446b384f39SPeter Avalos }
35456b384f39SPeter Avalos 
35466b384f39SPeter Avalos /*
35476b384f39SPeter Avalos  * Examine Zip64 EOCD locator:  If it's valid, store the information
35486b384f39SPeter Avalos  * from it.
35496b384f39SPeter Avalos  */
3550e95abc47Szrj static int
read_zip64_eocd(struct archive_read * a,struct zip * zip,const char * p)35516b384f39SPeter Avalos read_zip64_eocd(struct archive_read *a, struct zip *zip, const char *p)
35526b384f39SPeter Avalos {
35536b384f39SPeter Avalos 	int64_t eocd64_offset;
35546b384f39SPeter Avalos 	int64_t eocd64_size;
35556b384f39SPeter Avalos 
35566b384f39SPeter Avalos 	/* Sanity-check the locator record. */
35576b384f39SPeter Avalos 
35586b384f39SPeter Avalos 	/* Central dir must be on first volume. */
35596b384f39SPeter Avalos 	if (archive_le32dec(p + 4) != 0)
3560e95abc47Szrj 		return 0;
35616b384f39SPeter Avalos 	/* Must be only a single volume. */
35626b384f39SPeter Avalos 	if (archive_le32dec(p + 16) != 1)
3563e95abc47Szrj 		return 0;
35646b384f39SPeter Avalos 
35656b384f39SPeter Avalos 	/* Find the Zip64 EOCD record. */
35666b384f39SPeter Avalos 	eocd64_offset = archive_le64dec(p + 8);
35676b384f39SPeter Avalos 	if (__archive_read_seek(a, eocd64_offset, SEEK_SET) < 0)
3568e95abc47Szrj 		return 0;
35696b384f39SPeter Avalos 	if ((p = __archive_read_ahead(a, 56, NULL)) == NULL)
3570e95abc47Szrj 		return 0;
35716b384f39SPeter Avalos 	/* Make sure we can read all of it. */
35726b384f39SPeter Avalos 	eocd64_size = archive_le64dec(p + 4) + 12;
35736b384f39SPeter Avalos 	if (eocd64_size < 56 || eocd64_size > 16384)
3574e95abc47Szrj 		return 0;
35756b384f39SPeter Avalos 	if ((p = __archive_read_ahead(a, (size_t)eocd64_size, NULL)) == NULL)
3576e95abc47Szrj 		return 0;
35776b384f39SPeter Avalos 
35786b384f39SPeter Avalos 	/* Sanity-check the EOCD64 */
35796b384f39SPeter Avalos 	if (archive_le32dec(p + 16) != 0) /* Must be disk #0 */
3580e95abc47Szrj 		return 0;
35816b384f39SPeter Avalos 	if (archive_le32dec(p + 20) != 0) /* CD must be on disk #0 */
3582e95abc47Szrj 		return 0;
35836b384f39SPeter Avalos 	/* CD can't be split. */
35846b384f39SPeter Avalos 	if (archive_le64dec(p + 24) != archive_le64dec(p + 32))
3585e95abc47Szrj 		return 0;
35866b384f39SPeter Avalos 
35876b384f39SPeter Avalos 	/* Save the central directory offset for later use. */
35886b384f39SPeter Avalos 	zip->central_directory_offset = archive_le64dec(p + 48);
3589*50f8aa9cSAntonio Huete Jimenez 	/* TODO: Needs scanning backwards to find the eocd64 instead of assuming */
3590*50f8aa9cSAntonio Huete Jimenez 	zip->central_directory_offset_adjusted = zip->central_directory_offset;
3591e95abc47Szrj 
3592e95abc47Szrj 	return 32;
35936b384f39SPeter Avalos }
35946b384f39SPeter Avalos 
35956b384f39SPeter Avalos static int
archive_read_format_zip_seekable_bid(struct archive_read * a,int best_bid)35966b384f39SPeter Avalos archive_read_format_zip_seekable_bid(struct archive_read *a, int best_bid)
35976b384f39SPeter Avalos {
35986b384f39SPeter Avalos 	struct zip *zip = (struct zip *)a->format->data;
35996b384f39SPeter Avalos 	int64_t file_size, current_offset;
36006b384f39SPeter Avalos 	const char *p;
36016b384f39SPeter Avalos 	int i, tail;
36026b384f39SPeter Avalos 
36036b384f39SPeter Avalos 	/* If someone has already bid more than 32, then avoid
36046b384f39SPeter Avalos 	   trashing the look-ahead buffers with a seek. */
36056b384f39SPeter Avalos 	if (best_bid > 32)
36066b384f39SPeter Avalos 		return (-1);
36076b384f39SPeter Avalos 
36086b384f39SPeter Avalos 	file_size = __archive_read_seek(a, 0, SEEK_END);
36096b384f39SPeter Avalos 	if (file_size <= 0)
36106b384f39SPeter Avalos 		return 0;
36116b384f39SPeter Avalos 
36126b384f39SPeter Avalos 	/* Search last 16k of file for end-of-central-directory
36136b384f39SPeter Avalos 	 * record (which starts with PK\005\006) */
36146b384f39SPeter Avalos 	tail = (int)zipmin(1024 * 16, file_size);
36156b384f39SPeter Avalos 	current_offset = __archive_read_seek(a, -tail, SEEK_END);
36166b384f39SPeter Avalos 	if (current_offset < 0)
36176b384f39SPeter Avalos 		return 0;
36186b384f39SPeter Avalos 	if ((p = __archive_read_ahead(a, (size_t)tail, NULL)) == NULL)
36196b384f39SPeter Avalos 		return 0;
36206b384f39SPeter Avalos 	/* Boyer-Moore search backwards from the end, since we want
36216b384f39SPeter Avalos 	 * to match the last EOCD in the file (there can be more than
36226b384f39SPeter Avalos 	 * one if there is an uncompressed Zip archive as a member
36236b384f39SPeter Avalos 	 * within this Zip archive). */
36246b384f39SPeter Avalos 	for (i = tail - 22; i > 0;) {
36256b384f39SPeter Avalos 		switch (p[i]) {
36266b384f39SPeter Avalos 		case 'P':
36276b384f39SPeter Avalos 			if (memcmp(p + i, "PK\005\006", 4) == 0) {
36286b384f39SPeter Avalos 				int ret = read_eocd(zip, p + i,
36296b384f39SPeter Avalos 				    current_offset + i);
36306b384f39SPeter Avalos 				/* Zip64 EOCD locator precedes
36316b384f39SPeter Avalos 				 * regular EOCD if present. */
3632e95abc47Szrj 				if (i >= 20 && memcmp(p + i - 20, "PK\006\007", 4) == 0) {
3633e95abc47Szrj 					int ret_zip64 = read_zip64_eocd(a, zip, p + i - 20);
3634e95abc47Szrj 					if (ret_zip64 > ret)
3635e95abc47Szrj 						ret = ret_zip64;
36366b384f39SPeter Avalos 				}
36376b384f39SPeter Avalos 				return (ret);
36386b384f39SPeter Avalos 			}
36396b384f39SPeter Avalos 			i -= 4;
36406b384f39SPeter Avalos 			break;
36416b384f39SPeter Avalos 		case 'K': i -= 1; break;
36426b384f39SPeter Avalos 		case 005: i -= 2; break;
36436b384f39SPeter Avalos 		case 006: i -= 3; break;
36446b384f39SPeter Avalos 		default: i -= 4; break;
36456b384f39SPeter Avalos 		}
36466b384f39SPeter Avalos 	}
36476b384f39SPeter Avalos 	return 0;
36486b384f39SPeter Avalos }
36496b384f39SPeter Avalos 
36506b384f39SPeter Avalos /* The red-black trees are only used in seeking mode to manage
36516b384f39SPeter Avalos  * the in-memory copy of the central directory. */
36526b384f39SPeter Avalos 
36536b384f39SPeter Avalos static int
cmp_node(const struct archive_rb_node * n1,const struct archive_rb_node * n2)36546b384f39SPeter Avalos cmp_node(const struct archive_rb_node *n1, const struct archive_rb_node *n2)
36556b384f39SPeter Avalos {
36566b384f39SPeter Avalos 	const struct zip_entry *e1 = (const struct zip_entry *)n1;
36576b384f39SPeter Avalos 	const struct zip_entry *e2 = (const struct zip_entry *)n2;
36586b384f39SPeter Avalos 
36596b384f39SPeter Avalos 	if (e1->local_header_offset > e2->local_header_offset)
36606b384f39SPeter Avalos 		return -1;
36616b384f39SPeter Avalos 	if (e1->local_header_offset < e2->local_header_offset)
36626b384f39SPeter Avalos 		return 1;
36636b384f39SPeter Avalos 	return 0;
36646b384f39SPeter Avalos }
36656b384f39SPeter Avalos 
36666b384f39SPeter Avalos static int
cmp_key(const struct archive_rb_node * n,const void * key)36676b384f39SPeter Avalos cmp_key(const struct archive_rb_node *n, const void *key)
36686b384f39SPeter Avalos {
36696b384f39SPeter Avalos 	/* This function won't be called */
36706b384f39SPeter Avalos 	(void)n; /* UNUSED */
36716b384f39SPeter Avalos 	(void)key; /* UNUSED */
36726b384f39SPeter Avalos 	return 1;
36736b384f39SPeter Avalos }
36746b384f39SPeter Avalos 
36756b384f39SPeter Avalos static const struct archive_rb_tree_ops rb_ops = {
36766b384f39SPeter Avalos 	&cmp_node, &cmp_key
36776b384f39SPeter Avalos };
36786b384f39SPeter Avalos 
36796b384f39SPeter Avalos static int
rsrc_cmp_node(const struct archive_rb_node * n1,const struct archive_rb_node * n2)36806b384f39SPeter Avalos rsrc_cmp_node(const struct archive_rb_node *n1,
36816b384f39SPeter Avalos     const struct archive_rb_node *n2)
36826b384f39SPeter Avalos {
36836b384f39SPeter Avalos 	const struct zip_entry *e1 = (const struct zip_entry *)n1;
36846b384f39SPeter Avalos 	const struct zip_entry *e2 = (const struct zip_entry *)n2;
36856b384f39SPeter Avalos 
36866b384f39SPeter Avalos 	return (strcmp(e2->rsrcname.s, e1->rsrcname.s));
36876b384f39SPeter Avalos }
36886b384f39SPeter Avalos 
36896b384f39SPeter Avalos static int
rsrc_cmp_key(const struct archive_rb_node * n,const void * key)36906b384f39SPeter Avalos rsrc_cmp_key(const struct archive_rb_node *n, const void *key)
36916b384f39SPeter Avalos {
36926b384f39SPeter Avalos 	const struct zip_entry *e = (const struct zip_entry *)n;
36936b384f39SPeter Avalos 	return (strcmp((const char *)key, e->rsrcname.s));
36946b384f39SPeter Avalos }
36956b384f39SPeter Avalos 
36966b384f39SPeter Avalos static const struct archive_rb_tree_ops rb_rsrc_ops = {
36976b384f39SPeter Avalos 	&rsrc_cmp_node, &rsrc_cmp_key
36986b384f39SPeter Avalos };
36996b384f39SPeter Avalos 
37006b384f39SPeter Avalos static const char *
rsrc_basename(const char * name,size_t name_length)37016b384f39SPeter Avalos rsrc_basename(const char *name, size_t name_length)
37026b384f39SPeter Avalos {
37036b384f39SPeter Avalos 	const char *s, *r;
37046b384f39SPeter Avalos 
37056b384f39SPeter Avalos 	r = s = name;
37066b384f39SPeter Avalos 	for (;;) {
37076b384f39SPeter Avalos 		s = memchr(s, '/', name_length - (s - name));
37086b384f39SPeter Avalos 		if (s == NULL)
37096b384f39SPeter Avalos 			break;
37106b384f39SPeter Avalos 		r = ++s;
37116b384f39SPeter Avalos 	}
37126b384f39SPeter Avalos 	return (r);
37136b384f39SPeter Avalos }
37146b384f39SPeter Avalos 
37156b384f39SPeter Avalos static void
expose_parent_dirs(struct zip * zip,const char * name,size_t name_length)37166b384f39SPeter Avalos expose_parent_dirs(struct zip *zip, const char *name, size_t name_length)
37176b384f39SPeter Avalos {
37186b384f39SPeter Avalos 	struct archive_string str;
37196b384f39SPeter Avalos 	struct zip_entry *dir;
37206b384f39SPeter Avalos 	char *s;
37216b384f39SPeter Avalos 
37226b384f39SPeter Avalos 	archive_string_init(&str);
37236b384f39SPeter Avalos 	archive_strncpy(&str, name, name_length);
37246b384f39SPeter Avalos 	for (;;) {
37256b384f39SPeter Avalos 		s = strrchr(str.s, '/');
37266b384f39SPeter Avalos 		if (s == NULL)
37276b384f39SPeter Avalos 			break;
37286b384f39SPeter Avalos 		*s = '\0';
37296b384f39SPeter Avalos 		/* Transfer the parent directory from zip->tree_rsrc RB
37306b384f39SPeter Avalos 		 * tree to zip->tree RB tree to expose. */
37316b384f39SPeter Avalos 		dir = (struct zip_entry *)
37326b384f39SPeter Avalos 		    __archive_rb_tree_find_node(&zip->tree_rsrc, str.s);
37336b384f39SPeter Avalos 		if (dir == NULL)
37346b384f39SPeter Avalos 			break;
37356b384f39SPeter Avalos 		__archive_rb_tree_remove_node(&zip->tree_rsrc, &dir->node);
37366b384f39SPeter Avalos 		archive_string_free(&dir->rsrcname);
37376b384f39SPeter Avalos 		__archive_rb_tree_insert_node(&zip->tree, &dir->node);
37386b384f39SPeter Avalos 	}
37396b384f39SPeter Avalos 	archive_string_free(&str);
37406b384f39SPeter Avalos }
37416b384f39SPeter Avalos 
37426b384f39SPeter Avalos static int
slurp_central_directory(struct archive_read * a,struct archive_entry * entry,struct zip * zip)3743085658deSDaniel Fojt slurp_central_directory(struct archive_read *a, struct archive_entry* entry,
3744085658deSDaniel Fojt     struct zip *zip)
37456b384f39SPeter Avalos {
37466b384f39SPeter Avalos 	ssize_t i;
37476b384f39SPeter Avalos 	unsigned found;
37486b384f39SPeter Avalos 	int64_t correction;
37496b384f39SPeter Avalos 	ssize_t bytes_avail;
37506b384f39SPeter Avalos 	const char *p;
37516b384f39SPeter Avalos 
37526b384f39SPeter Avalos 	/*
37536b384f39SPeter Avalos 	 * Find the start of the central directory.  The end-of-CD
37546b384f39SPeter Avalos 	 * record has our starting point, but there are lots of
37556b384f39SPeter Avalos 	 * Zip archives which have had other data prepended to the
37566b384f39SPeter Avalos 	 * file, which makes the recorded offsets all too small.
37576b384f39SPeter Avalos 	 * So we search forward from the specified offset until we
37586b384f39SPeter Avalos 	 * find the real start of the central directory.  Then we
37596b384f39SPeter Avalos 	 * know the correction we need to apply to account for leading
37606b384f39SPeter Avalos 	 * padding.
37616b384f39SPeter Avalos 	 */
3762*50f8aa9cSAntonio Huete Jimenez 	if (__archive_read_seek(a, zip->central_directory_offset_adjusted, SEEK_SET)
3763*50f8aa9cSAntonio Huete Jimenez 		< 0)
37646b384f39SPeter Avalos 		return ARCHIVE_FATAL;
37656b384f39SPeter Avalos 
37666b384f39SPeter Avalos 	found = 0;
37676b384f39SPeter Avalos 	while (!found) {
37686b384f39SPeter Avalos 		if ((p = __archive_read_ahead(a, 20, &bytes_avail)) == NULL)
37696b384f39SPeter Avalos 			return ARCHIVE_FATAL;
37706b384f39SPeter Avalos 		for (found = 0, i = 0; !found && i < bytes_avail - 4;) {
37716b384f39SPeter Avalos 			switch (p[i + 3]) {
37726b384f39SPeter Avalos 			case 'P': i += 3; break;
37736b384f39SPeter Avalos 			case 'K': i += 2; break;
37746b384f39SPeter Avalos 			case 001: i += 1; break;
37756b384f39SPeter Avalos 			case 002:
37766b384f39SPeter Avalos 				if (memcmp(p + i, "PK\001\002", 4) == 0) {
37776b384f39SPeter Avalos 					p += i;
37786b384f39SPeter Avalos 					found = 1;
37796b384f39SPeter Avalos 				} else
37806b384f39SPeter Avalos 					i += 4;
37816b384f39SPeter Avalos 				break;
37826b384f39SPeter Avalos 			case 005: i += 1; break;
37836b384f39SPeter Avalos 			case 006:
37846b384f39SPeter Avalos 				if (memcmp(p + i, "PK\005\006", 4) == 0) {
37856b384f39SPeter Avalos 					p += i;
37866b384f39SPeter Avalos 					found = 1;
37876b384f39SPeter Avalos 				} else if (memcmp(p + i, "PK\006\006", 4) == 0) {
37886b384f39SPeter Avalos 					p += i;
37896b384f39SPeter Avalos 					found = 1;
37906b384f39SPeter Avalos 				} else
37916b384f39SPeter Avalos 					i += 1;
37926b384f39SPeter Avalos 				break;
37936b384f39SPeter Avalos 			default: i += 4; break;
37946b384f39SPeter Avalos 			}
37956b384f39SPeter Avalos 		}
37966b384f39SPeter Avalos 		__archive_read_consume(a, i);
37976b384f39SPeter Avalos 	}
37986b384f39SPeter Avalos 	correction = archive_filter_bytes(&a->archive, 0)
37996b384f39SPeter Avalos 			- zip->central_directory_offset;
38006b384f39SPeter Avalos 
38016b384f39SPeter Avalos 	__archive_rb_tree_init(&zip->tree, &rb_ops);
38026b384f39SPeter Avalos 	__archive_rb_tree_init(&zip->tree_rsrc, &rb_rsrc_ops);
38036b384f39SPeter Avalos 
38046b384f39SPeter Avalos 	zip->central_directory_entries_total = 0;
38056b384f39SPeter Avalos 	while (1) {
38066b384f39SPeter Avalos 		struct zip_entry *zip_entry;
38076b384f39SPeter Avalos 		size_t filename_length, extra_length, comment_length;
38086b384f39SPeter Avalos 		uint32_t external_attributes;
38096b384f39SPeter Avalos 		const char *name, *r;
38106b384f39SPeter Avalos 
38116b384f39SPeter Avalos 		if ((p = __archive_read_ahead(a, 4, NULL)) == NULL)
38126b384f39SPeter Avalos 			return ARCHIVE_FATAL;
38136b384f39SPeter Avalos 		if (memcmp(p, "PK\006\006", 4) == 0
38146b384f39SPeter Avalos 		    || memcmp(p, "PK\005\006", 4) == 0) {
38156b384f39SPeter Avalos 			break;
38166b384f39SPeter Avalos 		} else if (memcmp(p, "PK\001\002", 4) != 0) {
38176b384f39SPeter Avalos 			archive_set_error(&a->archive,
38186b384f39SPeter Avalos 			    -1, "Invalid central directory signature");
38196b384f39SPeter Avalos 			return ARCHIVE_FATAL;
38206b384f39SPeter Avalos 		}
38216b384f39SPeter Avalos 		if ((p = __archive_read_ahead(a, 46, NULL)) == NULL)
38226b384f39SPeter Avalos 			return ARCHIVE_FATAL;
38236b384f39SPeter Avalos 
38246b384f39SPeter Avalos 		zip_entry = calloc(1, sizeof(struct zip_entry));
3825085658deSDaniel Fojt 		if (zip_entry == NULL) {
3826085658deSDaniel Fojt 			archive_set_error(&a->archive, ENOMEM,
3827085658deSDaniel Fojt 				"Can't allocate zip entry");
3828085658deSDaniel Fojt 			return ARCHIVE_FATAL;
3829085658deSDaniel Fojt 		}
38306b384f39SPeter Avalos 		zip_entry->next = zip->zip_entries;
38316b384f39SPeter Avalos 		zip_entry->flags |= LA_FROM_CENTRAL_DIRECTORY;
38326b384f39SPeter Avalos 		zip->zip_entries = zip_entry;
38336b384f39SPeter Avalos 		zip->central_directory_entries_total++;
38346b384f39SPeter Avalos 
38356b384f39SPeter Avalos 		/* version = p[4]; */
38366b384f39SPeter Avalos 		zip_entry->system = p[5];
38376b384f39SPeter Avalos 		/* version_required = archive_le16dec(p + 6); */
38386b384f39SPeter Avalos 		zip_entry->zip_flags = archive_le16dec(p + 8);
38396b384f39SPeter Avalos 		if (zip_entry->zip_flags
38406b384f39SPeter Avalos 		      & (ZIP_ENCRYPTED | ZIP_STRONG_ENCRYPTED)){
38416b384f39SPeter Avalos 			zip->has_encrypted_entries = 1;
38426b384f39SPeter Avalos 		}
38436b384f39SPeter Avalos 		zip_entry->compression = (char)archive_le16dec(p + 10);
38446b384f39SPeter Avalos 		zip_entry->mtime = zip_time(p + 12);
38456b384f39SPeter Avalos 		zip_entry->crc32 = archive_le32dec(p + 16);
38466b384f39SPeter Avalos 		if (zip_entry->zip_flags & ZIP_LENGTH_AT_END)
38476b384f39SPeter Avalos 			zip_entry->decdat = p[13];
38486b384f39SPeter Avalos 		else
38496b384f39SPeter Avalos 			zip_entry->decdat = p[19];
38506b384f39SPeter Avalos 		zip_entry->compressed_size = archive_le32dec(p + 20);
38516b384f39SPeter Avalos 		zip_entry->uncompressed_size = archive_le32dec(p + 24);
38526b384f39SPeter Avalos 		filename_length = archive_le16dec(p + 28);
38536b384f39SPeter Avalos 		extra_length = archive_le16dec(p + 30);
38546b384f39SPeter Avalos 		comment_length = archive_le16dec(p + 32);
3855085658deSDaniel Fojt 		/* disk_start = archive_le16dec(p + 34);
3856085658deSDaniel Fojt 		 *   Better be zero.
3857085658deSDaniel Fojt 		 * internal_attributes = archive_le16dec(p + 36);
3858085658deSDaniel Fojt 		 *   text bit */
38596b384f39SPeter Avalos 		external_attributes = archive_le32dec(p + 38);
38606b384f39SPeter Avalos 		zip_entry->local_header_offset =
38616b384f39SPeter Avalos 		    archive_le32dec(p + 42) + correction;
38626b384f39SPeter Avalos 
38636b384f39SPeter Avalos 		/* If we can't guess the mode, leave it zero here;
38646b384f39SPeter Avalos 		   when we read the local file header we might get
38656b384f39SPeter Avalos 		   more information. */
38666b384f39SPeter Avalos 		if (zip_entry->system == 3) {
38676b384f39SPeter Avalos 			zip_entry->mode = external_attributes >> 16;
38686b384f39SPeter Avalos 		} else if (zip_entry->system == 0) {
38696b384f39SPeter Avalos 			// Interpret MSDOS directory bit
38706b384f39SPeter Avalos 			if (0x10 == (external_attributes & 0x10)) {
38716b384f39SPeter Avalos 				zip_entry->mode = AE_IFDIR | 0775;
38726b384f39SPeter Avalos 			} else {
38736b384f39SPeter Avalos 				zip_entry->mode = AE_IFREG | 0664;
38746b384f39SPeter Avalos 			}
38756b384f39SPeter Avalos 			if (0x01 == (external_attributes & 0x01)) {
38766b384f39SPeter Avalos 				// Read-only bit; strip write permissions
38776b384f39SPeter Avalos 				zip_entry->mode &= 0555;
38786b384f39SPeter Avalos 			}
38796b384f39SPeter Avalos 		} else {
38806b384f39SPeter Avalos 			zip_entry->mode = 0;
38816b384f39SPeter Avalos 		}
38826b384f39SPeter Avalos 
38836b384f39SPeter Avalos 		/* We're done with the regular data; get the filename and
38846b384f39SPeter Avalos 		 * extra data. */
38856b384f39SPeter Avalos 		__archive_read_consume(a, 46);
38866b384f39SPeter Avalos 		p = __archive_read_ahead(a, filename_length + extra_length,
38876b384f39SPeter Avalos 			NULL);
38886b384f39SPeter Avalos 		if (p == NULL) {
38896b384f39SPeter Avalos 			archive_set_error(&a->archive,
38906b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
38916b384f39SPeter Avalos 			    "Truncated ZIP file header");
38926b384f39SPeter Avalos 			return ARCHIVE_FATAL;
38936b384f39SPeter Avalos 		}
3894085658deSDaniel Fojt 		if (ARCHIVE_OK != process_extra(a, entry, p + filename_length,
3895085658deSDaniel Fojt 		    extra_length, zip_entry)) {
3896e95abc47Szrj 			return ARCHIVE_FATAL;
3897e95abc47Szrj 		}
38986b384f39SPeter Avalos 
38996b384f39SPeter Avalos 		/*
39006b384f39SPeter Avalos 		 * Mac resource fork files are stored under the
39016b384f39SPeter Avalos 		 * "__MACOSX/" directory, so we should check if
39026b384f39SPeter Avalos 		 * it is.
39036b384f39SPeter Avalos 		 */
39046b384f39SPeter Avalos 		if (!zip->process_mac_extensions) {
39056b384f39SPeter Avalos 			/* Treat every entry as a regular entry. */
39066b384f39SPeter Avalos 			__archive_rb_tree_insert_node(&zip->tree,
39076b384f39SPeter Avalos 			    &zip_entry->node);
39086b384f39SPeter Avalos 		} else {
39096b384f39SPeter Avalos 			name = p;
39106b384f39SPeter Avalos 			r = rsrc_basename(name, filename_length);
39116b384f39SPeter Avalos 			if (filename_length >= 9 &&
39126b384f39SPeter Avalos 			    strncmp("__MACOSX/", name, 9) == 0) {
39136b384f39SPeter Avalos 				/* If this file is not a resource fork nor
39146b384f39SPeter Avalos 				 * a directory. We should treat it as a non
39156b384f39SPeter Avalos 				 * resource fork file to expose it. */
39166b384f39SPeter Avalos 				if (name[filename_length-1] != '/' &&
3917085658deSDaniel Fojt 				    (r - name < 3 || r[0] != '.' ||
3918085658deSDaniel Fojt 				     r[1] != '_')) {
39196b384f39SPeter Avalos 					__archive_rb_tree_insert_node(
39206b384f39SPeter Avalos 					    &zip->tree, &zip_entry->node);
39216b384f39SPeter Avalos 					/* Expose its parent directories. */
39226b384f39SPeter Avalos 					expose_parent_dirs(zip, name,
39236b384f39SPeter Avalos 					    filename_length);
39246b384f39SPeter Avalos 				} else {
39256b384f39SPeter Avalos 					/* This file is a resource fork file or
39266b384f39SPeter Avalos 					 * a directory. */
39276b384f39SPeter Avalos 					archive_strncpy(&(zip_entry->rsrcname),
39286b384f39SPeter Avalos 					     name, filename_length);
39296b384f39SPeter Avalos 					__archive_rb_tree_insert_node(
39306b384f39SPeter Avalos 					    &zip->tree_rsrc, &zip_entry->node);
39316b384f39SPeter Avalos 				}
39326b384f39SPeter Avalos 			} else {
39336b384f39SPeter Avalos 				/* Generate resource fork name to find its
39346b384f39SPeter Avalos 				 * resource file at zip->tree_rsrc. */
39356b384f39SPeter Avalos 				archive_strcpy(&(zip_entry->rsrcname),
39366b384f39SPeter Avalos 				    "__MACOSX/");
39376b384f39SPeter Avalos 				archive_strncat(&(zip_entry->rsrcname),
39386b384f39SPeter Avalos 				    name, r - name);
39396b384f39SPeter Avalos 				archive_strcat(&(zip_entry->rsrcname), "._");
39406b384f39SPeter Avalos 				archive_strncat(&(zip_entry->rsrcname),
39416b384f39SPeter Avalos 				    name + (r - name),
39426b384f39SPeter Avalos 				    filename_length - (r - name));
39436b384f39SPeter Avalos 				/* Register an entry to RB tree to sort it by
39446b384f39SPeter Avalos 				 * file offset. */
39456b384f39SPeter Avalos 				__archive_rb_tree_insert_node(&zip->tree,
39466b384f39SPeter Avalos 				    &zip_entry->node);
39476b384f39SPeter Avalos 			}
39486b384f39SPeter Avalos 		}
39496b384f39SPeter Avalos 
39506b384f39SPeter Avalos 		/* Skip the comment too ... */
39516b384f39SPeter Avalos 		__archive_read_consume(a,
39526b384f39SPeter Avalos 		    filename_length + extra_length + comment_length);
39536b384f39SPeter Avalos 	}
39546b384f39SPeter Avalos 
39556b384f39SPeter Avalos 	return ARCHIVE_OK;
39566b384f39SPeter Avalos }
39576b384f39SPeter Avalos 
39586b384f39SPeter Avalos static ssize_t
zip_get_local_file_header_size(struct archive_read * a,size_t extra)39596b384f39SPeter Avalos zip_get_local_file_header_size(struct archive_read *a, size_t extra)
39606b384f39SPeter Avalos {
39616b384f39SPeter Avalos 	const char *p;
39626b384f39SPeter Avalos 	ssize_t filename_length, extra_length;
39636b384f39SPeter Avalos 
39646b384f39SPeter Avalos 	if ((p = __archive_read_ahead(a, extra + 30, NULL)) == NULL) {
39656b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
39666b384f39SPeter Avalos 		    "Truncated ZIP file header");
39676b384f39SPeter Avalos 		return (ARCHIVE_WARN);
39686b384f39SPeter Avalos 	}
39696b384f39SPeter Avalos 	p += extra;
39706b384f39SPeter Avalos 
39716b384f39SPeter Avalos 	if (memcmp(p, "PK\003\004", 4) != 0) {
39726b384f39SPeter Avalos 		archive_set_error(&a->archive, -1, "Damaged Zip archive");
39736b384f39SPeter Avalos 		return ARCHIVE_WARN;
39746b384f39SPeter Avalos 	}
39756b384f39SPeter Avalos 	filename_length = archive_le16dec(p + 26);
39766b384f39SPeter Avalos 	extra_length = archive_le16dec(p + 28);
39776b384f39SPeter Avalos 
39786b384f39SPeter Avalos 	return (30 + filename_length + extra_length);
39796b384f39SPeter Avalos }
39806b384f39SPeter Avalos 
39816b384f39SPeter Avalos static int
zip_read_mac_metadata(struct archive_read * a,struct archive_entry * entry,struct zip_entry * rsrc)39826b384f39SPeter Avalos zip_read_mac_metadata(struct archive_read *a, struct archive_entry *entry,
39836b384f39SPeter Avalos     struct zip_entry *rsrc)
39846b384f39SPeter Avalos {
39856b384f39SPeter Avalos 	struct zip *zip = (struct zip *)a->format->data;
39866b384f39SPeter Avalos 	unsigned char *metadata, *mp;
39876b384f39SPeter Avalos 	int64_t offset = archive_filter_bytes(&a->archive, 0);
39886b384f39SPeter Avalos 	size_t remaining_bytes, metadata_bytes;
39896b384f39SPeter Avalos 	ssize_t hsize;
39906b384f39SPeter Avalos 	int ret = ARCHIVE_OK, eof;
39916b384f39SPeter Avalos 
39926b384f39SPeter Avalos 	switch(rsrc->compression) {
39936b384f39SPeter Avalos 	case 0:  /* No compression. */
39946b384f39SPeter Avalos 		if (rsrc->uncompressed_size != rsrc->compressed_size) {
3995085658deSDaniel Fojt 			archive_set_error(&a->archive,
3996085658deSDaniel Fojt 			    ARCHIVE_ERRNO_FILE_FORMAT,
3997085658deSDaniel Fojt 			    "Malformed OS X metadata entry: "
3998085658deSDaniel Fojt 			    "inconsistent size");
39996b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
40006b384f39SPeter Avalos 		}
40016b384f39SPeter Avalos #ifdef HAVE_ZLIB_H
40026b384f39SPeter Avalos 	case 8: /* Deflate compression. */
40036b384f39SPeter Avalos #endif
40046b384f39SPeter Avalos 		break;
40056b384f39SPeter Avalos 	default: /* Unsupported compression. */
40066b384f39SPeter Avalos 		/* Return a warning. */
40076b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
40086b384f39SPeter Avalos 		    "Unsupported ZIP compression method (%s)",
40096b384f39SPeter Avalos 		    compression_name(rsrc->compression));
40106b384f39SPeter Avalos 		/* We can't decompress this entry, but we will
40116b384f39SPeter Avalos 		 * be able to skip() it and try the next entry. */
40126b384f39SPeter Avalos 		return (ARCHIVE_WARN);
40136b384f39SPeter Avalos 	}
40146b384f39SPeter Avalos 
40156b384f39SPeter Avalos 	if (rsrc->uncompressed_size > (4 * 1024 * 1024)) {
40166b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
40176b384f39SPeter Avalos 		    "Mac metadata is too large: %jd > 4M bytes",
40186b384f39SPeter Avalos 		    (intmax_t)rsrc->uncompressed_size);
40196b384f39SPeter Avalos 		return (ARCHIVE_WARN);
40206b384f39SPeter Avalos 	}
40216b384f39SPeter Avalos 	if (rsrc->compressed_size > (4 * 1024 * 1024)) {
40226b384f39SPeter Avalos 		archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
40236b384f39SPeter Avalos 		    "Mac metadata is too large: %jd > 4M bytes",
40246b384f39SPeter Avalos 		    (intmax_t)rsrc->compressed_size);
40256b384f39SPeter Avalos 		return (ARCHIVE_WARN);
40266b384f39SPeter Avalos 	}
40276b384f39SPeter Avalos 
40286b384f39SPeter Avalos 	metadata = malloc((size_t)rsrc->uncompressed_size);
40296b384f39SPeter Avalos 	if (metadata == NULL) {
40306b384f39SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
40316b384f39SPeter Avalos 		    "Can't allocate memory for Mac metadata");
40326b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
40336b384f39SPeter Avalos 	}
40346b384f39SPeter Avalos 
40356b384f39SPeter Avalos 	if (offset < rsrc->local_header_offset)
40366b384f39SPeter Avalos 		__archive_read_consume(a, rsrc->local_header_offset - offset);
40376b384f39SPeter Avalos 	else if (offset != rsrc->local_header_offset) {
40386b384f39SPeter Avalos 		__archive_read_seek(a, rsrc->local_header_offset, SEEK_SET);
40396b384f39SPeter Avalos 	}
40406b384f39SPeter Avalos 
40416b384f39SPeter Avalos 	hsize = zip_get_local_file_header_size(a, 0);
40426b384f39SPeter Avalos 	__archive_read_consume(a, hsize);
40436b384f39SPeter Avalos 
40446b384f39SPeter Avalos 	remaining_bytes = (size_t)rsrc->compressed_size;
40456b384f39SPeter Avalos 	metadata_bytes = (size_t)rsrc->uncompressed_size;
40466b384f39SPeter Avalos 	mp = metadata;
40476b384f39SPeter Avalos 	eof = 0;
40486b384f39SPeter Avalos 	while (!eof && remaining_bytes) {
40496b384f39SPeter Avalos 		const unsigned char *p;
40506b384f39SPeter Avalos 		ssize_t bytes_avail;
40516b384f39SPeter Avalos 		size_t bytes_used;
40526b384f39SPeter Avalos 
40536b384f39SPeter Avalos 		p = __archive_read_ahead(a, 1, &bytes_avail);
40546b384f39SPeter Avalos 		if (p == NULL) {
40556b384f39SPeter Avalos 			archive_set_error(&a->archive,
40566b384f39SPeter Avalos 			    ARCHIVE_ERRNO_FILE_FORMAT,
40576b384f39SPeter Avalos 			    "Truncated ZIP file header");
40586b384f39SPeter Avalos 			ret = ARCHIVE_WARN;
40596b384f39SPeter Avalos 			goto exit_mac_metadata;
40606b384f39SPeter Avalos 		}
40616b384f39SPeter Avalos 		if ((size_t)bytes_avail > remaining_bytes)
40626b384f39SPeter Avalos 			bytes_avail = remaining_bytes;
40636b384f39SPeter Avalos 		switch(rsrc->compression) {
40646b384f39SPeter Avalos 		case 0:  /* No compression. */
40656b384f39SPeter Avalos 			if ((size_t)bytes_avail > metadata_bytes)
40666b384f39SPeter Avalos 				bytes_avail = metadata_bytes;
40676b384f39SPeter Avalos 			memcpy(mp, p, bytes_avail);
40686b384f39SPeter Avalos 			bytes_used = (size_t)bytes_avail;
40696b384f39SPeter Avalos 			metadata_bytes -= bytes_used;
40706b384f39SPeter Avalos 			mp += bytes_used;
40716b384f39SPeter Avalos 			if (metadata_bytes == 0)
40726b384f39SPeter Avalos 				eof = 1;
40736b384f39SPeter Avalos 			break;
40746b384f39SPeter Avalos #ifdef HAVE_ZLIB_H
40756b384f39SPeter Avalos 		case 8: /* Deflate compression. */
40766b384f39SPeter Avalos 		{
40776b384f39SPeter Avalos 			int r;
40786b384f39SPeter Avalos 
40796b384f39SPeter Avalos 			ret = zip_deflate_init(a, zip);
40806b384f39SPeter Avalos 			if (ret != ARCHIVE_OK)
40816b384f39SPeter Avalos 				goto exit_mac_metadata;
40826b384f39SPeter Avalos 			zip->stream.next_in =
40836b384f39SPeter Avalos 			    (Bytef *)(uintptr_t)(const void *)p;
40846b384f39SPeter Avalos 			zip->stream.avail_in = (uInt)bytes_avail;
40856b384f39SPeter Avalos 			zip->stream.total_in = 0;
40866b384f39SPeter Avalos 			zip->stream.next_out = mp;
40876b384f39SPeter Avalos 			zip->stream.avail_out = (uInt)metadata_bytes;
40886b384f39SPeter Avalos 			zip->stream.total_out = 0;
40896b384f39SPeter Avalos 
40906b384f39SPeter Avalos 			r = inflate(&zip->stream, 0);
40916b384f39SPeter Avalos 			switch (r) {
40926b384f39SPeter Avalos 			case Z_OK:
40936b384f39SPeter Avalos 				break;
40946b384f39SPeter Avalos 			case Z_STREAM_END:
40956b384f39SPeter Avalos 				eof = 1;
40966b384f39SPeter Avalos 				break;
40976b384f39SPeter Avalos 			case Z_MEM_ERROR:
40986b384f39SPeter Avalos 				archive_set_error(&a->archive, ENOMEM,
40996b384f39SPeter Avalos 				    "Out of memory for ZIP decompression");
41006b384f39SPeter Avalos 				ret = ARCHIVE_FATAL;
41016b384f39SPeter Avalos 				goto exit_mac_metadata;
41026b384f39SPeter Avalos 			default:
41036b384f39SPeter Avalos 				archive_set_error(&a->archive,
41046b384f39SPeter Avalos 				    ARCHIVE_ERRNO_MISC,
41056b384f39SPeter Avalos 				    "ZIP decompression failed (%d)", r);
41066b384f39SPeter Avalos 				ret = ARCHIVE_FATAL;
41076b384f39SPeter Avalos 				goto exit_mac_metadata;
41086b384f39SPeter Avalos 			}
41096b384f39SPeter Avalos 			bytes_used = zip->stream.total_in;
41106b384f39SPeter Avalos 			metadata_bytes -= zip->stream.total_out;
41116b384f39SPeter Avalos 			mp += zip->stream.total_out;
41126b384f39SPeter Avalos 			break;
41136b384f39SPeter Avalos 		}
41146b384f39SPeter Avalos #endif
41156b384f39SPeter Avalos 		default:
41166b384f39SPeter Avalos 			bytes_used = 0;
41176b384f39SPeter Avalos 			break;
41186b384f39SPeter Avalos 		}
41196b384f39SPeter Avalos 		__archive_read_consume(a, bytes_used);
41206b384f39SPeter Avalos 		remaining_bytes -= bytes_used;
41216b384f39SPeter Avalos 	}
41226b384f39SPeter Avalos 	archive_entry_copy_mac_metadata(entry, metadata,
41236b384f39SPeter Avalos 	    (size_t)rsrc->uncompressed_size - metadata_bytes);
41246b384f39SPeter Avalos 
41256b384f39SPeter Avalos exit_mac_metadata:
41266b384f39SPeter Avalos 	__archive_read_seek(a, offset, SEEK_SET);
41276b384f39SPeter Avalos 	zip->decompress_init = 0;
41286b384f39SPeter Avalos 	free(metadata);
41296b384f39SPeter Avalos 	return (ret);
41306b384f39SPeter Avalos }
41316b384f39SPeter Avalos 
41326b384f39SPeter Avalos static int
archive_read_format_zip_seekable_read_header(struct archive_read * a,struct archive_entry * entry)41336b384f39SPeter Avalos archive_read_format_zip_seekable_read_header(struct archive_read *a,
41346b384f39SPeter Avalos 	struct archive_entry *entry)
41356b384f39SPeter Avalos {
41366b384f39SPeter Avalos 	struct zip *zip = (struct zip *)a->format->data;
41376b384f39SPeter Avalos 	struct zip_entry *rsrc;
41386b384f39SPeter Avalos 	int64_t offset;
41396b384f39SPeter Avalos 	int r, ret = ARCHIVE_OK;
41406b384f39SPeter Avalos 
41416b384f39SPeter Avalos 	/*
41426b384f39SPeter Avalos 	 * It should be sufficient to call archive_read_next_header() for
41436b384f39SPeter Avalos 	 * a reader to determine if an entry is encrypted or not. If the
41446b384f39SPeter Avalos 	 * encryption of an entry is only detectable when calling
41456b384f39SPeter Avalos 	 * archive_read_data(), so be it. We'll do the same check there
41466b384f39SPeter Avalos 	 * as well.
41476b384f39SPeter Avalos 	 */
41486b384f39SPeter Avalos 	if (zip->has_encrypted_entries ==
41496b384f39SPeter Avalos 			ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW)
41506b384f39SPeter Avalos 		zip->has_encrypted_entries = 0;
41516b384f39SPeter Avalos 
41526b384f39SPeter Avalos 	a->archive.archive_format = ARCHIVE_FORMAT_ZIP;
41536b384f39SPeter Avalos 	if (a->archive.archive_format_name == NULL)
41546b384f39SPeter Avalos 		a->archive.archive_format_name = "ZIP";
41556b384f39SPeter Avalos 
41566b384f39SPeter Avalos 	if (zip->zip_entries == NULL) {
4157085658deSDaniel Fojt 		r = slurp_central_directory(a, entry, zip);
41586b384f39SPeter Avalos 		if (r != ARCHIVE_OK)
41596b384f39SPeter Avalos 			return r;
41606b384f39SPeter Avalos 		/* Get first entry whose local header offset is lower than
41616b384f39SPeter Avalos 		 * other entries in the archive file. */
41626b384f39SPeter Avalos 		zip->entry =
41636b384f39SPeter Avalos 		    (struct zip_entry *)ARCHIVE_RB_TREE_MIN(&zip->tree);
41646b384f39SPeter Avalos 	} else if (zip->entry != NULL) {
41656b384f39SPeter Avalos 		/* Get next entry in local header offset order. */
41666b384f39SPeter Avalos 		zip->entry = (struct zip_entry *)__archive_rb_tree_iterate(
41676b384f39SPeter Avalos 		    &zip->tree, &zip->entry->node, ARCHIVE_RB_DIR_RIGHT);
41686b384f39SPeter Avalos 	}
41696b384f39SPeter Avalos 
41706b384f39SPeter Avalos 	if (zip->entry == NULL)
41716b384f39SPeter Avalos 		return ARCHIVE_EOF;
41726b384f39SPeter Avalos 
41736b384f39SPeter Avalos 	if (zip->entry->rsrcname.s)
41746b384f39SPeter Avalos 		rsrc = (struct zip_entry *)__archive_rb_tree_find_node(
41756b384f39SPeter Avalos 		    &zip->tree_rsrc, zip->entry->rsrcname.s);
41766b384f39SPeter Avalos 	else
41776b384f39SPeter Avalos 		rsrc = NULL;
41786b384f39SPeter Avalos 
41796b384f39SPeter Avalos 	if (zip->cctx_valid)
41806b384f39SPeter Avalos 		archive_decrypto_aes_ctr_release(&zip->cctx);
41816b384f39SPeter Avalos 	if (zip->hctx_valid)
41826b384f39SPeter Avalos 		archive_hmac_sha1_cleanup(&zip->hctx);
41836b384f39SPeter Avalos 	zip->tctx_valid = zip->cctx_valid = zip->hctx_valid = 0;
41846b384f39SPeter Avalos 	__archive_read_reset_passphrase(a);
41856b384f39SPeter Avalos 
41866b384f39SPeter Avalos 	/* File entries are sorted by the header offset, we should mostly
4187085658deSDaniel Fojt 	 * use __archive_read_consume to advance a read point to avoid
4188085658deSDaniel Fojt 	 * redundant data reading.  */
41896b384f39SPeter Avalos 	offset = archive_filter_bytes(&a->archive, 0);
41906b384f39SPeter Avalos 	if (offset < zip->entry->local_header_offset)
41916b384f39SPeter Avalos 		__archive_read_consume(a,
41926b384f39SPeter Avalos 		    zip->entry->local_header_offset - offset);
41936b384f39SPeter Avalos 	else if (offset != zip->entry->local_header_offset) {
41946b384f39SPeter Avalos 		__archive_read_seek(a, zip->entry->local_header_offset,
41956b384f39SPeter Avalos 		    SEEK_SET);
41966b384f39SPeter Avalos 	}
41976b384f39SPeter Avalos 	zip->unconsumed = 0;
41986b384f39SPeter Avalos 	r = zip_read_local_file_header(a, entry, zip);
41996b384f39SPeter Avalos 	if (r != ARCHIVE_OK)
42006b384f39SPeter Avalos 		return r;
42016b384f39SPeter Avalos 	if (rsrc) {
42026b384f39SPeter Avalos 		int ret2 = zip_read_mac_metadata(a, entry, rsrc);
42036b384f39SPeter Avalos 		if (ret2 < ret)
42046b384f39SPeter Avalos 			ret = ret2;
42056b384f39SPeter Avalos 	}
42066b384f39SPeter Avalos 	return (ret);
42076b384f39SPeter Avalos }
42086b384f39SPeter Avalos 
42096b384f39SPeter Avalos /*
42106b384f39SPeter Avalos  * We're going to seek for the next header anyway, so we don't
42116b384f39SPeter Avalos  * need to bother doing anything here.
42126b384f39SPeter Avalos  */
42136b384f39SPeter Avalos static int
archive_read_format_zip_read_data_skip_seekable(struct archive_read * a)42146b384f39SPeter Avalos archive_read_format_zip_read_data_skip_seekable(struct archive_read *a)
42156b384f39SPeter Avalos {
42166b384f39SPeter Avalos 	struct zip *zip;
42176b384f39SPeter Avalos 	zip = (struct zip *)(a->format->data);
42186b384f39SPeter Avalos 
42196b384f39SPeter Avalos 	zip->unconsumed = 0;
42206b384f39SPeter Avalos 	return (ARCHIVE_OK);
42216b384f39SPeter Avalos }
42226b384f39SPeter Avalos 
42236b384f39SPeter Avalos int
archive_read_support_format_zip_seekable(struct archive * _a)42246b384f39SPeter Avalos archive_read_support_format_zip_seekable(struct archive *_a)
42256b384f39SPeter Avalos {
42266b384f39SPeter Avalos 	struct archive_read *a = (struct archive_read *)_a;
42276b384f39SPeter Avalos 	struct zip *zip;
42286b384f39SPeter Avalos 	int r;
42296b384f39SPeter Avalos 
42306b384f39SPeter Avalos 	archive_check_magic(_a, ARCHIVE_READ_MAGIC,
42316b384f39SPeter Avalos 	    ARCHIVE_STATE_NEW, "archive_read_support_format_zip_seekable");
42326b384f39SPeter Avalos 
42336b384f39SPeter Avalos 	zip = (struct zip *)calloc(1, sizeof(*zip));
42346b384f39SPeter Avalos 	if (zip == NULL) {
42356b384f39SPeter Avalos 		archive_set_error(&a->archive, ENOMEM,
42366b384f39SPeter Avalos 		    "Can't allocate zip data");
42376b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
42386b384f39SPeter Avalos 	}
42396b384f39SPeter Avalos 
42406b384f39SPeter Avalos #ifdef HAVE_COPYFILE_H
42416b384f39SPeter Avalos 	/* Set this by default on Mac OS. */
42426b384f39SPeter Avalos 	zip->process_mac_extensions = 1;
42436b384f39SPeter Avalos #endif
42446b384f39SPeter Avalos 
42456b384f39SPeter Avalos 	/*
42466b384f39SPeter Avalos 	 * Until enough data has been read, we cannot tell about
42476b384f39SPeter Avalos 	 * any encrypted entries yet.
42486b384f39SPeter Avalos 	 */
42496b384f39SPeter Avalos 	zip->has_encrypted_entries = ARCHIVE_READ_FORMAT_ENCRYPTION_DONT_KNOW;
42506b384f39SPeter Avalos 	zip->crc32func = real_crc32;
42516b384f39SPeter Avalos 
42526b384f39SPeter Avalos 	r = __archive_read_register_format(a,
42536b384f39SPeter Avalos 	    zip,
42546b384f39SPeter Avalos 	    "zip",
42556b384f39SPeter Avalos 	    archive_read_format_zip_seekable_bid,
42566b384f39SPeter Avalos 	    archive_read_format_zip_options,
42576b384f39SPeter Avalos 	    archive_read_format_zip_seekable_read_header,
42586b384f39SPeter Avalos 	    archive_read_format_zip_read_data,
42596b384f39SPeter Avalos 	    archive_read_format_zip_read_data_skip_seekable,
42606b384f39SPeter Avalos 	    NULL,
42616b384f39SPeter Avalos 	    archive_read_format_zip_cleanup,
42626b384f39SPeter Avalos 	    archive_read_support_format_zip_capabilities_seekable,
42636b384f39SPeter Avalos 	    archive_read_format_zip_has_encrypted_entries);
42646b384f39SPeter Avalos 
42656b384f39SPeter Avalos 	if (r != ARCHIVE_OK)
42666b384f39SPeter Avalos 		free(zip);
42676b384f39SPeter Avalos 	return (ARCHIVE_OK);
42686b384f39SPeter Avalos }
4269085658deSDaniel Fojt 
4270085658deSDaniel Fojt /*# vim:set noet:*/
4271