Exemple #1
0
static int isal_deflate_int_stateless(struct isal_zstream *stream, uint8_t * next_in,
				      const uint32_t avail_in)
{
	uint32_t crc32 = 0;
	uint32_t repeated_char_length;

#ifndef DEFLATE
	if (write_gzip_header_stateless(stream))
		return STATELESS_OVERFLOW;
#endif

	if (avail_in >= 8
	    && (*(uint64_t *) stream->next_in == 0
		|| *(uint64_t *) stream->next_in == ~(uint64_t) 0))
		repeated_char_length =
		    detect_repeated_char_length(stream->next_in, stream->avail_in);
	else
		repeated_char_length = 0;

	if (stream->avail_in == repeated_char_length) {
		if (write_constant_compressed_stateless(stream,
							stream->next_in[0],
							repeated_char_length, 1) != COMP_OK)
			return STATELESS_OVERFLOW;

#ifndef DEFLATE
		crc32 = crc32_gzip(0x0, next_in, avail_in);
#endif

		/* write_trailer_stateless is required because if flushes out the last of the output */
		if (write_trailer_stateless(stream, avail_in, crc32) != COMP_OK)
			return STATELESS_OVERFLOW;
		return COMP_OK;

	} else if (repeated_char_length >= MIN_REPEAT_LEN) {
		if (write_constant_compressed_stateless
		    (stream, stream->next_in[0], repeated_char_length, 0) != COMP_OK)
			return STATELESS_OVERFLOW;
	}

	if (write_deflate_header_unaligned_stateless(stream) != COMP_OK)
		return STATELESS_OVERFLOW;
	if (stream->avail_out < 8)
		return STATELESS_OVERFLOW;

	isal_deflate_body_stateless(stream);

	if (!stream->internal_state.has_eob)
		return STATELESS_OVERFLOW;

#ifndef DEFLATE
	crc32 = crc32_gzip(0x0, next_in, avail_in);
#endif

	if (write_trailer_stateless(stream, avail_in, crc32) != COMP_OK)
		return STATELESS_OVERFLOW;

	return COMP_OK;
}
Exemple #2
0
static void isal_deflate_pass(struct isal_zstream *stream)
{
	struct isal_zstate *state = &stream->internal_state;
	struct isal_hufftables *hufftables = stream->hufftables;
	uint8_t *start_in = stream->next_in;

	if (state->state == ZSTATE_NEW_HDR || state->state == ZSTATE_HDR) {
		if (state->count == 0)
			/* Assume the final header is being written since the header
			 * stored in hufftables is the final header. */
			state->has_eob_hdr = 1;
		write_header(stream, hufftables->deflate_hdr, hufftables->deflate_hdr_count,
			     hufftables->deflate_hdr_extra_bits, ZSTATE_BODY,
			     !stream->end_of_stream);
	}

	if (state->state == ZSTATE_BODY)
		isal_deflate_body(stream);

	if (state->state == ZSTATE_FLUSH_READ_BUFFER)
		isal_deflate_finish(stream);

	if (state->state == ZSTATE_SYNC_FLUSH)
		sync_flush(stream);

	if (state->state == ZSTATE_FLUSH_WRITE_BUFFER)
		flush_write_buffer(stream);

	if (stream->gzip_flag)
		state->crc = crc32_gzip(state->crc, start_in, stream->next_in - start_in);

	if (state->state == ZSTATE_TRL)
		write_trailer(stream);
}
Exemple #3
0
static void isal_deflate_icf_pass(struct isal_zstream *stream)
{
	uint8_t *start_in = stream->next_in;
	struct isal_zstate *state = &stream->internal_state;
	struct level_2_buf *level_buf = (struct level_2_buf *)stream->level_buf;

	do {
		if (state->state == ZSTATE_NEW_HDR)
			init_new_icf_block(stream);

		if (state->state == ZSTATE_BODY)
			isal_deflate_icf_body(stream);

		if (state->state == ZSTATE_FLUSH_READ_BUFFER)
			isal_deflate_icf_finish(stream);

		if (state->state == ZSTATE_CREATE_HDR)
			create_icf_block_hdr(stream);

		if (state->state == ZSTATE_HDR)
			/* Note that the header may be prepended by the
			 * remaining bits in the previous block, as such the
			 * toggle header flag cannot be used */
			write_header(stream, level_buf->deflate_hdr,
				     level_buf->deflate_hdr_count,
				     level_buf->deflate_hdr_extra_bits,
				     ZSTATE_FLUSH_ICF_BUFFER, 0);

		if (state->state == ZSTATE_FLUSH_ICF_BUFFER)
			flush_icf_block(stream);

	} while (state->state == ZSTATE_NEW_HDR);

	if (state->state == ZSTATE_SYNC_FLUSH)
		sync_flush(stream);

	if (state->state == ZSTATE_FLUSH_WRITE_BUFFER)
		flush_write_buffer(stream);

	if (stream->gzip_flag)
		state->crc = crc32_gzip(state->crc, start_in, stream->next_in - start_in);

	if (state->state == ZSTATE_TRL)
		write_trailer(stream);
}
Exemple #4
0
int isal_deflate_stateless(struct isal_zstream *stream)
{
	uint8_t *next_in = stream->next_in;
	const uint32_t avail_in = stream->avail_in;
	const uint32_t total_in = stream->total_in;

	uint8_t *next_out = stream->next_out;
	const uint32_t avail_out = stream->avail_out;
	const uint32_t total_out = stream->total_out;
	const uint32_t gzip_flag = stream->gzip_flag;

	uint32_t crc32 = 0;
	uint32_t stored_len;

	/* Final block has already been written */
	stream->internal_state.has_eob_hdr = 0;
	init(&stream->internal_state.bitbuf);
	stream->internal_state.state = ZSTATE_NEW_HDR;
	stream->internal_state.crc = 0;

	if (stream->flush == NO_FLUSH)
		stream->end_of_stream = 1;

	if (stream->flush != NO_FLUSH && stream->flush != FULL_FLUSH)
		return INVALID_FLUSH;

	if (stream->level != 0 && stream->level != 1)
		return ISAL_INVALID_LEVEL;

	if (avail_in == 0)
		stored_len = STORED_BLK_HDR_BZ;
	else
		stored_len =
		    STORED_BLK_HDR_BZ * ((avail_in + STORED_BLK_MAX_BZ - 1) /
					 STORED_BLK_MAX_BZ) + avail_in;

	/*
	   at least 1 byte compressed data in the case of empty dynamic block which only
	   contains the EOB
	 */

	if (stream->gzip_flag == IGZIP_GZIP)
		stored_len += gzip_hdr_bytes + gzip_trl_bytes;

	else if (stream->gzip_flag == IGZIP_GZIP_NO_HDR)
		stored_len += gzip_trl_bytes;

	/*
	   the output buffer should be no less than 8 bytes
	   while empty stored deflate block is 5 bytes only
	 */
	if (stream->avail_out < 8)
		return STATELESS_OVERFLOW;

	if (isal_deflate_int_stateless(stream) == COMP_OK)
		return COMP_OK;
	else {
		if (stream->flush == FULL_FLUSH) {
			stream->internal_state.file_start =
			    (uint8_t *) & stream->internal_state.buffer;
			reset_match_history(stream);
		}
		stream->internal_state.has_eob_hdr = 0;
	}

	if (avail_out < stored_len)
		return STATELESS_OVERFLOW;

	stream->next_in = next_in;
	stream->avail_in = avail_in;
	stream->total_in = total_in;

	stream->next_out = next_out;
	stream->avail_out = avail_out;
	stream->total_out = total_out;

	stream->gzip_flag = gzip_flag;

	if (stream->gzip_flag)
		crc32 = crc32_gzip(0x0, next_in, avail_in);

	return write_stored_block_stateless(stream, stored_len, crc32);
}
Exemple #5
0
static void write_constant_compressed_stateless(struct isal_zstream *stream,
						uint32_t repeated_length)
{
	/* Assumes repeated_length is at least 1.
	 * Assumes the input end_of_stream is either 0 or 1. */
	struct isal_zstate *state = &stream->internal_state;
	uint32_t rep_bits = ((repeated_length - 1) / 258) * 2;
	uint32_t rep_bytes = rep_bits / 8;
	uint32_t rep_extra = (repeated_length - 1) % 258;
	uint32_t bytes;
	uint32_t repeated_char = *stream->next_in;
	uint8_t *start_in = stream->next_in;

	/* Guarantee there is enough space for the header even in the worst case */
	if (stream->avail_out < HEADER_LENGTH + MAX_FIXUP_CODE_LENGTH + rep_bytes + 8)
		return;

	/* Assumes the repeated char is either 0 or 0xFF. */
	memcpy(stream->next_out, repeated_char_header[repeated_char & 1], HEADER_LENGTH);

	if (stream->avail_in == repeated_length && stream->end_of_stream > 0) {
		stream->next_out[0] |= 1;
		state->has_eob_hdr = 1;
		state->has_eob = 1;
		state->state = ZSTATE_TRL;
	} else {
		state->state = ZSTATE_NEW_HDR;
	}

	memset(stream->next_out + HEADER_LENGTH, 0, rep_bytes);
	stream->avail_out -= HEADER_LENGTH + rep_bytes;
	stream->next_out += HEADER_LENGTH + rep_bytes;
	stream->total_out += HEADER_LENGTH + rep_bytes;

	set_buf(&state->bitbuf, stream->next_out, stream->avail_out);

	/* These two lines are basically a modified version of init. */
	state->bitbuf.m_bits = 0;
	state->bitbuf.m_bit_count = rep_bits % 8;

	/* Add smaller repeat codes as necessary. Code280 can describe repeat
	 * lengths of 115-130 bits. Code10 can describe repeat lengths of 10
	 * bits. If more than 230 bits, fill code with two code280s. Else if
	 * more than 115 repeates, fill with code10s until one code280 can
	 * finish the rest of the repeats. Else, fill with code10s and
	 * literals */
	if (rep_extra > 115) {
		while (rep_extra > 130 && rep_extra < 230) {
			write_bits(&state->bitbuf, CODE_10, CODE_10_LENGTH);
			rep_extra -= 10;
		}

		if (rep_extra >= 230) {
			write_bits(&state->bitbuf,
				   CODE_280 | ((rep_extra / 2 - 115) <<
					       CODE_280_LENGTH), CODE_280_TOTAL_LENGTH);
			rep_extra -= rep_extra / 2;
		}

		write_bits(&state->bitbuf,
			   CODE_280 | ((rep_extra - 115) << CODE_280_LENGTH),
			   CODE_280_TOTAL_LENGTH);

	} else {
		while (rep_extra >= 10) {

			write_bits(&state->bitbuf, CODE_10, CODE_10_LENGTH);
			rep_extra -= 10;
		}

		for (; rep_extra > 0; rep_extra--)
			write_bits(&state->bitbuf, CODE_LIT, CODE_LIT_LENGTH);
	}

	write_bits(&state->bitbuf, END_OF_BLOCK, END_OF_BLOCK_LEN);

	stream->next_in += repeated_length;
	stream->avail_in -= repeated_length;
	stream->total_in += repeated_length;

	bytes = buffer_used(&state->bitbuf);
	stream->next_out = buffer_ptr(&state->bitbuf);
	stream->avail_out -= bytes;
	stream->total_out += bytes;

	if (stream->gzip_flag)
		state->crc = crc32_gzip(state->crc, start_in, stream->next_in - start_in);

	return;
}
LIBEXPORT enum decompress_result
gzip_decompress(struct deflate_decompressor *d,
		const void *in, size_t in_nbytes,
		void *out, size_t out_nbytes_avail,
		size_t *actual_out_nbytes_ret)
{
	const u8 *in_next = in;
	const u8 * const in_end = in_next + in_nbytes;
	u8 flg;
	size_t actual_out_nbytes;
	enum decompress_result result;

	if (in_nbytes < GZIP_MIN_OVERHEAD)
		return DECOMPRESS_BAD_DATA;

	/* ID1 */
	if (*in_next++ != GZIP_ID1)
		return DECOMPRESS_BAD_DATA;
	/* ID2 */
	if (*in_next++ != GZIP_ID2)
		return DECOMPRESS_BAD_DATA;
	/* CM */
	if (*in_next++ != GZIP_CM_DEFLATE)
		return DECOMPRESS_BAD_DATA;
	flg = *in_next++;
	/* MTIME */
	in_next += 4;
	/* XFL */
	in_next += 1;
	/* OS */
	in_next += 1;

	if (flg & GZIP_FRESERVED)
		return DECOMPRESS_BAD_DATA;

	/* Extra field */
	if (flg & GZIP_FEXTRA) {
		u16 xlen = get_unaligned_le16(in_next);
		in_next += 2;

		if (in_end - in_next < (u32)xlen + GZIP_FOOTER_SIZE)
			return DECOMPRESS_BAD_DATA;

		in_next += xlen;
	}

	/* Original file name (zero terminated) */
	if (flg & GZIP_FNAME) {
		while (*in_next++ != 0 && in_next != in_end)
			;
		if (in_end - in_next < GZIP_FOOTER_SIZE)
			return DECOMPRESS_BAD_DATA;
	}

	/* File comment (zero terminated) */
	if (flg & GZIP_FCOMMENT) {
		while (*in_next++ != 0 && in_next != in_end)
			;
		if (in_end - in_next < GZIP_FOOTER_SIZE)
			return DECOMPRESS_BAD_DATA;
	}

	/* CRC16 for gzip header */
	if (flg & GZIP_FHCRC) {
		in_next += 2;
		if (in_end - in_next < GZIP_FOOTER_SIZE)
			return DECOMPRESS_BAD_DATA;
	}

	/* Compressed data  */
	result = deflate_decompress(d, in_next,
				    in_end - GZIP_FOOTER_SIZE - in_next,
				    out, out_nbytes_avail,
				    actual_out_nbytes_ret);
	if (result != DECOMPRESS_SUCCESS)
		return result;

	if (actual_out_nbytes_ret)
		actual_out_nbytes = *actual_out_nbytes_ret;
	else
		actual_out_nbytes = out_nbytes_avail;

	in_next = in_end - GZIP_FOOTER_SIZE;

	/* CRC32 */
	if (crc32_gzip(out, actual_out_nbytes) != get_unaligned_le32(in_next))
		return DECOMPRESS_BAD_DATA;
	in_next += 4;

	/* ISIZE */
	if ((u32)actual_out_nbytes != get_unaligned_le32(in_next))
		return DECOMPRESS_BAD_DATA;

	return DECOMPRESS_SUCCESS;
}
Exemple #7
0
int isal_deflate_stateless(struct isal_zstream *stream)
{
	uint8_t *next_in = stream->next_in;
	const uint32_t avail_in = stream->avail_in;

	uint8_t *next_out = stream->next_out;
	const uint32_t avail_out = stream->avail_out;

	uint32_t crc32 = 0;
	uint32_t stored_len;
	uint32_t dyn_min_len;
	uint32_t min_len;
	uint32_t select_stored_blk = 0;

	if (avail_in == 0)
		stored_len = STORED_BLK_HDR_BZ;
	else
		stored_len =
		    STORED_BLK_HDR_BZ * ((avail_in + STORED_BLK_MAX_BZ - 1) /
					 STORED_BLK_MAX_BZ) + avail_in;

	/*
	   at least 1 byte compressed data in the case of empty dynamic block which only
	   contains the EOB
	 */

	dyn_min_len = stream->hufftables->deflate_hdr_count + 1;
#ifndef DEFLATE
	dyn_min_len += gzip_hdr_bytes + gzip_trl_bytes + 1;
	stored_len += gzip_hdr_bytes + gzip_trl_bytes;
#endif

	min_len = dyn_min_len;

	if (stored_len < dyn_min_len) {
		min_len = stored_len;
		select_stored_blk = 1;
	}

	/*
	   the output buffer should be no less than 8 bytes
	   while empty stored deflate block is 5 bytes only
	 */
	if (avail_out < min_len || stream->avail_out < 8)
		return STATELESS_OVERFLOW;

	if (!select_stored_blk) {
		if (isal_deflate_int_stateless(stream, next_in, avail_in) == COMP_OK)
			return COMP_OK;
	}
	if (avail_out < stored_len)
		return STATELESS_OVERFLOW;

	isal_deflate_init(stream);

	stream->next_in = next_in;
	stream->avail_in = avail_in;
	stream->total_in = 0;

	stream->next_out = next_out;
	stream->avail_out = avail_out;
	stream->total_out = 0;

#ifndef DEFLATE
	crc32 = crc32_gzip(0x0, next_in, avail_in);
#endif
	return write_stored_block_stateless(stream, stored_len, crc32);
}