From 38906e07a0380901105855d09ef8d45bfb5402d7 Mon Sep 17 00:00:00 2001 From: kientzle Date: Mon, 11 Jun 2007 05:17:30 +0000 Subject: Don't lose leading '/' for pathnames exactly 101 bytes long. Also, update the test harness to exercise this case. --- lib/libarchive/archive_write_set_format_ustar.c | 10 ++++++++++ lib/libarchive/test/test_tar_filenames.c | 23 +++++++++++++++-------- 2 files changed, 25 insertions(+), 8 deletions(-) (limited to 'lib') diff --git a/lib/libarchive/archive_write_set_format_ustar.c b/lib/libarchive/archive_write_set_format_ustar.c index f43c23a..390b1a0 100644 --- a/lib/libarchive/archive_write_set_format_ustar.c +++ b/lib/libarchive/archive_write_set_format_ustar.c @@ -279,6 +279,16 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512], /* Store in two pieces, splitting at a '/'. */ p = strchr(pp + strlen(pp) - USTAR_name_size - 1, '/'); /* + * If the separator we found is the first '/', find + * the next one. (This is a pathological case that + * occurs for paths of exactly 101 bytes that start with + * '/'; it occurs because the separating '/' is not + * stored explicitly and the reconstruction assumes that + * an empty prefix means there is no '/' separator.) + */ + if (p == pp) + p = strchr(p + 1, '/'); + /* * If there is no path separator, or the prefix or * remaining name are too large, return an error. */ diff --git a/lib/libarchive/test/test_tar_filenames.c b/lib/libarchive/test/test_tar_filenames.c index fb15a96..b534174 100644 --- a/lib/libarchive/test/test_tar_filenames.c +++ b/lib/libarchive/test/test_tar_filenames.c @@ -31,8 +31,8 @@ __FBSDID("$FreeBSD$"); * filenames into prefix/suffix. */ -static void -test_filename(int dlen, int flen) +static +test_filename(const char *prefix, int dlen, int flen) { char buff[8192]; char filename[400]; @@ -40,12 +40,17 @@ test_filename(int dlen, int flen) struct archive_entry *ae; struct archive *a; size_t used; - int i; + size_t prefix_length = 0; + int i = 0; - for (i = 0; i < dlen; i++) + if (prefix) { + strcpy(filename, prefix); + i = prefix_length = strlen(prefix); + } + for (; i < prefix_length + dlen; i++) filename[i] = 'a'; filename[i++] = '/'; - for (; i < dlen + flen + 1; i++) + for (; i < prefix_length + dlen + flen + 1; i++) filename[i] = 'b'; filename[i++] = '\0'; @@ -111,7 +116,7 @@ test_filename(int dlen, int flen) assertA(0 == archive_read_next_header(a, &ae)); failure("Pathname %d/%d: %s", dlen, flen, archive_entry_pathname(ae)); assertEqualString(filename, archive_entry_pathname(ae)); - assert((S_IFREG | 0755) == archive_entry_mode(ae)); + assertEqualInt((S_IFREG | 0755), archive_entry_mode(ae)); /* * Read the two dirs and check the names. @@ -147,13 +152,15 @@ DEFINE_TEST(test_tar_filenames) /* Repeat the following for a variety of dir/file lengths. */ for (dlen = 40; dlen < 60; dlen++) { for (flen = 40; flen < 60; flen++) { - test_filename(dlen, flen); + test_filename(NULL, dlen, flen); + test_filename("/", dlen, flen); } } for (dlen = 140; dlen < 160; dlen++) { for (flen = 90; flen < 110; flen++) { - test_filename(dlen, flen); + test_filename(NULL, dlen, flen); + test_filename("/", dlen, flen); } } } -- cgit v1.1