xref: /freebsd/contrib/xz/src/liblzma/common/stream_flags_decoder.c (revision 3b35e7ee8de9b0260149a2b77e87a2b9c7a36244)
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