1 // SPDX-License-Identifier: 0BSD 2 3 /////////////////////////////////////////////////////////////////////////////// 4 // 5 /// \file stream_flags_decoder.c 6 /// \brief Decodes Stream Header and Stream Footer from .xz files 7 // 8 // Author: Lasse Collin 9 // 10 /////////////////////////////////////////////////////////////////////////////// 11 12 #include "stream_flags_common.h" 13 14 15 static bool 16 stream_flags_decode(lzma_stream_flags *options, const uint8_t *in) 17 { 18 // Reserved bits must be unset. 19 if (in[0] != 0x00 || (in[1] & 0xF0)) 20 return true; 21 22 options->version = 0; 23 options->check = in[1] & 0x0F; 24 25 return false; 26 } 27 28 29 extern LZMA_API(lzma_ret) 30 lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in) 31 { 32 // Magic 33 if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0) 34 return LZMA_FORMAT_ERROR; 35 36 // Verify the CRC32 so we can distinguish between corrupt 37 // and unsupported files. 38 const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic), 39 LZMA_STREAM_FLAGS_SIZE, 0); 40 if (crc != read32le(in + sizeof(lzma_header_magic) 41 + LZMA_STREAM_FLAGS_SIZE)) { 42 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 43 return LZMA_DATA_ERROR; 44 #endif 45 } 46 47 // Stream Flags 48 if (stream_flags_decode(options, in + sizeof(lzma_header_magic))) 49 return LZMA_OPTIONS_ERROR; 50 51 // Set Backward Size to indicate unknown value. That way 52 // lzma_stream_flags_compare() can be used to compare Stream Header 53 // and Stream Footer while keeping it useful also for comparing 54 // two Stream Footers. 55 options->backward_size = LZMA_VLI_UNKNOWN; 56 57 return LZMA_OK; 58 } 59 60 61 extern LZMA_API(lzma_ret) 62 lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in) 63 { 64 // Magic 65 if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE, 66 lzma_footer_magic, sizeof(lzma_footer_magic)) != 0) 67 return LZMA_FORMAT_ERROR; 68 69 // CRC32 70 const uint32_t crc = lzma_crc32(in + sizeof(uint32_t), 71 sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0); 72 if (crc != read32le(in)) { 73 #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 74 return LZMA_DATA_ERROR; 75 #endif 76 } 77 78 // Stream Flags 79 if (stream_flags_decode(options, in + sizeof(uint32_t) * 2)) 80 return LZMA_OPTIONS_ERROR; 81 82 // Backward Size 83 options->backward_size = read32le(in + sizeof(uint32_t)); 84 options->backward_size = (options->backward_size + 1) * 4; 85 86 return LZMA_OK; 87 } 88