xref: /freebsd/contrib/xz/src/liblzma/common/block_util.c (revision 4fefe1b763573c873bf3dbf3b6f28c22de0ffada)
1 // SPDX-License-Identifier: 0BSD
2 
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file       block_util.c
6 /// \brief      Utility functions to handle lzma_block
7 //
8 //  Author:     Lasse Collin
9 //
10 ///////////////////////////////////////////////////////////////////////////////
11 
12 #include "common.h"
13 #include "index.h"
14 
15 
16 extern LZMA_API(lzma_ret)
17 lzma_block_compressed_size(lzma_block *block, lzma_vli unpadded_size)
18 {
19 	// Validate everything but Uncompressed Size and filters.
20 	if (lzma_block_unpadded_size(block) == 0)
21 		return LZMA_PROG_ERROR;
22 
23 	const uint32_t container_size = block->header_size
24 			+ lzma_check_size(block->check);
25 
26 	// Validate that Compressed Size will be greater than zero.
27 	if (unpadded_size <= container_size)
28 		return LZMA_DATA_ERROR;
29 
30 	// Calculate what Compressed Size is supposed to be.
31 	// If Compressed Size was present in Block Header,
32 	// compare that the new value matches it.
33 	const lzma_vli compressed_size = unpadded_size - container_size;
34 	if (block->compressed_size != LZMA_VLI_UNKNOWN
35 			&& block->compressed_size != compressed_size)
36 		return LZMA_DATA_ERROR;
37 
38 	block->compressed_size = compressed_size;
39 
40 	return LZMA_OK;
41 }
42 
43 
44 extern LZMA_API(lzma_vli)
45 lzma_block_unpadded_size(const lzma_block *block)
46 {
47 	// Validate the values that we are interested in i.e. all but
48 	// Uncompressed Size and the filters.
49 	//
50 	// NOTE: This function is used for validation too, so it is
51 	// essential that these checks are always done even if
52 	// Compressed Size is unknown.
53 	if (block == NULL || block->version > 1
54 			|| block->header_size < LZMA_BLOCK_HEADER_SIZE_MIN
55 			|| block->header_size > LZMA_BLOCK_HEADER_SIZE_MAX
56 			|| (block->header_size & 3)
57 			|| !lzma_vli_is_valid(block->compressed_size)
58 			|| block->compressed_size == 0
59 			|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
60 		return 0;
61 
62 	// If Compressed Size is unknown, return that we cannot know
63 	// size of the Block either.
64 	if (block->compressed_size == LZMA_VLI_UNKNOWN)
65 		return LZMA_VLI_UNKNOWN;
66 
67 	// Calculate Unpadded Size and validate it.
68 	const lzma_vli unpadded_size = block->compressed_size
69 				+ block->header_size
70 				+ lzma_check_size(block->check);
71 
72 	assert(unpadded_size >= UNPADDED_SIZE_MIN);
73 	if (unpadded_size > UNPADDED_SIZE_MAX)
74 		return 0;
75 
76 	return unpadded_size;
77 }
78 
79 
80 extern LZMA_API(lzma_vli)
81 lzma_block_total_size(const lzma_block *block)
82 {
83 	lzma_vli unpadded_size = lzma_block_unpadded_size(block);
84 
85 	if (unpadded_size != LZMA_VLI_UNKNOWN)
86 		unpadded_size = vli_ceil4(unpadded_size);
87 
88 	return unpadded_size;
89 }
90