1 /*- 2 * Copyright (c) 2003-2007 Tim Kientzle 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 #include "test.h" 26 __FBSDID("$FreeBSD$"); 27 28 #ifdef HAVE_LIBZ 29 static const int libz_enabled = 1; 30 #else 31 static const int libz_enabled = 0; 32 #endif 33 34 /* Copy this function for each test file and adjust it accordingly. */ 35 static void 36 test_compat_zip_1(void) 37 { 38 char name[] = "test_compat_zip_1.zip"; 39 struct archive_entry *ae; 40 struct archive *a; 41 int r; 42 43 assert((a = archive_read_new()) != NULL); 44 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 45 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); 46 extract_reference_file(name); 47 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); 48 49 /* Read first entry. */ 50 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 51 assertEqualString("META-INF/MANIFEST.MF", archive_entry_pathname(ae)); 52 53 /* Read second entry. */ 54 r = archive_read_next_header(a, &ae); 55 if (r == ARCHIVE_FATAL && !libz_enabled) { 56 skipping("Skipping ZIP compression check: %s", 57 archive_error_string(a)); 58 goto finish; 59 } 60 assertEqualIntA(a, ARCHIVE_OK, r); 61 assertEqualString("tmp.class", archive_entry_pathname(ae)); 62 63 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 64 65 assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE); 66 assertEqualInt(archive_format(a), ARCHIVE_FORMAT_ZIP); 67 68 finish: 69 assertEqualInt(ARCHIVE_OK, archive_read_close(a)); 70 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 71 } 72 73 /* 74 * Verify that we skip junk between entries. The compat_zip_2.zip file 75 * has several bytes of junk between 'file1' and 'file2'. Such 76 * junk is routinely introduced by some Zip writers when they manipulate 77 * existing zip archives. 78 */ 79 static void 80 test_compat_zip_2(void) 81 { 82 char name[] = "test_compat_zip_2.zip"; 83 struct archive_entry *ae; 84 struct archive *a; 85 86 assert((a = archive_read_new()) != NULL); 87 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 88 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); 89 extract_reference_file(name); 90 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, name, 10240)); 91 92 /* Read first entry. */ 93 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 94 assertEqualString("file1", archive_entry_pathname(ae)); 95 96 /* Read first entry. */ 97 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 98 assertEqualString("file2", archive_entry_pathname(ae)); 99 100 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 101 assertEqualInt(ARCHIVE_OK, archive_read_close(a)); 102 assertEqualInt(ARCHIVE_OK, archive_read_free(a)); 103 } 104 105 /* 106 * Issue 185: Test a regression that got in between 2.6 and 2.7 that 107 * broke extraction of Zip entries with length-at-end. 108 */ 109 static void 110 test_compat_zip_3(void) 111 { 112 const char *refname = "test_compat_zip_3.zip"; 113 struct archive_entry *ae; 114 struct archive *a; 115 116 extract_reference_file(refname); 117 assert((a = archive_read_new()) != NULL); 118 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 119 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 120 assertEqualIntA(a, ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); 121 122 /* First entry. */ 123 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 124 assertEqualString("soapui-4.0.0/", archive_entry_pathname(ae)); 125 assertEqualInt(0, archive_entry_size(ae)); 126 assert(archive_entry_size_is_set(ae)); 127 assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); 128 129 /* Second entry. */ 130 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 131 assertEqualString("soapui-4.0.0/soapui-settings.xml", archive_entry_pathname(ae)); 132 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 133 assertEqualInt(1030, archive_entry_size(ae)); 134 assert(archive_entry_size_is_set(ae)); 135 136 /* Extract under a different name. */ 137 archive_entry_set_pathname(ae, "test_3.txt"); 138 if(libz_enabled) { 139 char *p; 140 size_t s; 141 assertEqualIntA(a, ARCHIVE_OK, archive_read_extract(a, ae, 0)); 142 /* Verify the first 12 bytes actually got written to disk correctly. */ 143 p = slurpfile(&s, "test_3.txt"); 144 assertEqualInt(s, 1030); 145 assertEqualMem(p, "<?xml versio", 12); 146 free(p); 147 } else { 148 skipping("Skipping ZIP compression check, no libz support"); 149 } 150 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 151 152 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 153 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 154 } 155 156 /** 157 * A file with leading garbage (similar to an SFX file). 158 */ 159 static void 160 test_compat_zip_4(void) 161 { 162 const char *refname = "test_compat_zip_4.zip"; 163 struct archive_entry *ae; 164 struct archive *a; 165 void *p; 166 size_t s; 167 168 extract_reference_file(refname); 169 p = slurpfile(&s, refname); 170 171 /* SFX files require seek support. */ 172 assert((a = archive_read_new()) != NULL); 173 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 174 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 175 assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 18)); 176 177 /* First entry. */ 178 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 179 assertEqualString("foo", archive_entry_pathname(ae)); 180 assertEqualInt(4, archive_entry_size(ae)); 181 assert(archive_entry_size_is_set(ae)); 182 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 183 assertEqualInt(0412, archive_entry_perm(ae)); 184 185 /* Second entry. */ 186 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 187 assertEqualString("bar", archive_entry_pathname(ae)); 188 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 189 assertEqualInt(4, archive_entry_size(ae)); 190 assert(archive_entry_size_is_set(ae)); 191 assertEqualInt(0567, archive_entry_perm(ae)); 192 193 /* Third entry. */ 194 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 195 assertEqualString("baz", archive_entry_pathname(ae)); 196 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 197 assertEqualInt(4, archive_entry_size(ae)); 198 assert(archive_entry_size_is_set(ae)); 199 assertEqualInt(0644, archive_entry_perm(ae)); 200 201 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 202 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 203 204 /* Try reading without seek support and watch it fail. */ 205 assert((a = archive_read_new()) != NULL); 206 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 207 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 208 assertEqualIntA(a, ARCHIVE_FATAL, read_open_memory(a, p, s, 3)); 209 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 210 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 211 free(p); 212 } 213 /** 214 * Issue 152: A file generated by a tool that doesn't really 215 * believe in populating local file headers at all. This 216 * is only readable with the seeking reader. 217 */ 218 static void 219 test_compat_zip_5(void) 220 { 221 const char *refname = "test_compat_zip_5.zip"; 222 struct archive_entry *ae; 223 struct archive *a; 224 void *p; 225 size_t s; 226 227 extract_reference_file(refname); 228 p = slurpfile(&s, refname); 229 230 /* Verify with seek support. 231 * Everything works correctly here. */ 232 assert((a = archive_read_new()) != NULL); 233 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 234 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 235 assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 18)); 236 237 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 238 assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae)); 239 assertEqualInt(3559, archive_entry_size(ae)); 240 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 241 assertEqualInt(0666, archive_entry_perm(ae)); 242 243 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 244 assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae)); 245 assertEqualInt(456, archive_entry_size(ae)); 246 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 247 assertEqualInt(0666, archive_entry_perm(ae)); 248 249 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 250 assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae)); 251 assertEqualInt(1495, archive_entry_size(ae)); 252 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 253 assertEqualInt(0666, archive_entry_perm(ae)); 254 /* TODO: Read some of the file data and verify it. 255 The code to read uncompressed Zip entries with "file at end" semantics 256 is tricky and should be verified more carefully. */ 257 258 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 259 assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae)); 260 261 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 262 assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae)); 263 264 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 265 assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae)); 266 267 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 268 assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae)); 269 270 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 271 assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae)); 272 273 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 274 assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae)); 275 276 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 277 assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae)); 278 279 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 280 assertEqualString("_rels/.rels", archive_entry_pathname(ae)); 281 282 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 283 assertEqualString("[Content_Types].xml", archive_entry_pathname(ae)); 284 285 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 286 287 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 288 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 289 290 /* Try reading without seek support. */ 291 assert((a = archive_read_new()) != NULL); 292 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 293 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 294 assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 3)); 295 296 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 297 assertEqualString("Metadata/Job_PT.xml", archive_entry_pathname(ae)); 298 assertEqualInt(0, archive_entry_size(ae)); 299 assert(!archive_entry_size_is_set(ae)); 300 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 301 assertEqualInt(0666, archive_entry_perm(ae)); 302 303 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 304 assertEqualString("Metadata/MXDC_Empty_PT.xml", archive_entry_pathname(ae)); 305 assertEqualInt(0, archive_entry_size(ae)); 306 assert(!archive_entry_size_is_set(ae)); 307 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 308 assertEqualInt(0666, archive_entry_perm(ae)); 309 310 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 311 assertEqualString("Documents/1/Metadata/Page1_Thumbnail.JPG", archive_entry_pathname(ae)); 312 assertEqualInt(0, archive_entry_size(ae)); 313 assert(!archive_entry_size_is_set(ae)); 314 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 315 assertEqualInt(0666, archive_entry_perm(ae)); 316 317 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 318 assertEqualString("Documents/1/Pages/_rels/1.fpage.rels", archive_entry_pathname(ae)); 319 320 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 321 assertEqualString("Documents/1/Pages/1.fpage", archive_entry_pathname(ae)); 322 323 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 324 assertEqualString("Documents/1/Resources/Fonts/3DFDBC8B-4514-41F1-A808-DEA1C79BAC2B.odttf", archive_entry_pathname(ae)); 325 326 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 327 assertEqualString("Documents/1/_rels/FixedDocument.fdoc.rels", archive_entry_pathname(ae)); 328 329 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 330 assertEqualString("Documents/1/FixedDocument.fdoc", archive_entry_pathname(ae)); 331 332 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 333 assertEqualString("_rels/FixedDocumentSequence.fdseq.rels", archive_entry_pathname(ae)); 334 335 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 336 assertEqualString("FixedDocumentSequence.fdseq", archive_entry_pathname(ae)); 337 338 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 339 assertEqualString("_rels/.rels", archive_entry_pathname(ae)); 340 341 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 342 assertEqualString("[Content_Types].xml", archive_entry_pathname(ae)); 343 344 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 345 346 assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a)); 347 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 348 free(p); 349 } 350 351 /* 352 * Issue 225: Errors extracting MSDOS Zip archives with directories. 353 */ 354 static void 355 compat_zip_6_verify(struct archive *a) 356 { 357 struct archive_entry *ae; 358 359 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 360 assertEqualString("New Folder/New Folder/", archive_entry_pathname(ae)); 361 assertEqualInt(AE_IFDIR, archive_entry_filetype(ae)); 362 /* Zip timestamps are local time, so vary by time zone. */ 363 /* TODO: A more complex assert would work here; we could 364 verify that it's within +/- 24 hours of a particular value. */ 365 /* assertEqualInt(1327314468, archive_entry_mtime(ae)); */ 366 assertEqualInt(0, archive_entry_size(ae)); 367 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 368 assertEqualString("New Folder/New Folder/New Text Document.txt", archive_entry_pathname(ae)); 369 assertEqualInt(AE_IFREG, archive_entry_filetype(ae)); 370 /* Zip timestamps are local time, so vary by time zone. */ 371 /* assertEqualInt(1327314476, archive_entry_mtime(ae)); */ 372 assertEqualInt(11, archive_entry_size(ae)); 373 assertEqualIntA(a, ARCHIVE_EOF, archive_read_next_header(a, &ae)); 374 } 375 376 static void 377 test_compat_zip_6(void) 378 { 379 const char *refname = "test_compat_zip_6.zip"; 380 struct archive *a; 381 void *p; 382 size_t s; 383 384 extract_reference_file(refname); 385 p = slurpfile(&s, refname); 386 387 assert((a = archive_read_new()) != NULL); 388 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 389 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 390 assertEqualIntA(a, ARCHIVE_OK, read_open_memory_seek(a, p, s, 7)); 391 compat_zip_6_verify(a); 392 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 393 394 assert((a = archive_read_new()) != NULL); 395 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a)); 396 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a)); 397 assertEqualIntA(a, ARCHIVE_OK, read_open_memory(a, p, s, 7)); 398 compat_zip_6_verify(a); 399 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 400 free(p); 401 } 402 403 /* 404 * Issue 226: Try to reproduce hang when reading archives where the 405 * length-at-end marker ends exactly on a block boundary. 406 */ 407 static void 408 test_compat_zip_7(void) 409 { 410 const char *refname = "test_compat_zip_7.xps"; 411 struct archive *a; 412 struct archive_entry *ae; 413 void *p; 414 size_t s; 415 int i; 416 417 extract_reference_file(refname); 418 p = slurpfile(&s, refname); 419 420 for (i = 1; i < 1000; ++i) { 421 assert((a = archive_read_new()) != NULL); 422 assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_zip(a)); 423 assertEqualIntA(a, ARCHIVE_OK, read_open_memory_minimal(a, p, s, i)); 424 425 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 426 assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); 427 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 428 assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); 429 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 430 assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); 431 assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae)); 432 assertEqualIntA(a, ARCHIVE_OK, archive_read_data_skip(a)); 433 434 assertEqualIntA(a, ARCHIVE_OK, archive_read_free(a)); 435 } 436 free(p); 437 } 438 439 DEFINE_TEST(test_compat_zip) 440 { 441 test_compat_zip_1(); 442 test_compat_zip_2(); 443 test_compat_zip_3(); 444 test_compat_zip_4(); 445 test_compat_zip_5(); 446 test_compat_zip_6(); 447 test_compat_zip_7(); 448 } 449 450 451