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