]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
Merge branch 'master' of github.com:kientzle/libarchive-zip64
authorTim Kientzle <kientzle@acm.org>
Sun, 12 Jan 2014 17:18:57 +0000 (09:18 -0800)
committerTim Kientzle <kientzle@acm.org>
Sun, 12 Jan 2014 17:18:57 +0000 (09:18 -0800)
1  2 
libarchive/archive_read_support_format_zip.c
libarchive/archive_write_set_format_zip.c
libarchive/test/test_write_format_zip.c
libarchive/test/test_write_format_zip_file.c

index ae8035cc893153309c4d47b82b49b97966c3317f,b3ccf7c00becf622846fd9d3f8caf556eb9aa2e1..37fbeb14ecbc5394e3423f8b166ca932f19b01d6
@@@ -339,19 -339,29 +339,37 @@@ process_extra(const char *p, size_t ext
                        }
                        break;
                }
-               case 0x414C:
+               case 0x6c65:
                {
-                       /* Experimental 'LA' field */
+                       /* Experimental 'el' field */
 +                      /*
 +                       * Introduced Dec 2013 to provide a way to
 +                       * include external file attributes in local file
 +                       * header.  This provides file type and permission
 +                       * information necessary to support full streaming
 +                       * extraction.  Currently being discussed with
 +                       * other Zip developers... subject to change.
 +                       */
-                       if (datasize >= 2) {
+                       int bitmap, bitmap_last;
+                       if (datasize < 1)
+                               break;
+                       bitmap_last = bitmap = 0xff & p[offset];
+                       offset += 1;
+                       datasize -= 1;
+                       /* We only support first 7 bits of bitmap; skip rest. */
+                       while ((bitmap_last & 0x80) != 0
+                           && datasize >= 1) {
+                               bitmap_last = p[offset];
+                               offset += 1;
+                               datasize -= 1;
+                       }
+                       if (bitmap & 1) {
                                // 2 byte "version made by"
+                               if (datasize < 2)
+                                       break;
                                zip_entry->system
                                    = archive_le16dec(p + offset) >> 8;
                                offset += 2;
index 0199023fb61aaab0b4c8acc87d8169ce12c202df,11656f0830b2849caf1bdeb47979385b8a3a5f69..5a32b9df97444c414644f0a0408a0dec6972b90f
@@@ -272,14 -249,13 +263,19 @@@ archive_write_zip_options(struct archiv
                }
                return (ret);
        } else if (strcmp(key, "zip64") == 0) {
-               zip->force_zip64 = (val != NULL && *val != '\0');
-               zip->avoid_zip64 = !zip->force_zip64;
 +              /*
 +               * Bias decisions about Zip64: force them to be
 +               * generated in certain cases where they are not
 +               * forbidden or avoid them in certain cases where they
 +               * are not strictly required.
 +               */
+               if (val != NULL && *val != '\0') {
+                       zip->flags |= ZIP_FLAG_FORCE_ZIP64;
+                       zip->flags &= ~ZIP_FLAG_AVOID_ZIP64;
+               } else {
+                       zip->flags &= ~ZIP_FLAG_FORCE_ZIP64;
+                       zip->flags |= ZIP_FLAG_AVOID_ZIP64;
+               }
                return (ARCHIVE_OK);
        }
  
@@@ -426,6 -401,6 +421,23 @@@ archive_write_zip_header(struct archive
                return ARCHIVE_FAILED;
        };
  
++      /* If we're not using Zip64, reject large files. */
++      if (zip->flags & ZIP_FLAG_AVOID_ZIP64) {
++              /* Reject entries over 4GB. */
++              if (archive_entry_size_is_set(entry)
++                  && (archive_entry_size(entry) > 0xffffffff)) {
++                      archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++                          "Files > 4GB require Zip64 extensions");
++                      return ARCHIVE_FAILED;
++              }
++              /* Reject entries if archive is > 4GB. */
++              if (zip->written_bytes > 0xffffffff) {
++                      archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
++                          "Archives > 4GB require Zip64 extensions");
++                      return ARCHIVE_FAILED;
++              }
++      }
++
        /* Only regular files can have size > 0. */
        if (type != AE_IFREG)
                archive_entry_set_size(entry, 0);
index fc91f855086cb685d4fdf862ec4d770f1b868edf,31c611fefe7f12b64a5fa6eff7d8388938d7e126..4c94e123bb8ab6d3b7b9b5839812f9a88b5a045f
@@@ -581,10 -581,9 +581,12 @@@ DEFINE_TEST(test_write_format_zip64
        assert((a = archive_write_new()) != NULL);
        assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_zip(a));
        assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
 -      assertEqualIntA(a, ARCHIVE_OK, archive_write_set_options(a, "zip:zip64"));
 +      assertEqualIntA(a, ARCHIVE_OK,
 +          archive_write_set_options(a, "zip:zip64"));
 +      assertEqualIntA(a, ARCHIVE_OK,
 +          archive_write_set_options(a, "zip:experimental"));
+       assertEqualIntA(a, ARCHIVE_OK,
+           archive_write_set_options(a, "zip:experimental"));
        assertEqualIntA(a, ARCHIVE_OK,
            archive_write_open_memory(a, buff, buffsize, &used));
        write_contents(a);