Path: blob/master/Utilities/cmliblzma/liblzma/common/block_header_decoder.c
3153 views
// SPDX-License-Identifier: 0BSD12///////////////////////////////////////////////////////////////////////////////3//4/// \file block_header_decoder.c5/// \brief Decodes Block Header from .xz files6//7// Author: Lasse Collin8//9///////////////////////////////////////////////////////////////////////////////1011#include "common.h"12#include "check.h"131415extern LZMA_API(lzma_ret)16lzma_block_header_decode(lzma_block *block,17const lzma_allocator *allocator, const uint8_t *in)18{19// NOTE: We consider the header to be corrupt not only when the20// CRC32 doesn't match, but also when variable-length integers21// are invalid or over 63 bits, or if the header is too small22// to contain the claimed information.2324// Catch unexpected NULL pointers.25if (block == NULL || block->filters == NULL || in == NULL)26return LZMA_PROG_ERROR;2728// Initialize the filter options array. This way the caller can29// safely free() the options even if an error occurs in this function.30for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {31block->filters[i].id = LZMA_VLI_UNKNOWN;32block->filters[i].options = NULL;33}3435// Versions 0 and 1 are supported. If a newer version was specified,36// we need to downgrade it.37if (block->version > 1)38block->version = 1;3940// This isn't a Block Header option, but since the decompressor will41// read it if version >= 1, it's better to initialize it here than42// to expect the caller to do it since in almost all cases this43// should be false.44block->ignore_check = false;4546// Validate Block Header Size and Check type. The caller must have47// already set these, so it is a programming error if this test fails.48if (lzma_block_header_size_decode(in[0]) != block->header_size49|| (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)50return LZMA_PROG_ERROR;5152// Exclude the CRC32 field.53const size_t in_size = block->header_size - 4;5455// Verify CRC3256if (lzma_crc32(in, in_size, 0) != read32le(in + in_size)) {57#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION58return LZMA_DATA_ERROR;59#endif60}6162// Check for unsupported flags.63if (in[1] & 0x3C)64return LZMA_OPTIONS_ERROR;6566// Start after the Block Header Size and Block Flags fields.67size_t in_pos = 2;6869// Compressed Size70if (in[1] & 0x40) {71return_if_error(lzma_vli_decode(&block->compressed_size,72NULL, in, &in_pos, in_size));7374// Validate Compressed Size. This checks that it isn't zero75// and that the total size of the Block is a valid VLI.76if (lzma_block_unpadded_size(block) == 0)77return LZMA_DATA_ERROR;78} else {79block->compressed_size = LZMA_VLI_UNKNOWN;80}8182// Uncompressed Size83if (in[1] & 0x80)84return_if_error(lzma_vli_decode(&block->uncompressed_size,85NULL, in, &in_pos, in_size));86else87block->uncompressed_size = LZMA_VLI_UNKNOWN;8889// Filter Flags90const size_t filter_count = (in[1] & 3U) + 1;91for (size_t i = 0; i < filter_count; ++i) {92const lzma_ret ret = lzma_filter_flags_decode(93&block->filters[i], allocator,94in, &in_pos, in_size);95if (ret != LZMA_OK) {96lzma_filters_free(block->filters, allocator);97return ret;98}99}100101// Padding102while (in_pos < in_size) {103if (in[in_pos++] != 0x00) {104lzma_filters_free(block->filters, allocator);105106// Possibly some new field present so use107// LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.108return LZMA_OPTIONS_ERROR;109}110}111112return LZMA_OK;113}114115116