Merge pull request #3257 from R4mbb/fix-pax-all-slash-pathname
pax: handle all-slash pathnames in USTAR name splitting
This commit is contained in:
2 files changed
+51
No files matched your search
@@ -1607,6 +1607,26 @@ build_ustar_entry_name(char *dest, const char *src, size_t src_length,
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Pathological case: after trimming trailing '/' characters and
|
||||
* '/.' path elements, there is no filename component left. This
|
||||
* happens for pathnames made entirely of '/' characters. Do not
|
||||
* attempt to compute filename_end - 1 in that case, which would
|
||||
* move the filename pointer in front of the input buffer and read
|
||||
* one byte out of bounds. Emit a root-like ustar name instead.
|
||||
*/
|
||||
if (filename_end == src) {
|
||||
p = dest;
|
||||
if (insert != NULL) {
|
||||
strcpy(p, insert);
|
||||
p += strlen(insert);
|
||||
}
|
||||
*p++ = '/';
|
||||
*p = '\0';
|
||||
return (dest);
|
||||
}
|
||||
|
||||
if (need_slash)
|
||||
suffix_length--;
|
||||
/* Find start of filename. */
|
||||
|
||||
@@ -36,6 +36,7 @@ DEFINE_TEST(test_write_format_pax)
|
||||
int i;
|
||||
char nulls[1024];
|
||||
int64_t offset, length;
|
||||
char long_slashes[300 + 1];
|
||||
|
||||
buff = malloc(buffsize); /* million bytes of work area */
|
||||
assert(buff != NULL);
|
||||
@@ -125,6 +126,23 @@ DEFINE_TEST(test_write_format_pax)
|
||||
archive_entry_free(ae);
|
||||
assertEqualIntA(a, 8, archive_write_data(a, "12345678", 9));
|
||||
|
||||
/*
|
||||
* A pathname made entirely of '/' characters used to trigger an
|
||||
* out-of-bounds read in the pax writer when the pathname was long
|
||||
* enough to require USTAR name splitting.
|
||||
*/
|
||||
memset(long_slashes, '/', 300);
|
||||
long_slashes[300] = '\0';
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_atime(ae, 2, 20);
|
||||
archive_entry_set_ctime(ae, 4, 40);
|
||||
archive_entry_set_mtime(ae, 5, 50);
|
||||
archive_entry_copy_pathname(ae, long_slashes);
|
||||
archive_entry_set_mode(ae, S_IFREG | 0644);
|
||||
archive_entry_set_size(ae, 0);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/*
|
||||
* XXX TODO XXX Archive directory, other file types.
|
||||
* Archive extended attributes, ACLs, other metadata.
|
||||
@@ -243,6 +261,19 @@ DEFINE_TEST(test_write_format_pax)
|
||||
assertEqualIntA(a, 8, archive_read_data(a, buff2, 10));
|
||||
assertEqualMem(buff2, "12345678", 8);
|
||||
|
||||
/*
|
||||
* Read the all-slash pathname entry.
|
||||
*/
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
|
||||
assertEqualString(long_slashes, archive_entry_pathname(ae));
|
||||
assertEqualInt(2, archive_entry_atime(ae));
|
||||
assertEqualInt(20, archive_entry_atime_nsec(ae));
|
||||
assertEqualInt(4, archive_entry_ctime(ae));
|
||||
assertEqualInt(40, archive_entry_ctime_nsec(ae));
|
||||
assertEqualInt(5, archive_entry_mtime(ae));
|
||||
assertEqualInt(50, archive_entry_mtime_nsec(ae));
|
||||
assertEqualInt(0, archive_entry_size(ae));
|
||||
|
||||
/*
|
||||
* Verify the end of the archive.
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user