1/////////////////////////////////////////////////////////////////////////////// 2// 3/// \file test_block_header.c 4/// \brief Tests Block Header coders 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 "tests.h" 14 15 16static uint8_t buf[LZMA_BLOCK_HEADER_SIZE_MAX]; 17static lzma_block known_options; 18static lzma_block decoded_options; 19 20static lzma_options_lzma opt_lzma; 21 22static lzma_filter filters_none[1] = { 23 { 24 .id = LZMA_VLI_UNKNOWN, 25 }, 26}; 27 28 29static lzma_filter filters_one[2] = { 30 { 31 .id = LZMA_FILTER_LZMA2, 32 .options = &opt_lzma, 33 }, { 34 .id = LZMA_VLI_UNKNOWN, 35 } 36}; 37 38 39static lzma_filter filters_four[5] = { 40 { 41 .id = LZMA_FILTER_X86, 42 .options = NULL, 43 }, { 44 .id = LZMA_FILTER_X86, 45 .options = NULL, 46 }, { 47 .id = LZMA_FILTER_X86, 48 .options = NULL, 49 }, { 50 .id = LZMA_FILTER_LZMA2, 51 .options = &opt_lzma, 52 }, { 53 .id = LZMA_VLI_UNKNOWN, 54 } 55}; 56 57 58static lzma_filter filters_five[6] = { 59 { 60 .id = LZMA_FILTER_X86, 61 .options = NULL, 62 }, { 63 .id = LZMA_FILTER_X86, 64 .options = NULL, 65 }, { 66 .id = LZMA_FILTER_X86, 67 .options = NULL, 68 }, { 69 .id = LZMA_FILTER_X86, 70 .options = NULL, 71 }, { 72 .id = LZMA_FILTER_LZMA2, 73 .options = &opt_lzma, 74 }, { 75 .id = LZMA_VLI_UNKNOWN, 76 } 77}; 78 79 80static void 81code(void) 82{ 83 expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK); 84 85 lzma_filter filters[LZMA_FILTERS_MAX + 1]; 86 memcrap(filters, sizeof(filters)); 87 memcrap(&decoded_options, sizeof(decoded_options)); 88 89 decoded_options.header_size = known_options.header_size; 90 decoded_options.check = known_options.check; 91 decoded_options.filters = filters; 92 expect(lzma_block_header_decode(&decoded_options, NULL, buf) 93 == LZMA_OK); 94 95 expect(known_options.compressed_size 96 == decoded_options.compressed_size); 97 expect(known_options.uncompressed_size 98 == decoded_options.uncompressed_size); 99 100 for (size_t i = 0; known_options.filters[i].id 101 != LZMA_VLI_UNKNOWN; ++i) 102 expect(known_options.filters[i].id == filters[i].id); 103 104 for (size_t i = 0; i < LZMA_FILTERS_MAX; ++i) 105 free(decoded_options.filters[i].options); 106} 107 108 109static void 110test1(void) 111{ 112 known_options = (lzma_block){ 113 .check = LZMA_CHECK_NONE, 114 .compressed_size = LZMA_VLI_UNKNOWN, 115 .uncompressed_size = LZMA_VLI_UNKNOWN, 116 .filters = NULL, 117 }; 118 119 expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); 120 121 known_options.filters = filters_none; 122 expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); 123 124 known_options.filters = filters_five; 125 expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); 126 127 known_options.filters = filters_one; 128 expect(lzma_block_header_size(&known_options) == LZMA_OK); 129 130 known_options.check = 999; // Some invalid value, which gets ignored. 131 expect(lzma_block_header_size(&known_options) == LZMA_OK); 132 133 known_options.compressed_size = 5; 134 expect(lzma_block_header_size(&known_options) == LZMA_OK); 135 136 known_options.compressed_size = 0; // Cannot be zero. 137 expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); 138 139 // LZMA_VLI_MAX is too big to keep the total size of the Block 140 // a valid VLI, but lzma_block_header_size() is not meant 141 // to validate it. (lzma_block_header_encode() must validate it.) 142 known_options.compressed_size = LZMA_VLI_MAX; 143 expect(lzma_block_header_size(&known_options) == LZMA_OK); 144 145 known_options.compressed_size = LZMA_VLI_UNKNOWN; 146 known_options.uncompressed_size = 0; 147 expect(lzma_block_header_size(&known_options) == LZMA_OK); 148 149 known_options.uncompressed_size = LZMA_VLI_MAX + 1; 150 expect(lzma_block_header_size(&known_options) == LZMA_PROG_ERROR); 151} 152 153 154static void 155test2(void) 156{ 157 known_options = (lzma_block){ 158 .check = LZMA_CHECK_CRC32, 159 .compressed_size = LZMA_VLI_UNKNOWN, 160 .uncompressed_size = LZMA_VLI_UNKNOWN, 161 .filters = filters_four, 162 }; 163 164 expect(lzma_block_header_size(&known_options) == LZMA_OK); 165 code(); 166 167 known_options.compressed_size = 123456; 168 known_options.uncompressed_size = 234567; 169 expect(lzma_block_header_size(&known_options) == LZMA_OK); 170 code(); 171 172 // We can make the sizes smaller while keeping the header size 173 // the same. 174 known_options.compressed_size = 12; 175 known_options.uncompressed_size = 23; 176 code(); 177} 178 179 180static void 181test3(void) 182{ 183 known_options = (lzma_block){ 184 .check = LZMA_CHECK_CRC32, 185 .compressed_size = LZMA_VLI_UNKNOWN, 186 .uncompressed_size = LZMA_VLI_UNKNOWN, 187 .filters = filters_one, 188 }; 189 190 expect(lzma_block_header_size(&known_options) == LZMA_OK); 191 known_options.header_size += 4; 192 expect(lzma_block_header_encode(&known_options, buf) == LZMA_OK); 193 194 lzma_filter filters[LZMA_FILTERS_MAX + 1]; 195 decoded_options.header_size = known_options.header_size; 196 decoded_options.check = known_options.check; 197 decoded_options.filters = filters; 198 199 // Wrong size 200 ++buf[0]; 201 expect(lzma_block_header_decode(&decoded_options, NULL, buf) 202 == LZMA_PROG_ERROR); 203 --buf[0]; 204 205 // Wrong CRC32 206 buf[known_options.header_size - 1] ^= 1; 207 expect(lzma_block_header_decode(&decoded_options, NULL, buf) 208 == LZMA_DATA_ERROR); 209 buf[known_options.header_size - 1] ^= 1; 210 211 // Unsupported filter 212 // NOTE: This may need updating when new IDs become supported. 213 buf[2] ^= 0x1F; 214 unaligned_write32le(buf + known_options.header_size - 4, 215 lzma_crc32(buf, known_options.header_size - 4, 0)); 216 expect(lzma_block_header_decode(&decoded_options, NULL, buf) 217 == LZMA_OPTIONS_ERROR); 218 buf[2] ^= 0x1F; 219 220 // Non-nul Padding 221 buf[known_options.header_size - 4 - 1] ^= 1; 222 unaligned_write32le(buf + known_options.header_size - 4, 223 lzma_crc32(buf, known_options.header_size - 4, 0)); 224 expect(lzma_block_header_decode(&decoded_options, NULL, buf) 225 == LZMA_OPTIONS_ERROR); 226 buf[known_options.header_size - 4 - 1] ^= 1; 227} 228 229 230int 231main(void) 232{ 233 succeed(lzma_lzma_preset(&opt_lzma, 1)); 234 235 test1(); 236 test2(); 237 test3(); 238 239 return 0; 240} 241