1*3b35e7eeSXin LI // SPDX-License-Identifier: 0BSD 2*3b35e7eeSXin LI 381ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 481ad8388SMartin Matuska // 581ad8388SMartin Matuska /// \file stream_flags_decoder.c 681ad8388SMartin Matuska /// \brief Decodes Stream Header and Stream Footer from .xz files 781ad8388SMartin Matuska // 881ad8388SMartin Matuska // Author: Lasse Collin 981ad8388SMartin Matuska // 1081ad8388SMartin Matuska /////////////////////////////////////////////////////////////////////////////// 1181ad8388SMartin Matuska 1281ad8388SMartin Matuska #include "stream_flags_common.h" 1381ad8388SMartin Matuska 1481ad8388SMartin Matuska 1581ad8388SMartin Matuska static bool 1681ad8388SMartin Matuska stream_flags_decode(lzma_stream_flags *options, const uint8_t *in) 1781ad8388SMartin Matuska { 1881ad8388SMartin Matuska // Reserved bits must be unset. 1981ad8388SMartin Matuska if (in[0] != 0x00 || (in[1] & 0xF0)) 2081ad8388SMartin Matuska return true; 2181ad8388SMartin Matuska 2281ad8388SMartin Matuska options->version = 0; 2381ad8388SMartin Matuska options->check = in[1] & 0x0F; 2481ad8388SMartin Matuska 2581ad8388SMartin Matuska return false; 2681ad8388SMartin Matuska } 2781ad8388SMartin Matuska 2881ad8388SMartin Matuska 2981ad8388SMartin Matuska extern LZMA_API(lzma_ret) 3081ad8388SMartin Matuska lzma_stream_header_decode(lzma_stream_flags *options, const uint8_t *in) 3181ad8388SMartin Matuska { 3281ad8388SMartin Matuska // Magic 3381ad8388SMartin Matuska if (memcmp(in, lzma_header_magic, sizeof(lzma_header_magic)) != 0) 3481ad8388SMartin Matuska return LZMA_FORMAT_ERROR; 3581ad8388SMartin Matuska 3681ad8388SMartin Matuska // Verify the CRC32 so we can distinguish between corrupt 3781ad8388SMartin Matuska // and unsupported files. 3881ad8388SMartin Matuska const uint32_t crc = lzma_crc32(in + sizeof(lzma_header_magic), 3981ad8388SMartin Matuska LZMA_STREAM_FLAGS_SIZE, 0); 40a8675d92SXin LI if (crc != read32le(in + sizeof(lzma_header_magic) 4173ed8e77SXin LI + LZMA_STREAM_FLAGS_SIZE)) { 4273ed8e77SXin LI #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 4381ad8388SMartin Matuska return LZMA_DATA_ERROR; 4473ed8e77SXin LI #endif 4573ed8e77SXin LI } 4681ad8388SMartin Matuska 4781ad8388SMartin Matuska // Stream Flags 4881ad8388SMartin Matuska if (stream_flags_decode(options, in + sizeof(lzma_header_magic))) 4981ad8388SMartin Matuska return LZMA_OPTIONS_ERROR; 5081ad8388SMartin Matuska 5181ad8388SMartin Matuska // Set Backward Size to indicate unknown value. That way 5281ad8388SMartin Matuska // lzma_stream_flags_compare() can be used to compare Stream Header 5381ad8388SMartin Matuska // and Stream Footer while keeping it useful also for comparing 5481ad8388SMartin Matuska // two Stream Footers. 5581ad8388SMartin Matuska options->backward_size = LZMA_VLI_UNKNOWN; 5681ad8388SMartin Matuska 5781ad8388SMartin Matuska return LZMA_OK; 5881ad8388SMartin Matuska } 5981ad8388SMartin Matuska 6081ad8388SMartin Matuska 6181ad8388SMartin Matuska extern LZMA_API(lzma_ret) 6281ad8388SMartin Matuska lzma_stream_footer_decode(lzma_stream_flags *options, const uint8_t *in) 6381ad8388SMartin Matuska { 6481ad8388SMartin Matuska // Magic 6581ad8388SMartin Matuska if (memcmp(in + sizeof(uint32_t) * 2 + LZMA_STREAM_FLAGS_SIZE, 6681ad8388SMartin Matuska lzma_footer_magic, sizeof(lzma_footer_magic)) != 0) 6781ad8388SMartin Matuska return LZMA_FORMAT_ERROR; 6881ad8388SMartin Matuska 6981ad8388SMartin Matuska // CRC32 7081ad8388SMartin Matuska const uint32_t crc = lzma_crc32(in + sizeof(uint32_t), 7181ad8388SMartin Matuska sizeof(uint32_t) + LZMA_STREAM_FLAGS_SIZE, 0); 7273ed8e77SXin LI if (crc != read32le(in)) { 7373ed8e77SXin LI #ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION 7481ad8388SMartin Matuska return LZMA_DATA_ERROR; 7573ed8e77SXin LI #endif 7673ed8e77SXin LI } 7781ad8388SMartin Matuska 7881ad8388SMartin Matuska // Stream Flags 7981ad8388SMartin Matuska if (stream_flags_decode(options, in + sizeof(uint32_t) * 2)) 8081ad8388SMartin Matuska return LZMA_OPTIONS_ERROR; 8181ad8388SMartin Matuska 8281ad8388SMartin Matuska // Backward Size 83a8675d92SXin LI options->backward_size = read32le(in + sizeof(uint32_t)); 8481ad8388SMartin Matuska options->backward_size = (options->backward_size + 1) * 4; 8581ad8388SMartin Matuska 8681ad8388SMartin Matuska return LZMA_OK; 8781ad8388SMartin Matuska } 88