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