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