1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 // vim: expandtab:ts=8:sw=4:softtabstop=4:
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file       test_stream_flags.c
6 /// \brief      Tests Stream Header and Stream Footer coders
7 //
8 //  Author:     Lasse Collin
9 //
10 //  This file has been put into the public domain.
11 //  You can do whatever you want with this file.
12 //
13 ///////////////////////////////////////////////////////////////////////////////
14 
15 #include "tests.h"
16 
17 
18 static lzma_stream_flags known_flags;
19 static lzma_stream_flags decoded_flags;
20 static uint8_t buffer[LZMA_STREAM_HEADER_SIZE];
21 
22 
23 static bool
validate(void)24 validate(void)
25 {
26 	// TODO: This could require the specific error type as an argument.
27 	// We could also test that lzma_stream_flags_compare() gives
28 	// the correct return values in different situations.
29 	return lzma_stream_flags_compare(&known_flags, &decoded_flags)
30 			!= LZMA_OK;
31 }
32 
33 
34 static bool
test_header_decoder(lzma_ret expected_ret)35 test_header_decoder(lzma_ret expected_ret)
36 {
37 	memcrap(&decoded_flags, sizeof(decoded_flags));
38 
39 	if (lzma_stream_header_decode(&decoded_flags, buffer) != expected_ret)
40 		return true;
41 
42 	if (expected_ret != LZMA_OK)
43 		return false;
44 
45 	// Header doesn't have Backward Size, so make
46 	// lzma_stream_flags_compare() ignore it.
47 	decoded_flags.backward_size = LZMA_VLI_UNKNOWN;
48 	return validate();
49 }
50 
51 
52 static void
test_header(void)53 test_header(void)
54 {
55 	memcrap(buffer, sizeof(buffer));
56 	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
57 	succeed(test_header_decoder(LZMA_OK));
58 }
59 
60 
61 static bool
test_footer_decoder(lzma_ret expected_ret)62 test_footer_decoder(lzma_ret expected_ret)
63 {
64 	memcrap(&decoded_flags, sizeof(decoded_flags));
65 
66 	if (lzma_stream_footer_decode(&decoded_flags, buffer) != expected_ret)
67 		return true;
68 
69 	if (expected_ret != LZMA_OK)
70 		return false;
71 
72 	return validate();
73 }
74 
75 
76 static void
test_footer(void)77 test_footer(void)
78 {
79 	memcrap(buffer, sizeof(buffer));
80 	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
81 	succeed(test_footer_decoder(LZMA_OK));
82 }
83 
84 
85 static void
test_encode_invalid(void)86 test_encode_invalid(void)
87 {
88 	known_flags.check = LZMA_CHECK_ID_MAX + 1;
89 	known_flags.backward_size = 1024;
90 
91 	expect(lzma_stream_header_encode(&known_flags, buffer)
92 			== LZMA_PROG_ERROR);
93 
94 	expect(lzma_stream_footer_encode(&known_flags, buffer)
95 			== LZMA_PROG_ERROR);
96 
97 	known_flags.check = (lzma_check)(-1);
98 
99 	expect(lzma_stream_header_encode(&known_flags, buffer)
100 			== LZMA_PROG_ERROR);
101 
102 	expect(lzma_stream_footer_encode(&known_flags, buffer)
103 			== LZMA_PROG_ERROR);
104 
105 	known_flags.check = LZMA_CHECK_NONE;
106 	known_flags.backward_size = 0;
107 
108 	// Header encoder ignores backward_size.
109 	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
110 
111 	expect(lzma_stream_footer_encode(&known_flags, buffer)
112 			== LZMA_PROG_ERROR);
113 
114 	known_flags.backward_size = LZMA_VLI_MAX;
115 
116 	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
117 
118 	expect(lzma_stream_footer_encode(&known_flags, buffer)
119 			== LZMA_PROG_ERROR);
120 }
121 
122 
123 static void
test_decode_invalid(void)124 test_decode_invalid(void)
125 {
126 	known_flags.check = LZMA_CHECK_NONE;
127 	known_flags.backward_size = 1024;
128 
129 	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
130 
131 	// Test 1 (invalid Magic Bytes)
132 	buffer[5] ^= 1;
133 	succeed(test_header_decoder(LZMA_FORMAT_ERROR));
134 	buffer[5] ^= 1;
135 
136 	// Test 2a (valid CRC32)
137 	uint32_t crc = lzma_crc32(buffer + 6, 2, 0);
138 	integer_write_32(buffer + 8, crc);
139 	succeed(test_header_decoder(LZMA_OK));
140 
141 	// Test 2b (invalid Stream Flags with valid CRC32)
142 	buffer[6] ^= 0x20;
143 	crc = lzma_crc32(buffer + 6, 2, 0);
144 	integer_write_32(buffer + 8, crc);
145 	succeed(test_header_decoder(LZMA_OPTIONS_ERROR));
146 
147 	// Test 3 (invalid CRC32)
148 	expect(lzma_stream_header_encode(&known_flags, buffer) == LZMA_OK);
149 	buffer[9] ^= 1;
150 	succeed(test_header_decoder(LZMA_DATA_ERROR));
151 
152 	// Test 4 (invalid Stream Flags with valid CRC32)
153 	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
154 	buffer[9] ^= 0x40;
155 	crc = lzma_crc32(buffer + 4, 6, 0);
156 	integer_write_32(buffer, crc);
157 	succeed(test_footer_decoder(LZMA_OPTIONS_ERROR));
158 
159 	// Test 5 (invalid Magic Bytes)
160 	expect(lzma_stream_footer_encode(&known_flags, buffer) == LZMA_OK);
161 	buffer[11] ^= 1;
162 	succeed(test_footer_decoder(LZMA_FORMAT_ERROR));
163 }
164 
165 
166 int
main(void)167 main(void)
168 {
169 	// Valid headers
170 	known_flags.backward_size = 1024;
171 	for (lzma_check check = LZMA_CHECK_NONE;
172 			check <= LZMA_CHECK_ID_MAX; ++check) {
173 		test_header();
174 		test_footer();
175 	}
176 
177 	// Invalid headers
178 	test_encode_invalid();
179 	test_decode_invalid();
180 
181 	return 0;
182 }
183