16b384f39SPeter Avalos /*-
26b384f39SPeter Avalos  * Copyright (c) 2014 Michihiro NAKAJIMA
36b384f39SPeter Avalos  * All rights reserved.
46b384f39SPeter Avalos  *
56b384f39SPeter Avalos  * Redistribution and use in source and binary forms, with or without
66b384f39SPeter Avalos  * modification, are permitted provided that the following conditions
76b384f39SPeter Avalos  * are met:
86b384f39SPeter Avalos  * 1. Redistributions of source code must retain the above copyright
96b384f39SPeter Avalos  *    notice, this list of conditions and the following disclaimer.
106b384f39SPeter Avalos  * 2. Redistributions in binary form must reproduce the above copyright
116b384f39SPeter Avalos  *    notice, this list of conditions and the following disclaimer in the
126b384f39SPeter Avalos  *    documentation and/or other materials provided with the distribution.
136b384f39SPeter Avalos  *
146b384f39SPeter Avalos  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
156b384f39SPeter Avalos  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
166b384f39SPeter Avalos  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
176b384f39SPeter Avalos  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
186b384f39SPeter Avalos  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
196b384f39SPeter Avalos  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
206b384f39SPeter Avalos  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
216b384f39SPeter Avalos  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
226b384f39SPeter Avalos  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
236b384f39SPeter Avalos  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
246b384f39SPeter Avalos  */
256b384f39SPeter Avalos 
266b384f39SPeter Avalos #include "archive_platform.h"
276b384f39SPeter Avalos 
286b384f39SPeter Avalos __FBSDID("$FreeBSD$");
296b384f39SPeter Avalos 
306b384f39SPeter Avalos #ifdef HAVE_ERRNO_H
316b384f39SPeter Avalos #include <errno.h>
326b384f39SPeter Avalos #endif
336b384f39SPeter Avalos #include <stdio.h>
346b384f39SPeter Avalos #ifdef HAVE_STDLIB_H
356b384f39SPeter Avalos #include <stdlib.h>
366b384f39SPeter Avalos #endif
376b384f39SPeter Avalos #ifdef HAVE_STRING_H
386b384f39SPeter Avalos #include <string.h>
396b384f39SPeter Avalos #endif
406b384f39SPeter Avalos #ifdef HAVE_UNISTD_H
416b384f39SPeter Avalos #include <unistd.h>
426b384f39SPeter Avalos #endif
436b384f39SPeter Avalos #ifdef HAVE_LZ4_H
446b384f39SPeter Avalos #include <lz4.h>
456b384f39SPeter Avalos #endif
466b384f39SPeter Avalos 
476b384f39SPeter Avalos #include "archive.h"
486b384f39SPeter Avalos #include "archive_endian.h"
496b384f39SPeter Avalos #include "archive_private.h"
506b384f39SPeter Avalos #include "archive_read_private.h"
516b384f39SPeter Avalos #include "archive_xxhash.h"
526b384f39SPeter Avalos 
536b384f39SPeter Avalos #define LZ4_MAGICNUMBER		0x184d2204
546b384f39SPeter Avalos #define LZ4_SKIPPABLED		0x184d2a50
556b384f39SPeter Avalos #define LZ4_LEGACY		0x184c2102
566b384f39SPeter Avalos 
576b384f39SPeter Avalos #if defined(HAVE_LIBLZ4)
586b384f39SPeter Avalos struct private_data {
596b384f39SPeter Avalos 	enum {  SELECT_STREAM,
606b384f39SPeter Avalos 		READ_DEFAULT_STREAM,
616b384f39SPeter Avalos 		READ_DEFAULT_BLOCK,
626b384f39SPeter Avalos 		READ_LEGACY_STREAM,
636b384f39SPeter Avalos 		READ_LEGACY_BLOCK,
646b384f39SPeter Avalos 	}		stage;
656b384f39SPeter Avalos 	struct {
666b384f39SPeter Avalos 		unsigned block_independence:1;
676b384f39SPeter Avalos 		unsigned block_checksum:3;
686b384f39SPeter Avalos 		unsigned stream_size:1;
696b384f39SPeter Avalos 		unsigned stream_checksum:1;
706b384f39SPeter Avalos 		unsigned preset_dictionary:1;
716b384f39SPeter Avalos 		int	 block_maximum_size;
726b384f39SPeter Avalos 	} flags;
736b384f39SPeter Avalos 	int64_t		 stream_size;
746b384f39SPeter Avalos 	uint32_t	 dict_id;
756b384f39SPeter Avalos 	char		*out_block;
766b384f39SPeter Avalos 	size_t		 out_block_size;
776b384f39SPeter Avalos 
786b384f39SPeter Avalos 	/* Bytes read but not yet consumed via __archive_read_consume() */
796b384f39SPeter Avalos 	size_t		 unconsumed;
806b384f39SPeter Avalos 	size_t		 decoded_size;
816b384f39SPeter Avalos 	void		*xxh32_state;
826b384f39SPeter Avalos 
836b384f39SPeter Avalos 	char		 valid; /* True = decompressor is initialized */
846b384f39SPeter Avalos 	char		 eof; /* True = found end of compressed data. */
856b384f39SPeter Avalos };
866b384f39SPeter Avalos 
876b384f39SPeter Avalos #define LEGACY_BLOCK_SIZE	(8 * 1024 * 1024)
886b384f39SPeter Avalos 
896b384f39SPeter Avalos /* Lz4 filter */
906b384f39SPeter Avalos static ssize_t	lz4_filter_read(struct archive_read_filter *, const void **);
916b384f39SPeter Avalos static int	lz4_filter_close(struct archive_read_filter *);
926b384f39SPeter Avalos #endif
936b384f39SPeter Avalos 
946b384f39SPeter Avalos /*
956b384f39SPeter Avalos  * Note that we can detect lz4 archives even if we can't decompress
966b384f39SPeter Avalos  * them.  (In fact, we like detecting them because we can give better
976b384f39SPeter Avalos  * error messages.)  So the bid framework here gets compiled even
986b384f39SPeter Avalos  * if liblz4 is unavailable.
996b384f39SPeter Avalos  */
1006b384f39SPeter Avalos static int	lz4_reader_bid(struct archive_read_filter_bidder *, struct archive_read_filter *);
1016b384f39SPeter Avalos static int	lz4_reader_init(struct archive_read_filter *);
1026b384f39SPeter Avalos #if defined(HAVE_LIBLZ4)
1036b384f39SPeter Avalos static ssize_t  lz4_filter_read_default_stream(struct archive_read_filter *,
1046b384f39SPeter Avalos 		    const void **);
1056b384f39SPeter Avalos static ssize_t  lz4_filter_read_legacy_stream(struct archive_read_filter *,
1066b384f39SPeter Avalos 		    const void **);
1076b384f39SPeter Avalos #endif
1086b384f39SPeter Avalos 
109*50f8aa9cSAntonio Huete Jimenez static const struct archive_read_filter_bidder_vtable
110*50f8aa9cSAntonio Huete Jimenez lz4_bidder_vtable = {
111*50f8aa9cSAntonio Huete Jimenez 	.bid = lz4_reader_bid,
112*50f8aa9cSAntonio Huete Jimenez 	.init = lz4_reader_init,
113*50f8aa9cSAntonio Huete Jimenez };
114*50f8aa9cSAntonio Huete Jimenez 
1156b384f39SPeter Avalos int
archive_read_support_filter_lz4(struct archive * _a)1166b384f39SPeter Avalos archive_read_support_filter_lz4(struct archive *_a)
1176b384f39SPeter Avalos {
1186b384f39SPeter Avalos 	struct archive_read *a = (struct archive_read *)_a;
1196b384f39SPeter Avalos 
120*50f8aa9cSAntonio Huete Jimenez 	if (__archive_read_register_bidder(a, NULL, "lz4",
121*50f8aa9cSAntonio Huete Jimenez 				&lz4_bidder_vtable) != ARCHIVE_OK)
1226b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
1236b384f39SPeter Avalos 
1246b384f39SPeter Avalos #if defined(HAVE_LIBLZ4)
1256b384f39SPeter Avalos 	return (ARCHIVE_OK);
1266b384f39SPeter Avalos #else
1276b384f39SPeter Avalos 	archive_set_error(_a, ARCHIVE_ERRNO_MISC,
1286b384f39SPeter Avalos 	    "Using external lz4 program");
1296b384f39SPeter Avalos 	return (ARCHIVE_WARN);
1306b384f39SPeter Avalos #endif
1316b384f39SPeter Avalos }
1326b384f39SPeter Avalos 
1336b384f39SPeter Avalos /*
1346b384f39SPeter Avalos  * Test whether we can handle this data.
1356b384f39SPeter Avalos  *
1366b384f39SPeter Avalos  * This logic returns zero if any part of the signature fails.  It
1376b384f39SPeter Avalos  * also tries to Do The Right Thing if a very short buffer prevents us
1386b384f39SPeter Avalos  * from verifying as much as we would like.
1396b384f39SPeter Avalos  */
1406b384f39SPeter Avalos static int
lz4_reader_bid(struct archive_read_filter_bidder * self,struct archive_read_filter * filter)1416b384f39SPeter Avalos lz4_reader_bid(struct archive_read_filter_bidder *self,
1426b384f39SPeter Avalos     struct archive_read_filter *filter)
1436b384f39SPeter Avalos {
1446b384f39SPeter Avalos 	const unsigned char *buffer;
1456b384f39SPeter Avalos 	ssize_t avail;
1466b384f39SPeter Avalos 	int bits_checked;
1476b384f39SPeter Avalos 	uint32_t number;
1486b384f39SPeter Avalos 
1496b384f39SPeter Avalos 	(void)self; /* UNUSED */
1506b384f39SPeter Avalos 
1516b384f39SPeter Avalos 	/* Minimal lz4 archive is 11 bytes. */
1526b384f39SPeter Avalos 	buffer = __archive_read_filter_ahead(filter, 11, &avail);
1536b384f39SPeter Avalos 	if (buffer == NULL)
1546b384f39SPeter Avalos 		return (0);
1556b384f39SPeter Avalos 
1566b384f39SPeter Avalos 	/* First four bytes must be LZ4 magic numbers. */
1576b384f39SPeter Avalos 	bits_checked = 0;
1586b384f39SPeter Avalos 	if ((number = archive_le32dec(buffer)) == LZ4_MAGICNUMBER) {
1596b384f39SPeter Avalos 		unsigned char flag, BD;
1606b384f39SPeter Avalos 
1616b384f39SPeter Avalos 		bits_checked += 32;
1626b384f39SPeter Avalos 		/* Next follows a stream descriptor. */
1636b384f39SPeter Avalos 		/* Descriptor Flags. */
1646b384f39SPeter Avalos 		flag = buffer[4];
1656b384f39SPeter Avalos 		/* A version number must be "01". */
1666b384f39SPeter Avalos 		if (((flag & 0xc0) >> 6) != 1)
1676b384f39SPeter Avalos 			return (0);
1686b384f39SPeter Avalos 		/* A reserved bit must be "0". */
1696b384f39SPeter Avalos 		if (flag & 2)
1706b384f39SPeter Avalos 			return (0);
1716b384f39SPeter Avalos 		bits_checked += 8;
1726b384f39SPeter Avalos 		BD = buffer[5];
173e95abc47Szrj 		/* A block maximum size should be more than 3. */
1746b384f39SPeter Avalos 		if (((BD & 0x70) >> 4) < 4)
1756b384f39SPeter Avalos 			return (0);
1766b384f39SPeter Avalos 		/* Reserved bits must be "0". */
1776b384f39SPeter Avalos 		if (BD & ~0x70)
1786b384f39SPeter Avalos 			return (0);
1796b384f39SPeter Avalos 		bits_checked += 8;
1806b384f39SPeter Avalos 	} else if (number == LZ4_LEGACY) {
1816b384f39SPeter Avalos 		bits_checked += 32;
1826b384f39SPeter Avalos 	}
1836b384f39SPeter Avalos 
1846b384f39SPeter Avalos 	return (bits_checked);
1856b384f39SPeter Avalos }
1866b384f39SPeter Avalos 
1876b384f39SPeter Avalos #if !defined(HAVE_LIBLZ4)
1886b384f39SPeter Avalos 
1896b384f39SPeter Avalos /*
1906b384f39SPeter Avalos  * If we don't have the library on this system, we can't actually do the
1916b384f39SPeter Avalos  * decompression.  We can, however, still detect compressed archives
1926b384f39SPeter Avalos  * and emit a useful message.
1936b384f39SPeter Avalos  */
1946b384f39SPeter Avalos static int
lz4_reader_init(struct archive_read_filter * self)1956b384f39SPeter Avalos lz4_reader_init(struct archive_read_filter *self)
1966b384f39SPeter Avalos {
1976b384f39SPeter Avalos 	int r;
1986b384f39SPeter Avalos 
1996b384f39SPeter Avalos 	r = __archive_read_program(self, "lz4 -d -q");
2006b384f39SPeter Avalos 	/* Note: We set the format here even if __archive_read_program()
2016b384f39SPeter Avalos 	 * above fails.  We do, after all, know what the format is
2026b384f39SPeter Avalos 	 * even if we weren't able to read it. */
2036b384f39SPeter Avalos 	self->code = ARCHIVE_FILTER_LZ4;
2046b384f39SPeter Avalos 	self->name = "lz4";
2056b384f39SPeter Avalos 	return (r);
2066b384f39SPeter Avalos }
2076b384f39SPeter Avalos 
2086b384f39SPeter Avalos 
2096b384f39SPeter Avalos #else
2106b384f39SPeter Avalos 
211*50f8aa9cSAntonio Huete Jimenez static const struct archive_read_filter_vtable
212*50f8aa9cSAntonio Huete Jimenez lz4_reader_vtable = {
213*50f8aa9cSAntonio Huete Jimenez 	.read = lz4_filter_read,
214*50f8aa9cSAntonio Huete Jimenez 	.close = lz4_filter_close,
215*50f8aa9cSAntonio Huete Jimenez };
216*50f8aa9cSAntonio Huete Jimenez 
2176b384f39SPeter Avalos /*
2186b384f39SPeter Avalos  * Setup the callbacks.
2196b384f39SPeter Avalos  */
2206b384f39SPeter Avalos static int
lz4_reader_init(struct archive_read_filter * self)2216b384f39SPeter Avalos lz4_reader_init(struct archive_read_filter *self)
2226b384f39SPeter Avalos {
2236b384f39SPeter Avalos 	struct private_data *state;
2246b384f39SPeter Avalos 
2256b384f39SPeter Avalos 	self->code = ARCHIVE_FILTER_LZ4;
2266b384f39SPeter Avalos 	self->name = "lz4";
2276b384f39SPeter Avalos 
2286b384f39SPeter Avalos 	state = (struct private_data *)calloc(sizeof(*state), 1);
2296b384f39SPeter Avalos 	if (state == NULL) {
2306b384f39SPeter Avalos 		archive_set_error(&self->archive->archive, ENOMEM,
2316b384f39SPeter Avalos 		    "Can't allocate data for lz4 decompression");
2326b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
2336b384f39SPeter Avalos 	}
2346b384f39SPeter Avalos 
2356b384f39SPeter Avalos 	self->data = state;
2366b384f39SPeter Avalos 	state->stage = SELECT_STREAM;
237*50f8aa9cSAntonio Huete Jimenez 	self->vtable = &lz4_reader_vtable;
2386b384f39SPeter Avalos 
2396b384f39SPeter Avalos 	return (ARCHIVE_OK);
2406b384f39SPeter Avalos }
2416b384f39SPeter Avalos 
2426b384f39SPeter Avalos static int
lz4_allocate_out_block(struct archive_read_filter * self)2436b384f39SPeter Avalos lz4_allocate_out_block(struct archive_read_filter *self)
2446b384f39SPeter Avalos {
2456b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
2466b384f39SPeter Avalos 	size_t out_block_size = state->flags.block_maximum_size;
2476b384f39SPeter Avalos 	void *out_block;
2486b384f39SPeter Avalos 
2496b384f39SPeter Avalos 	if (!state->flags.block_independence)
2506b384f39SPeter Avalos 		out_block_size += 64 * 1024;
2516b384f39SPeter Avalos 	if (state->out_block_size < out_block_size) {
2526b384f39SPeter Avalos 		free(state->out_block);
2536b384f39SPeter Avalos 		out_block = (unsigned char *)malloc(out_block_size);
2546b384f39SPeter Avalos 		state->out_block_size = out_block_size;
2556b384f39SPeter Avalos 		if (out_block == NULL) {
2566b384f39SPeter Avalos 			archive_set_error(&self->archive->archive, ENOMEM,
2576b384f39SPeter Avalos 			    "Can't allocate data for lz4 decompression");
2586b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
2596b384f39SPeter Avalos 		}
2606b384f39SPeter Avalos 		state->out_block = out_block;
2616b384f39SPeter Avalos 	}
2626b384f39SPeter Avalos 	if (!state->flags.block_independence)
2636b384f39SPeter Avalos 		memset(state->out_block, 0, 64 * 1024);
2646b384f39SPeter Avalos 	return (ARCHIVE_OK);
2656b384f39SPeter Avalos }
2666b384f39SPeter Avalos 
2676b384f39SPeter Avalos static int
lz4_allocate_out_block_for_legacy(struct archive_read_filter * self)2686b384f39SPeter Avalos lz4_allocate_out_block_for_legacy(struct archive_read_filter *self)
2696b384f39SPeter Avalos {
2706b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
2716b384f39SPeter Avalos 	size_t out_block_size = LEGACY_BLOCK_SIZE;
2726b384f39SPeter Avalos 	void *out_block;
2736b384f39SPeter Avalos 
2746b384f39SPeter Avalos 	if (state->out_block_size < out_block_size) {
2756b384f39SPeter Avalos 		free(state->out_block);
2766b384f39SPeter Avalos 		out_block = (unsigned char *)malloc(out_block_size);
2776b384f39SPeter Avalos 		state->out_block_size = out_block_size;
2786b384f39SPeter Avalos 		if (out_block == NULL) {
2796b384f39SPeter Avalos 			archive_set_error(&self->archive->archive, ENOMEM,
2806b384f39SPeter Avalos 			    "Can't allocate data for lz4 decompression");
2816b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
2826b384f39SPeter Avalos 		}
2836b384f39SPeter Avalos 		state->out_block = out_block;
2846b384f39SPeter Avalos 	}
2856b384f39SPeter Avalos 	return (ARCHIVE_OK);
2866b384f39SPeter Avalos }
2876b384f39SPeter Avalos 
2886b384f39SPeter Avalos /*
2896b384f39SPeter Avalos  * Return the next block of decompressed data.
2906b384f39SPeter Avalos  */
2916b384f39SPeter Avalos static ssize_t
lz4_filter_read(struct archive_read_filter * self,const void ** p)2926b384f39SPeter Avalos lz4_filter_read(struct archive_read_filter *self, const void **p)
2936b384f39SPeter Avalos {
2946b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
2956b384f39SPeter Avalos 	ssize_t ret;
2966b384f39SPeter Avalos 
2976b384f39SPeter Avalos 	if (state->eof) {
2986b384f39SPeter Avalos 		*p = NULL;
2996b384f39SPeter Avalos 		return (0);
3006b384f39SPeter Avalos 	}
3016b384f39SPeter Avalos 
3026b384f39SPeter Avalos 	__archive_read_filter_consume(self->upstream, state->unconsumed);
3036b384f39SPeter Avalos 	state->unconsumed = 0;
3046b384f39SPeter Avalos 
3056b384f39SPeter Avalos 	switch (state->stage) {
3066b384f39SPeter Avalos 	case SELECT_STREAM:
3076b384f39SPeter Avalos 		break;
3086b384f39SPeter Avalos 	case READ_DEFAULT_STREAM:
3096b384f39SPeter Avalos 	case READ_LEGACY_STREAM:
3106b384f39SPeter Avalos 		/* Reading a lz4 stream already failed. */
3116b384f39SPeter Avalos 		archive_set_error(&self->archive->archive,
3126b384f39SPeter Avalos 		    ARCHIVE_ERRNO_MISC, "Invalid sequence.");
3136b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
3146b384f39SPeter Avalos 	case READ_DEFAULT_BLOCK:
3156b384f39SPeter Avalos 		ret = lz4_filter_read_default_stream(self, p);
3166b384f39SPeter Avalos 		if (ret != 0 || state->stage != SELECT_STREAM)
3176b384f39SPeter Avalos 			return ret;
3186b384f39SPeter Avalos 		break;
3196b384f39SPeter Avalos 	case READ_LEGACY_BLOCK:
3206b384f39SPeter Avalos 		ret = lz4_filter_read_legacy_stream(self, p);
3216b384f39SPeter Avalos 		if (ret != 0 || state->stage != SELECT_STREAM)
3226b384f39SPeter Avalos 			return ret;
3236b384f39SPeter Avalos 		break;
3246b384f39SPeter Avalos 	default:
3256b384f39SPeter Avalos 		archive_set_error(&self->archive->archive,
3266b384f39SPeter Avalos 		    ARCHIVE_ERRNO_MISC, "Program error.");
3276b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
3286b384f39SPeter Avalos 		break;
3296b384f39SPeter Avalos 	}
3306b384f39SPeter Avalos 
3316b384f39SPeter Avalos 	while (state->stage == SELECT_STREAM) {
3326b384f39SPeter Avalos 		const char *read_buf;
3336b384f39SPeter Avalos 
3346b384f39SPeter Avalos 		/* Read a magic number. */
3356b384f39SPeter Avalos 		read_buf = __archive_read_filter_ahead(self->upstream, 4,
3366b384f39SPeter Avalos 				NULL);
3376b384f39SPeter Avalos 		if (read_buf == NULL) {
3386b384f39SPeter Avalos 			state->eof = 1;
3396b384f39SPeter Avalos 			*p = NULL;
3406b384f39SPeter Avalos 			return (0);
3416b384f39SPeter Avalos 		}
3426b384f39SPeter Avalos 		uint32_t number = archive_le32dec(read_buf);
3436b384f39SPeter Avalos 		__archive_read_filter_consume(self->upstream, 4);
3446b384f39SPeter Avalos 		if (number == LZ4_MAGICNUMBER)
3456b384f39SPeter Avalos 			return lz4_filter_read_default_stream(self, p);
3466b384f39SPeter Avalos 		else if (number == LZ4_LEGACY)
3476b384f39SPeter Avalos 			return lz4_filter_read_legacy_stream(self, p);
3486b384f39SPeter Avalos 		else if ((number & ~0xF) == LZ4_SKIPPABLED) {
3496b384f39SPeter Avalos 			read_buf = __archive_read_filter_ahead(
3506b384f39SPeter Avalos 				self->upstream, 4, NULL);
3516b384f39SPeter Avalos 			if (read_buf == NULL) {
3526b384f39SPeter Avalos 				archive_set_error(
3536b384f39SPeter Avalos 				    &self->archive->archive,
3546b384f39SPeter Avalos 		    		    ARCHIVE_ERRNO_MISC,
3556b384f39SPeter Avalos 				    "Malformed lz4 data");
3566b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
3576b384f39SPeter Avalos 			}
3586b384f39SPeter Avalos 			uint32_t skip_bytes = archive_le32dec(read_buf);
3596b384f39SPeter Avalos 			__archive_read_filter_consume(self->upstream,
3606b384f39SPeter Avalos 				4 + skip_bytes);
3616b384f39SPeter Avalos 		} else {
3626b384f39SPeter Avalos 			/* Ignore following unrecognized data. */
3636b384f39SPeter Avalos 			state->eof = 1;
3646b384f39SPeter Avalos 			*p = NULL;
3656b384f39SPeter Avalos 			return (0);
3666b384f39SPeter Avalos 		}
3676b384f39SPeter Avalos 	}
3686b384f39SPeter Avalos 	state->eof = 1;
3696b384f39SPeter Avalos 	*p = NULL;
3706b384f39SPeter Avalos 	return (0);
3716b384f39SPeter Avalos }
3726b384f39SPeter Avalos 
3736b384f39SPeter Avalos static int
lz4_filter_read_descriptor(struct archive_read_filter * self)3746b384f39SPeter Avalos lz4_filter_read_descriptor(struct archive_read_filter *self)
3756b384f39SPeter Avalos {
3766b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
3776b384f39SPeter Avalos 	const char *read_buf;
3786b384f39SPeter Avalos 	ssize_t bytes_remaining;
3796b384f39SPeter Avalos 	ssize_t descriptor_bytes;
3806b384f39SPeter Avalos 	unsigned char flag, bd;
3816b384f39SPeter Avalos 	unsigned int chsum, chsum_verifier;
3826b384f39SPeter Avalos 
3836b384f39SPeter Avalos 	/* Make sure we have 2 bytes for flags. */
3846b384f39SPeter Avalos 	read_buf = __archive_read_filter_ahead(self->upstream, 2,
3856b384f39SPeter Avalos 	    &bytes_remaining);
3866b384f39SPeter Avalos 	if (read_buf == NULL) {
3876b384f39SPeter Avalos 		archive_set_error(&self->archive->archive,
3886b384f39SPeter Avalos 		    ARCHIVE_ERRNO_MISC,
3896b384f39SPeter Avalos 		    "truncated lz4 input");
3906b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
3916b384f39SPeter Avalos 	}
3926b384f39SPeter Avalos 
3936b384f39SPeter Avalos 	/*
3946b384f39SPeter Avalos 	   Parse flags.
3956b384f39SPeter Avalos 	 */
3966b384f39SPeter Avalos 	flag = (unsigned char)read_buf[0];
3976b384f39SPeter Avalos 	/* Verify version number. */
3986b384f39SPeter Avalos 	if ((flag & 0xc0) != 1<<6)
3996b384f39SPeter Avalos 		goto malformed_error;
4006b384f39SPeter Avalos 	/* A reserved bit must be zero. */
4016b384f39SPeter Avalos 	if (flag & 0x02)
4026b384f39SPeter Avalos 		goto malformed_error;
4036b384f39SPeter Avalos 	state->flags.block_independence = (flag & 0x20) != 0;
4046b384f39SPeter Avalos 	state->flags.block_checksum = (flag & 0x10)?4:0;
4056b384f39SPeter Avalos 	state->flags.stream_size = (flag & 0x08) != 0;
4066b384f39SPeter Avalos 	state->flags.stream_checksum = (flag & 0x04) != 0;
4076b384f39SPeter Avalos 	state->flags.preset_dictionary = (flag & 0x01) != 0;
4086b384f39SPeter Avalos 
4096b384f39SPeter Avalos 	/* BD */
4106b384f39SPeter Avalos 	bd = (unsigned char)read_buf[1];
4116b384f39SPeter Avalos 	/* Reserved bits must be zero. */
4126b384f39SPeter Avalos 	if (bd & 0x8f)
4136b384f39SPeter Avalos 		goto malformed_error;
414e95abc47Szrj 	/* Get a maximum block size. */
4156b384f39SPeter Avalos 	switch (read_buf[1] >> 4) {
4166b384f39SPeter Avalos 	case 4: /* 64 KB */
4176b384f39SPeter Avalos 		state->flags.block_maximum_size = 64 * 1024;
4186b384f39SPeter Avalos 		break;
4196b384f39SPeter Avalos 	case 5: /* 256 KB */
4206b384f39SPeter Avalos 		state->flags.block_maximum_size = 256 * 1024;
4216b384f39SPeter Avalos 		break;
4226b384f39SPeter Avalos 	case 6: /* 1 MB */
4236b384f39SPeter Avalos 		state->flags.block_maximum_size = 1024 * 1024;
4246b384f39SPeter Avalos 		break;
4256b384f39SPeter Avalos 	case 7: /* 4 MB */
4266b384f39SPeter Avalos 		state->flags.block_maximum_size = 4 * 1024 * 1024;
4276b384f39SPeter Avalos 		break;
4286b384f39SPeter Avalos 	default:
4296b384f39SPeter Avalos 		goto malformed_error;
4306b384f39SPeter Avalos 	}
4316b384f39SPeter Avalos 
4326b384f39SPeter Avalos 	/* Read the whole descriptor in a stream block. */
4336b384f39SPeter Avalos 	descriptor_bytes = 3;
4346b384f39SPeter Avalos 	if (state->flags.stream_size)
4356b384f39SPeter Avalos 		descriptor_bytes += 8;
4366b384f39SPeter Avalos 	if (state->flags.preset_dictionary)
4376b384f39SPeter Avalos 		descriptor_bytes += 4;
4386b384f39SPeter Avalos 	if (bytes_remaining < descriptor_bytes) {
4396b384f39SPeter Avalos 		read_buf = __archive_read_filter_ahead(self->upstream,
4406b384f39SPeter Avalos 		    descriptor_bytes, &bytes_remaining);
4416b384f39SPeter Avalos 		if (read_buf == NULL) {
4426b384f39SPeter Avalos 			archive_set_error(&self->archive->archive,
4436b384f39SPeter Avalos 			    ARCHIVE_ERRNO_MISC,
4446b384f39SPeter Avalos 			    "truncated lz4 input");
4456b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
4466b384f39SPeter Avalos 		}
4476b384f39SPeter Avalos 	}
4486b384f39SPeter Avalos 	/* Check if a descriptor is corrupted */
4496b384f39SPeter Avalos 	chsum = __archive_xxhash.XXH32(read_buf, (int)descriptor_bytes -1, 0);
4506b384f39SPeter Avalos 	chsum = (chsum >> 8) & 0xff;
4516b384f39SPeter Avalos 	chsum_verifier = read_buf[descriptor_bytes-1] & 0xff;
4526b384f39SPeter Avalos 	if (chsum != chsum_verifier)
4536b384f39SPeter Avalos 		goto malformed_error;
4546b384f39SPeter Avalos 
4556b384f39SPeter Avalos 	__archive_read_filter_consume(self->upstream, descriptor_bytes);
4566b384f39SPeter Avalos 
457085658deSDaniel Fojt 	/* Make sure we have a large enough buffer for uncompressed data. */
4586b384f39SPeter Avalos 	if (lz4_allocate_out_block(self) != ARCHIVE_OK)
4596b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
4606b384f39SPeter Avalos 	if (state->flags.stream_checksum)
4616b384f39SPeter Avalos 		state->xxh32_state = __archive_xxhash.XXH32_init(0);
4626b384f39SPeter Avalos 
4636b384f39SPeter Avalos 	state->decoded_size = 0;
4646b384f39SPeter Avalos 	/* Success */
4656b384f39SPeter Avalos 	return (ARCHIVE_OK);
4666b384f39SPeter Avalos malformed_error:
4676b384f39SPeter Avalos 	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
4686b384f39SPeter Avalos 	    "malformed lz4 data");
4696b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
4706b384f39SPeter Avalos }
4716b384f39SPeter Avalos 
4726b384f39SPeter Avalos static ssize_t
lz4_filter_read_data_block(struct archive_read_filter * self,const void ** p)4736b384f39SPeter Avalos lz4_filter_read_data_block(struct archive_read_filter *self, const void **p)
4746b384f39SPeter Avalos {
4756b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
4766b384f39SPeter Avalos 	ssize_t compressed_size;
4776b384f39SPeter Avalos 	const char *read_buf;
4786b384f39SPeter Avalos 	ssize_t bytes_remaining;
4796b384f39SPeter Avalos 	int checksum_size;
4806b384f39SPeter Avalos 	ssize_t uncompressed_size;
4816b384f39SPeter Avalos 	size_t prefix64k;
4826b384f39SPeter Avalos 
4836b384f39SPeter Avalos 	*p = NULL;
4846b384f39SPeter Avalos 
4856b384f39SPeter Avalos 	/* Make sure we have 4 bytes for a block size. */
4866b384f39SPeter Avalos 	read_buf = __archive_read_filter_ahead(self->upstream, 4,
4876b384f39SPeter Avalos 	    &bytes_remaining);
4886b384f39SPeter Avalos 	if (read_buf == NULL)
4896b384f39SPeter Avalos 		goto truncated_error;
4906b384f39SPeter Avalos 	compressed_size = archive_le32dec(read_buf);
491e95abc47Szrj 	if ((compressed_size & 0x7fffffff) > state->flags.block_maximum_size)
4926b384f39SPeter Avalos 		goto malformed_error;
4936b384f39SPeter Avalos 	/* A compressed size == 0 means the end of stream blocks. */
4946b384f39SPeter Avalos 	if (compressed_size == 0) {
4956b384f39SPeter Avalos 		__archive_read_filter_consume(self->upstream, 4);
4966b384f39SPeter Avalos 		return 0;
4976b384f39SPeter Avalos 	}
4986b384f39SPeter Avalos 
4996b384f39SPeter Avalos 	checksum_size = state->flags.block_checksum;
5006b384f39SPeter Avalos 	/* Check if the block is uncompressed. */
501e95abc47Szrj 	if (compressed_size & 0x80000000U) {
502e95abc47Szrj 		compressed_size &= 0x7fffffff;
5036b384f39SPeter Avalos 		uncompressed_size = compressed_size;
5046b384f39SPeter Avalos 	} else
5056b384f39SPeter Avalos 		uncompressed_size = 0;/* Unknown yet. */
5066b384f39SPeter Avalos 
5076b384f39SPeter Avalos 	/*
5086b384f39SPeter Avalos 	  Unfortunately, lz4 decompression API requires a whole block
5096b384f39SPeter Avalos 	  for its decompression speed, so we read a whole block and allocate
5106b384f39SPeter Avalos 	  a huge buffer used for decoded data.
5116b384f39SPeter Avalos 	*/
5126b384f39SPeter Avalos 	read_buf = __archive_read_filter_ahead(self->upstream,
5136b384f39SPeter Avalos 	    4 + compressed_size + checksum_size, &bytes_remaining);
5146b384f39SPeter Avalos 	if (read_buf == NULL)
5156b384f39SPeter Avalos 		goto truncated_error;
5166b384f39SPeter Avalos 
517085658deSDaniel Fojt 	/* Optional processing, checking a block sum. */
5186b384f39SPeter Avalos 	if (checksum_size) {
5196b384f39SPeter Avalos 		unsigned int chsum = __archive_xxhash.XXH32(
5206b384f39SPeter Avalos 			read_buf + 4, (int)compressed_size, 0);
5216b384f39SPeter Avalos 		unsigned int chsum_block =
5226b384f39SPeter Avalos 		    archive_le32dec(read_buf + 4 + compressed_size);
5236b384f39SPeter Avalos 		if (chsum != chsum_block)
5246b384f39SPeter Avalos 			goto malformed_error;
5256b384f39SPeter Avalos 	}
5266b384f39SPeter Avalos 
5276b384f39SPeter Avalos 
5286b384f39SPeter Avalos 	/* If the block is uncompressed, there is nothing to do. */
5296b384f39SPeter Avalos 	if (uncompressed_size) {
5306b384f39SPeter Avalos 		/* Prepare a prefix 64k block for next block. */
5316b384f39SPeter Avalos 		if (!state->flags.block_independence) {
5326b384f39SPeter Avalos 			prefix64k = 64 * 1024;
5336b384f39SPeter Avalos 			if (uncompressed_size < (ssize_t)prefix64k) {
5346b384f39SPeter Avalos 				memcpy(state->out_block
5356b384f39SPeter Avalos 					+ prefix64k - uncompressed_size,
5366b384f39SPeter Avalos 				    read_buf + 4,
5376b384f39SPeter Avalos 				    uncompressed_size);
5386b384f39SPeter Avalos 				memset(state->out_block, 0,
5396b384f39SPeter Avalos 				    prefix64k - uncompressed_size);
5406b384f39SPeter Avalos 			} else {
5416b384f39SPeter Avalos 				memcpy(state->out_block,
5426b384f39SPeter Avalos 				    read_buf + 4
5436b384f39SPeter Avalos 					+ uncompressed_size - prefix64k,
5446b384f39SPeter Avalos 				    prefix64k);
5456b384f39SPeter Avalos 			}
5466b384f39SPeter Avalos 			state->decoded_size = 0;
5476b384f39SPeter Avalos 		}
5486b384f39SPeter Avalos 		state->unconsumed = 4 + uncompressed_size + checksum_size;
5496b384f39SPeter Avalos 		*p = read_buf + 4;
5506b384f39SPeter Avalos 		return uncompressed_size;
5516b384f39SPeter Avalos 	}
5526b384f39SPeter Avalos 
5536b384f39SPeter Avalos 	/*
5546b384f39SPeter Avalos 	   Decompress a block data.
5556b384f39SPeter Avalos 	 */
5566b384f39SPeter Avalos 	if (state->flags.block_independence) {
5576b384f39SPeter Avalos 		prefix64k = 0;
5586b384f39SPeter Avalos 		uncompressed_size = LZ4_decompress_safe(read_buf + 4,
5596b384f39SPeter Avalos 		    state->out_block, (int)compressed_size,
5606b384f39SPeter Avalos 		    state->flags.block_maximum_size);
5616b384f39SPeter Avalos 	} else {
5626b384f39SPeter Avalos 		prefix64k = 64 * 1024;
5636b384f39SPeter Avalos 		if (state->decoded_size) {
5646b384f39SPeter Avalos 			if (state->decoded_size < prefix64k) {
5656b384f39SPeter Avalos 				memmove(state->out_block
5666b384f39SPeter Avalos 					+ prefix64k - state->decoded_size,
5676b384f39SPeter Avalos 				    state->out_block + prefix64k,
5686b384f39SPeter Avalos 				    state->decoded_size);
5696b384f39SPeter Avalos 				memset(state->out_block, 0,
5706b384f39SPeter Avalos 				    prefix64k - state->decoded_size);
5716b384f39SPeter Avalos 			} else {
5726b384f39SPeter Avalos 				memmove(state->out_block,
5736b384f39SPeter Avalos 				    state->out_block + state->decoded_size,
5746b384f39SPeter Avalos 				    prefix64k);
5756b384f39SPeter Avalos 			}
5766b384f39SPeter Avalos 		}
5776b384f39SPeter Avalos #if LZ4_VERSION_MAJOR >= 1 && LZ4_VERSION_MINOR >= 7
5786b384f39SPeter Avalos 		uncompressed_size = LZ4_decompress_safe_usingDict(
5796b384f39SPeter Avalos 		    read_buf + 4,
5806b384f39SPeter Avalos 		    state->out_block + prefix64k, (int)compressed_size,
5816b384f39SPeter Avalos 		    state->flags.block_maximum_size,
5826b384f39SPeter Avalos 		    state->out_block,
5836b384f39SPeter Avalos 		    prefix64k);
5846b384f39SPeter Avalos #else
5856b384f39SPeter Avalos 		uncompressed_size = LZ4_decompress_safe_withPrefix64k(
5866b384f39SPeter Avalos 		    read_buf + 4,
5876b384f39SPeter Avalos 		    state->out_block + prefix64k, (int)compressed_size,
5886b384f39SPeter Avalos 		    state->flags.block_maximum_size);
5896b384f39SPeter Avalos #endif
5906b384f39SPeter Avalos 	}
5916b384f39SPeter Avalos 
592e95abc47Szrj 	/* Check if an error occurred in the decompression process. */
5936b384f39SPeter Avalos 	if (uncompressed_size < 0) {
5946b384f39SPeter Avalos 		archive_set_error(&(self->archive->archive),
5956b384f39SPeter Avalos 		    ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
5966b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
5976b384f39SPeter Avalos 	}
5986b384f39SPeter Avalos 
5996b384f39SPeter Avalos 	state->unconsumed = 4 + compressed_size + checksum_size;
6006b384f39SPeter Avalos 	*p = state->out_block + prefix64k;
6016b384f39SPeter Avalos 	state->decoded_size = uncompressed_size;
6026b384f39SPeter Avalos 	return uncompressed_size;
6036b384f39SPeter Avalos 
6046b384f39SPeter Avalos malformed_error:
6056b384f39SPeter Avalos 	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
6066b384f39SPeter Avalos 	    "malformed lz4 data");
6076b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
6086b384f39SPeter Avalos truncated_error:
6096b384f39SPeter Avalos 	archive_set_error(&self->archive->archive, ARCHIVE_ERRNO_MISC,
6106b384f39SPeter Avalos 	    "truncated lz4 input");
6116b384f39SPeter Avalos 	return (ARCHIVE_FATAL);
6126b384f39SPeter Avalos }
6136b384f39SPeter Avalos 
6146b384f39SPeter Avalos static ssize_t
lz4_filter_read_default_stream(struct archive_read_filter * self,const void ** p)6156b384f39SPeter Avalos lz4_filter_read_default_stream(struct archive_read_filter *self, const void **p)
6166b384f39SPeter Avalos {
6176b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
6186b384f39SPeter Avalos 	const char *read_buf;
6196b384f39SPeter Avalos 	ssize_t bytes_remaining;
6206b384f39SPeter Avalos 	ssize_t ret;
6216b384f39SPeter Avalos 
6226b384f39SPeter Avalos 	if (state->stage == SELECT_STREAM) {
6236b384f39SPeter Avalos 		state->stage = READ_DEFAULT_STREAM;
624e95abc47Szrj 		/* First, read a descriptor. */
6256b384f39SPeter Avalos 		if((ret = lz4_filter_read_descriptor(self)) != ARCHIVE_OK)
6266b384f39SPeter Avalos 			return (ret);
6276b384f39SPeter Avalos 		state->stage = READ_DEFAULT_BLOCK;
6286b384f39SPeter Avalos 	}
6296b384f39SPeter Avalos 	/* Decompress a block. */
6306b384f39SPeter Avalos 	ret = lz4_filter_read_data_block(self, p);
6316b384f39SPeter Avalos 
6326b384f39SPeter Avalos 	/* If the end of block is detected, change the filter status
6336b384f39SPeter Avalos 	   to read next stream. */
6346b384f39SPeter Avalos 	if (ret == 0 && *p == NULL)
6356b384f39SPeter Avalos 		state->stage = SELECT_STREAM;
6366b384f39SPeter Avalos 
637085658deSDaniel Fojt 	/* Optional processing, checking a stream sum. */
6386b384f39SPeter Avalos 	if (state->flags.stream_checksum) {
6396b384f39SPeter Avalos 		if (state->stage == SELECT_STREAM) {
6406b384f39SPeter Avalos 			unsigned int checksum;
6416b384f39SPeter Avalos 			unsigned int checksum_stream;
6426b384f39SPeter Avalos 			read_buf = __archive_read_filter_ahead(self->upstream,
6436b384f39SPeter Avalos 			    4, &bytes_remaining);
6446b384f39SPeter Avalos 			if (read_buf == NULL) {
6456b384f39SPeter Avalos 				archive_set_error(&self->archive->archive,
6466b384f39SPeter Avalos 				    ARCHIVE_ERRNO_MISC, "truncated lz4 input");
6476b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
6486b384f39SPeter Avalos 			}
6496b384f39SPeter Avalos 			checksum = archive_le32dec(read_buf);
6506b384f39SPeter Avalos 			__archive_read_filter_consume(self->upstream, 4);
6516b384f39SPeter Avalos 			checksum_stream = __archive_xxhash.XXH32_digest(
6526b384f39SPeter Avalos 			    state->xxh32_state);
6536b384f39SPeter Avalos 			state->xxh32_state = NULL;
6546b384f39SPeter Avalos 			if (checksum != checksum_stream) {
6556b384f39SPeter Avalos 				archive_set_error(&self->archive->archive,
6566b384f39SPeter Avalos 				    ARCHIVE_ERRNO_MISC,
657085658deSDaniel Fojt 				    "lz4 stream checksum error");
6586b384f39SPeter Avalos 				return (ARCHIVE_FATAL);
6596b384f39SPeter Avalos 			}
6606b384f39SPeter Avalos 		} else if (ret > 0)
6616b384f39SPeter Avalos 			__archive_xxhash.XXH32_update(state->xxh32_state,
6626b384f39SPeter Avalos 			    *p, (int)ret);
6636b384f39SPeter Avalos 	}
6646b384f39SPeter Avalos 	return (ret);
6656b384f39SPeter Avalos }
6666b384f39SPeter Avalos 
6676b384f39SPeter Avalos static ssize_t
lz4_filter_read_legacy_stream(struct archive_read_filter * self,const void ** p)6686b384f39SPeter Avalos lz4_filter_read_legacy_stream(struct archive_read_filter *self, const void **p)
6696b384f39SPeter Avalos {
6706b384f39SPeter Avalos 	struct private_data *state = (struct private_data *)self->data;
671085658deSDaniel Fojt 	uint32_t compressed;
6726b384f39SPeter Avalos 	const char *read_buf;
6736b384f39SPeter Avalos 	ssize_t ret;
6746b384f39SPeter Avalos 
6756b384f39SPeter Avalos 	*p = NULL;
6766b384f39SPeter Avalos 	ret = lz4_allocate_out_block_for_legacy(self);
6776b384f39SPeter Avalos 	if (ret != ARCHIVE_OK)
6786b384f39SPeter Avalos 		return ret;
6796b384f39SPeter Avalos 
6806b384f39SPeter Avalos 	/* Make sure we have 4 bytes for a block size. */
6816b384f39SPeter Avalos 	read_buf = __archive_read_filter_ahead(self->upstream, 4, NULL);
6826b384f39SPeter Avalos 	if (read_buf == NULL) {
6836b384f39SPeter Avalos 		if (state->stage == SELECT_STREAM) {
6846b384f39SPeter Avalos 			state->stage = READ_LEGACY_STREAM;
6856b384f39SPeter Avalos 			archive_set_error(&self->archive->archive,
6866b384f39SPeter Avalos 			    ARCHIVE_ERRNO_MISC,
6876b384f39SPeter Avalos 			    "truncated lz4 input");
6886b384f39SPeter Avalos 			return (ARCHIVE_FATAL);
6896b384f39SPeter Avalos 		}
6906b384f39SPeter Avalos 		state->stage = SELECT_STREAM;
6916b384f39SPeter Avalos 		return 0;
6926b384f39SPeter Avalos 	}
6936b384f39SPeter Avalos 	state->stage = READ_LEGACY_BLOCK;
6946b384f39SPeter Avalos 	compressed = archive_le32dec(read_buf);
6956b384f39SPeter Avalos 	if (compressed > LZ4_COMPRESSBOUND(LEGACY_BLOCK_SIZE)) {
6966b384f39SPeter Avalos 		state->stage = SELECT_STREAM;
6976b384f39SPeter Avalos 		return 0;
6986b384f39SPeter Avalos 	}
6996b384f39SPeter Avalos 
7006b384f39SPeter Avalos 	/* Make sure we have a whole block. */
7016b384f39SPeter Avalos 	read_buf = __archive_read_filter_ahead(self->upstream,
7026b384f39SPeter Avalos 	    4 + compressed, NULL);
703e95abc47Szrj 	if (read_buf == NULL) {
704e95abc47Szrj 		archive_set_error(&(self->archive->archive),
705e95abc47Szrj 		    ARCHIVE_ERRNO_MISC, "truncated lz4 input");
706e95abc47Szrj 		return (ARCHIVE_FATAL);
707e95abc47Szrj 	}
7086b384f39SPeter Avalos 	ret = LZ4_decompress_safe(read_buf + 4, state->out_block,
7096b384f39SPeter Avalos 	    compressed, (int)state->out_block_size);
7106b384f39SPeter Avalos 	if (ret < 0) {
7116b384f39SPeter Avalos 		archive_set_error(&(self->archive->archive),
7126b384f39SPeter Avalos 		    ARCHIVE_ERRNO_MISC, "lz4 decompression failed");
7136b384f39SPeter Avalos 		return (ARCHIVE_FATAL);
7146b384f39SPeter Avalos 	}
7156b384f39SPeter Avalos 	*p = state->out_block;
7166b384f39SPeter Avalos 	state->unconsumed = 4 + compressed;
7176b384f39SPeter Avalos 	return ret;
7186b384f39SPeter Avalos }
7196b384f39SPeter Avalos 
7206b384f39SPeter Avalos /*
7216b384f39SPeter Avalos  * Clean up the decompressor.
7226b384f39SPeter Avalos  */
7236b384f39SPeter Avalos static int
lz4_filter_close(struct archive_read_filter * self)7246b384f39SPeter Avalos lz4_filter_close(struct archive_read_filter *self)
7256b384f39SPeter Avalos {
7266b384f39SPeter Avalos 	struct private_data *state;
7276b384f39SPeter Avalos 	int ret = ARCHIVE_OK;
7286b384f39SPeter Avalos 
7296b384f39SPeter Avalos 	state = (struct private_data *)self->data;
7306b384f39SPeter Avalos 	free(state->xxh32_state);
7316b384f39SPeter Avalos 	free(state->out_block);
7326b384f39SPeter Avalos 	free(state);
7336b384f39SPeter Avalos 	return (ret);
7346b384f39SPeter Avalos }
7356b384f39SPeter Avalos 
7366b384f39SPeter Avalos #endif /* HAVE_LIBLZ4 */
737