Don't lose leading '/' for pathnames exactly 101 bytes long.

Also, update the test harness to exercise this case.
This commit is contained in:
Tim Kientzle 2007-06-11 05:17:30 +00:00
parent 40ca0d5755
commit 8b63161182
2 changed files with 25 additions and 8 deletions

View File

@ -278,6 +278,16 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
else {
/* 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.

View File

@ -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);
}
}
}