xref: /freebsd/contrib/xz/src/liblzma/common/block_util.c (revision a8675d927bbde29d5a4dc6efddf2f0dc6d6d6983)
181ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
281ad8388SMartin Matuska //
3*a8675d92SXin LI /// \file       block_util.c
481ad8388SMartin Matuska /// \brief      Utility functions to handle lzma_block
581ad8388SMartin Matuska //
681ad8388SMartin Matuska //  Author:     Lasse Collin
781ad8388SMartin Matuska //
881ad8388SMartin Matuska //  This file has been put into the public domain.
981ad8388SMartin Matuska //  You can do whatever you want with this file.
1081ad8388SMartin Matuska //
1181ad8388SMartin Matuska ///////////////////////////////////////////////////////////////////////////////
1281ad8388SMartin Matuska 
1381ad8388SMartin Matuska #include "common.h"
1481ad8388SMartin Matuska #include "index.h"
1581ad8388SMartin Matuska 
1681ad8388SMartin Matuska 
1781ad8388SMartin Matuska extern LZMA_API(lzma_ret)
18e0f0e66dSMartin Matuska lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
1981ad8388SMartin Matuska {
2081ad8388SMartin Matuska 	// Validate everything but Uncompressed Size and filters.
2181ad8388SMartin Matuska 	if (lzma_block_unpadded_size(block) == 0)
2281ad8388SMartin Matuska 		return LZMA_PROG_ERROR;
2381ad8388SMartin Matuska 
2481ad8388SMartin Matuska 	const uint32_t container_size = block->header_size
2581ad8388SMartin Matuska 			+ lzma_check_size(block->check);
2681ad8388SMartin Matuska 
2781ad8388SMartin Matuska 	// Validate that Compressed Size will be greater than zero.
28e0f0e66dSMartin Matuska 	if (unpadded_size <= container_size)
2981ad8388SMartin Matuska 		return LZMA_DATA_ERROR;
3081ad8388SMartin Matuska 
3181ad8388SMartin Matuska 	// Calculate what Compressed Size is supposed to be.
3281ad8388SMartin Matuska 	// If Compressed Size was present in Block Header,
3381ad8388SMartin Matuska 	// compare that the new value matches it.
34e0f0e66dSMartin Matuska 	const lzma_vli compressed_size = unpadded_size - container_size;
3581ad8388SMartin Matuska 	if (block->compressed_size != LZMA_VLI_UNKNOWN
3681ad8388SMartin Matuska 			&& block->compressed_size != compressed_size)
3781ad8388SMartin Matuska 		return LZMA_DATA_ERROR;
3881ad8388SMartin Matuska 
3981ad8388SMartin Matuska 	block->compressed_size = compressed_size;
4081ad8388SMartin Matuska 
4181ad8388SMartin Matuska 	return LZMA_OK;
4281ad8388SMartin Matuska }
4381ad8388SMartin Matuska 
4481ad8388SMartin Matuska 
4581ad8388SMartin Matuska extern LZMA_API(lzma_vli)
4681ad8388SMartin Matuska lzma_block_unpadded_size(const lzma_block *block)
4781ad8388SMartin Matuska {
4881ad8388SMartin Matuska 	// Validate the values that we are interested in i.e. all but
4981ad8388SMartin Matuska 	// Uncompressed Size and the filters.
5081ad8388SMartin Matuska 	//
5181ad8388SMartin Matuska 	// NOTE: This function is used for validation too, so it is
5281ad8388SMartin Matuska 	// essential that these checks are always done even if
5381ad8388SMartin Matuska 	// Compressed Size is unknown.
5453200025SRui Paulo 	if (block == NULL || block->version > 1
5581ad8388SMartin Matuska 			|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
5681ad8388SMartin Matuska 			|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
5781ad8388SMartin Matuska 			|| (block->header_size & 3)
5881ad8388SMartin Matuska 			|| !lzma_vli_is_valid(block->compressed_size)
5981ad8388SMartin Matuska 			|| block->compressed_size == 0
6081ad8388SMartin Matuska 			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
6181ad8388SMartin Matuska 		return 0;
6281ad8388SMartin Matuska 
6381ad8388SMartin Matuska 	// If Compressed Size is unknown, return that we cannot know
6481ad8388SMartin Matuska 	// size of the Block either.
6581ad8388SMartin Matuska 	if (block->compressed_size == LZMA_VLI_UNKNOWN)
6681ad8388SMartin Matuska 		return LZMA_VLI_UNKNOWN;
6781ad8388SMartin Matuska 
6881ad8388SMartin Matuska 	// Calculate Unpadded Size and validate it.
6981ad8388SMartin Matuska 	const lzma_vli unpadded_size = block->compressed_size
7081ad8388SMartin Matuska 				+ block->header_size
7181ad8388SMartin Matuska 				+ lzma_check_size(block->check);
7281ad8388SMartin Matuska 
7381ad8388SMartin Matuska 	assert(unpadded_size >= UNPADDED_SIZE_MIN);
7481ad8388SMartin Matuska 	if (unpadded_size > UNPADDED_SIZE_MAX)
7581ad8388SMartin Matuska 		return 0;
7681ad8388SMartin Matuska 
7781ad8388SMartin Matuska 	return unpadded_size;
7881ad8388SMartin Matuska }
7981ad8388SMartin Matuska 
8081ad8388SMartin Matuska 
8181ad8388SMartin Matuska extern LZMA_API(lzma_vli)
8281ad8388SMartin Matuska lzma_block_total_size(const lzma_block *block)
8381ad8388SMartin Matuska {
8481ad8388SMartin Matuska 	lzma_vli unpadded_size = lzma_block_unpadded_size(block);
8581ad8388SMartin Matuska 
8681ad8388SMartin Matuska 	if (unpadded_size != LZMA_VLI_UNKNOWN)
8781ad8388SMartin Matuska 		unpadded_size = vli_ceil4(unpadded_size);
8881ad8388SMartin Matuska 
8981ad8388SMartin Matuska 	return unpadded_size;
9081ad8388SMartin Matuska }
91