From de610c2e433542cbe26df7d2ae4d66c0c55adae9 Mon Sep 17 00:00:00 2001 From: Nils Gladitz Date: Wed, 8 Apr 2015 20:58:29 +0200 Subject: [PATCH] Fall back to base-256 encoding for UID/GID like GNU tar does. --- libarchive/archive_write_set_format_gnutar.c | 12 +++++----- libarchive/test/test_write_format_gnutar.c | 24 +++++++++++++++++++- 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/libarchive/archive_write_set_format_gnutar.c b/libarchive/archive_write_set_format_gnutar.c index 13942c132..647079de6 100644 --- a/libarchive/archive_write_set_format_gnutar.c +++ b/libarchive/archive_write_set_format_gnutar.c @@ -644,18 +644,18 @@ archive_format_gnutar_header(struct archive_write *a, char h[512], format_octal(archive_entry_mode(entry) & 07777, h + GNUTAR_mode_offset, GNUTAR_mode_size); - /* TODO: How does GNU tar handle large UIDs? */ - if (format_octal(archive_entry_uid(entry), - h + GNUTAR_uid_offset, GNUTAR_uid_size)) { + /* GNU tar supports base-256 here, so should never overflow. */ + if (format_number(archive_entry_uid(entry), h + GNUTAR_uid_offset, + GNUTAR_uid_size, GNUTAR_uid_max_size)) { archive_set_error(&a->archive, ERANGE, "Numeric user ID %jd too large", (intmax_t)archive_entry_uid(entry)); ret = ARCHIVE_FAILED; } - /* TODO: How does GNU tar handle large GIDs? */ - if (format_octal(archive_entry_gid(entry), - h + GNUTAR_gid_offset, GNUTAR_gid_size)) { + /* GNU tar supports base-256 here, so should never overflow. */ + if (format_number(archive_entry_gid(entry), h + GNUTAR_gid_offset, + GNUTAR_gid_size, GNUTAR_gid_max_size)) { archive_set_error(&a->archive, ERANGE, "Numeric group ID %jd too large", (intmax_t)archive_entry_gid(entry)); diff --git a/libarchive/test/test_write_format_gnutar.c b/libarchive/test/test_write_format_gnutar.c index 63ee6225f..2a4c383e7 100644 --- a/libarchive/test/test_write_format_gnutar.c +++ b/libarchive/test/test_write_format_gnutar.c @@ -159,6 +159,19 @@ DEFINE_TEST(test_write_format_gnutar) assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); archive_entry_free(ae); + /* + * A file with large UID/GID that overflow octal encoding. + */ + assert((ae = archive_entry_new()) != NULL); + archive_entry_copy_pathname(ae, "large_uid_gid"); + archive_entry_set_mode(ae, S_IFREG | 0755); + archive_entry_set_size(ae, 8); + archive_entry_set_uid(ae, 123456789); + archive_entry_set_gid(ae, 987654321); + assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae)); + archive_entry_free(ae); + assertEqualIntA(a, 8, archive_write_data(a, "abcdefgh", 9)); + /* TODO: support GNU tar sparse format and test it here. */ /* See test_write_format_pax for an example of testing sparse files. */ @@ -173,7 +186,7 @@ DEFINE_TEST(test_write_format_gnutar) /* Verify GNU tar magic/version fields */ assertEqualMem(buff + 257, "ustar \0", 8); - assertEqualInt(14336, used); + assertEqualInt(15360, used); /* * @@ -225,6 +238,15 @@ DEFINE_TEST(test_write_format_gnutar) assertEqualString(longfilename, archive_entry_symlink(ae)); assertEqualInt(AE_IFLNK | 0755, archive_entry_mode(ae)); + /* + * Read file with large UID/GID. + */ + assertEqualIntA(a, 0, archive_read_next_header(a, &ae)); + assertEqualInt(123456789, archive_entry_uid(ae)); + assertEqualInt(987654321, archive_entry_gid(ae)); + assertEqualString("large_uid_gid", archive_entry_pathname(ae)); + assertEqualInt(S_IFREG | 0755, archive_entry_mode(ae)); + /* * Verify the end of the archive. */ -- 2.47.2