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