break;
}
case 0x414C:
+ {
/* Experimental 'LA' field */
- if (datasize >= 1) {
- // 1 byte system identifier
- zip_entry->system = p[offset];
+ 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 (datasize >= 2) {
+
+ if (bitmap & 1) {
+ // 2 byte "version made by"
+ if (datasize < 2)
+ break;
+ zip_entry->system
+ = archive_le16dec(p + offset) >> 8;
+ offset += 2;
+ datasize -= 2;
+ }
+ if (bitmap & 2) {
// 2 byte "internal file attributes"
+ uint32_t internal_attributes;
+ if (datasize < 2)
+ break;
+ internal_attributes
+ = archive_le16dec(p + offset);
+ // Not used by libarchive at present.
+ (void)internal_attributes; /* UNUSED */
offset += 2;
datasize -= 2;
}
- if (datasize >= 4) {
+ if (bitmap & 4) {
// 4 byte "external file attributes"
- uint32_t external_attributes
+ uint32_t external_attributes;
+ if (datasize < 4)
+ break;
+ external_attributes
= archive_le32dec(p + offset);
if (zip_entry->system == 3) {
zip_entry->mode
offset += 4;
datasize -= 4;
}
+ if (bitmap & 8) {
+ // 2 byte comment length + comment
+ uint32_t comment_length;
+ if (datasize < 2)
+ break;
+ comment_length
+ = archive_le16dec(p + offset);
+ offset += 2;
+ datasize -= 2;
+
+ if (datasize < comment_length)
+ break;
+ // Comment is not supported by libarchive
+ offset += comment_length;
+ datasize -= comment_length;
+ }
break;
+ }
case 0x7855:
/* Info-ZIP Unix Extra Field (type 2) "Ux". */
#ifdef DEBUG
unsigned char *external_info = e;
memcpy(e, "LA\000\000", 4); // 0x414C + 2-byte length
e += 4;
- e[0] = 3; /* system */
+ e[0] = 5; /* bitmap of included fields */
e += 1;
+ archive_le16enc(e, /* "Version created by" */
+ 3 * 256 + version_needed);
+ e += 2;
archive_le16enc(e, 0); /* internal file attributes */
e += 2;
archive_le32enc(e, /* external file attributes */
assertEqualInt(i4(q + 18), sizeof(file_data1) + sizeof(file_data2)); /* Compressed size */
assertEqualInt(i4(q + 22), sizeof(file_data1) + sizeof(file_data2)); /* Uncompressed size */
assertEqualInt(i2(q + 26), strlen(file_name)); /* Pathname length */
- assertEqualInt(i2(q + 28), 39); /* Extra field length */
+ assertEqualInt(i2(q + 28), 41); /* Extra field length */
assertEqualMem(q + 30, file_name, strlen(file_name)); /* Pathname */
extra_start = q = q + 30 + strlen(file_name);
assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */
q = q + 4 + i2(q + 2);
assertEqualInt(i2(q), 0x414c); /* 'LA' experimental extension header */
- assertEqualInt(i2(q + 2), 7); /* size */
- assertEqualInt(q[4], 3); /* system */
- assertEqualInt(i2(q + 5), 0); /* internal file attributes */
- assertEqualInt(i4(q + 7) >> 16 & 01777, file_perm); /* external file attributes */
+ assertEqualInt(i2(q + 2), 9); /* size */
+ assertEqualInt(q[4], 7); /* Bitmap of fields included. */
+ assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */
+ assertEqualInt(i2(q + 7), 0); /* internal file attributes */
+ assertEqualInt(i4(q + 9) >> 16 & 01777, file_perm); /* external file attributes */
q = q + 4 + i2(q + 2);
assert(q == extra_start + i2(local_header + 28));
assertEqualInt(i4(q + 18), 0); /* Compressed size */
assertEqualInt(i4(q + 22), 0); /* Uncompressed size */
assertEqualInt(i2(q + 26), strlen(folder_name)); /* Pathname length */
- assertEqualInt(i2(q + 28), 39); /* Extra field length */
+ assertEqualInt(i2(q + 28), 41); /* Extra field length */
assertEqualMem(q + 30, folder_name, strlen(folder_name)); /* Pathname */
extra_start = q = q + 30 + strlen(folder_name);
assertEqualInt(i2(q), 0x5455); /* 'UT' extension header */
q = q + 4 + i2(q + 2);
assertEqualInt(i2(q), 0x414c); /* 'LA' experimental extension header */
- assertEqualInt(i2(q + 2), 7); /* size */
- assertEqualInt(q[4], 3); /* system */
- assertEqualInt(i2(q + 5), 0); /* internal file attributes */
- assertEqualInt(i4(q + 7) >> 16 & 01777, folder_perm); /* external file attributes */
+ assertEqualInt(i2(q + 2), 9); /* size */
+ assertEqualInt(q[4], 7); /* bitmap of fields */
+ assertEqualInt(i2(q + 5) >> 8, 3); /* system & version made by */
+ assertEqualInt(i2(q + 7), 0); /* internal file attributes */
+ assertEqualInt(i4(q + 9) >> 16 & 01777, folder_perm); /* external file attributes */
q = q + 4 + i2(q + 2);
assert(q == extra_start + i2(local_header + 28));
/* assertEqualInt(i4(p + 18), sizeof(file_data)); */ /* Compressed size */
/* assertEqualInt(i4(p + 22), sizeof(file_data)); */ /* Uncompressed size not stored because we're using length-at-end. */
assertEqualInt(i2(p + 26), strlen(file_name)); /* Pathname length */
- assertEqualInt(i2(p + 28), 35); /* Extra field length */
+ assertEqualInt(i2(p + 28), 37); /* Extra field length */
assertEqualMem(p + 30, file_name, strlen(file_name)); /* Pathname */
p = extension_start = local_header + 30 + strlen(file_name);
extension_end = extension_start + i2(local_header + 28);
assertEqualInt(i4(p + 11), file_gid); /* 'Ux' GID */
p += 4 + i2(p + 2);
- assertEqualInt(i2(p), 0x414c); /* 'LA' experimental extension header */
- assertEqualInt(i2(p + 2), 7); /* 'at' size */
- assertEqualInt(p[4], 3); /* system */
- assertEqualInt(i2(p + 5), 0); /* internal file attributes */
- assertEqualInt(i4(p + 7) >> 16 & 01777, file_perm); /* external file attributes */
+ assertEqualInt(i2(p), 0x414c); /* 'LA' experimental extension block */
+ assertEqualInt(i2(p + 2), 9); /* size */
+ assertEqualInt(p[4], 7); /* bitmap of fields in this block */
+ assertEqualInt(i2(p + 5) >> 8, 3); /* System & version made by */
+ assertEqualInt(i2(p + 7), 0); /* internal file attributes */
+ assertEqualInt(i4(p + 9) >> 16 & 01777, file_perm); /* external file attributes */
p += 4 + i2(p + 2);
/* Just in case: Report any extra extensions. */
/* assertEqualInt(i4(p + 18), sizeof(file_data)); */ /* Compressed size */
/* assertEqualInt(i4(p + 22), sizeof(file_data)); */ /* Uncompressed size not stored because we're using length-at-end. */
assertEqualInt(i2(p + 26), strlen(file_name)); /* Pathname length */
- assertEqualInt(i2(p + 28), 55); /* Extra field length */
+ assertEqualInt(i2(p + 28), 57); /* Extra field length */
assertEqualMem(p + 30, file_name, strlen(file_name)); /* Pathname */
p = extension_start = local_header + 30 + strlen(file_name);
extension_end = extension_start + i2(local_header + 28);
p += 4 + i2(p + 2);
assertEqualInt(i2(p), 0x414c); /* 'LA' experimental extension header */
- assertEqualInt(i2(p + 2), 7); /* 'at' size */
- assertEqualInt(p[4], 3); /* system */
- assertEqualInt(i2(p + 5), 0); /* internal file attributes */
- assertEqualInt(i4(p + 7) >> 16 & 01777, file_perm); /* external file attributes */
+ assertEqualInt(i2(p + 2), 9); /* size */
+ assertEqualInt(p[4], 7); /* bitmap of included fields */
+ assertEqualInt(i2(p + 5) >> 8, 3); /* system & version made by */
+ assertEqualInt(i2(p + 7), 0); /* internal file attributes */
+ assertEqualInt(i4(p + 9) >> 16 & 01777, file_perm); /* external file attributes */
p += 4 + i2(p + 2);
/* Just in case: Report any extra extensions. */