block_header_decoder.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: 0BSD
  2. ///////////////////////////////////////////////////////////////////////////////
  3. //
  4. /// \file block_header_decoder.c
  5. /// \brief Decodes Block Header from .xz files
  6. //
  7. // Author: Lasse Collin
  8. //
  9. ///////////////////////////////////////////////////////////////////////////////
  10. #include "common.h"
  11. #include "check.h"
  12. extern LZMA_API(lzma_ret)
  13. lzma_block_header_decode(lzma_block *block,
  14. const lzma_allocator *allocator, const uint8_t *in)
  15. {
  16. // NOTE: We consider the header to be corrupt not only when the
  17. // CRC32 doesn't match, but also when variable-length integers
  18. // are invalid or over 63 bits, or if the header is too small
  19. // to contain the claimed information.
  20. // Catch unexpected NULL pointers.
  21. if (block == NULL || block->filters == NULL || in == NULL)
  22. return LZMA_PROG_ERROR;
  23. // Initialize the filter options array. This way the caller can
  24. // safely free() the options even if an error occurs in this function.
  25. for (size_t i = 0; i <= LZMA_FILTERS_MAX; ++i) {
  26. block->filters[i].id = LZMA_VLI_UNKNOWN;
  27. block->filters[i].options = NULL;
  28. }
  29. // Versions 0 and 1 are supported. If a newer version was specified,
  30. // we need to downgrade it.
  31. if (block->version > 1)
  32. block->version = 1;
  33. // This isn't a Block Header option, but since the decompressor will
  34. // read it if version >= 1, it's better to initialize it here than
  35. // to expect the caller to do it since in almost all cases this
  36. // should be false.
  37. block->ignore_check = false;
  38. // Validate Block Header Size and Check type. The caller must have
  39. // already set these, so it is a programming error if this test fails.
  40. if (lzma_block_header_size_decode(in[0]) != block->header_size
  41. || (unsigned int)(block->check) > LZMA_CHECK_ID_MAX)
  42. return LZMA_PROG_ERROR;
  43. // Exclude the CRC32 field.
  44. const size_t in_size = block->header_size - 4;
  45. // Verify CRC32
  46. if (lzma_crc32(in, in_size, 0) != read32le(in + in_size)) {
  47. #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
  48. return LZMA_DATA_ERROR;
  49. #endif
  50. }
  51. // Check for unsupported flags.
  52. if (in[1] & 0x3C)
  53. return LZMA_OPTIONS_ERROR;
  54. // Start after the Block Header Size and Block Flags fields.
  55. size_t in_pos = 2;
  56. // Compressed Size
  57. if (in[1] & 0x40) {
  58. return_if_error(lzma_vli_decode(&block->compressed_size,
  59. NULL, in, &in_pos, in_size));
  60. // Validate Compressed Size. This checks that it isn't zero
  61. // and that the total size of the Block is a valid VLI.
  62. if (lzma_block_unpadded_size(block) == 0)
  63. return LZMA_DATA_ERROR;
  64. } else {
  65. block->compressed_size = LZMA_VLI_UNKNOWN;
  66. }
  67. // Uncompressed Size
  68. if (in[1] & 0x80)
  69. return_if_error(lzma_vli_decode(&block->uncompressed_size,
  70. NULL, in, &in_pos, in_size));
  71. else
  72. block->uncompressed_size = LZMA_VLI_UNKNOWN;
  73. // Filter Flags
  74. const size_t filter_count = (in[1] & 3U) + 1;
  75. for (size_t i = 0; i < filter_count; ++i) {
  76. const lzma_ret ret = lzma_filter_flags_decode(
  77. &block->filters[i], allocator,
  78. in, &in_pos, in_size);
  79. if (ret != LZMA_OK) {
  80. lzma_filters_free(block->filters, allocator);
  81. return ret;
  82. }
  83. }
  84. // Padding
  85. while (in_pos < in_size) {
  86. if (in[in_pos++] != 0x00) {
  87. lzma_filters_free(block->filters, allocator);
  88. // Possibly some new field present so use
  89. // LZMA_OPTIONS_ERROR instead of LZMA_DATA_ERROR.
  90. return LZMA_OPTIONS_ERROR;
  91. }
  92. }
  93. return LZMA_OK;
  94. }