Merge pull request #3057 from i1011/mtree-null-deref-fix
mtree: Fix null dereference for some corner cases:
- a symlink whose target is never set
- emitting a root directory entry that is actually a file
(cherry picked from commit ea7084a735)
This commit is contained in:
1 parent
f774f03b40
commit
b3045fd830
2 files changed
+67
No files matched your search
@@ -801,6 +801,8 @@ mtree_entry_new(struct archive_write *a, struct archive_entry *entry,
|
||||
archive_strcpy(&me->symlink, s);
|
||||
me->nlink = archive_entry_nlink(entry);
|
||||
me->filetype = archive_entry_filetype(entry);
|
||||
if (me->filetype == AE_IFLNK && me->symlink.s == NULL)
|
||||
archive_strcpy(&me->symlink, "");
|
||||
me->mode = archive_entry_mode(entry) & 07777;
|
||||
me->uid = archive_entry_uid(entry);
|
||||
me->gid = archive_entry_gid(entry);
|
||||
@@ -2086,6 +2088,11 @@ mtree_entry_tree_add(struct archive_write *a, struct mtree_entry **filep)
|
||||
file = *filep;
|
||||
if (file->parentdir.length == 0 && file->basename.length == 1 &&
|
||||
file->basename.s[0] == '.') {
|
||||
if (file->filetype != AE_IFDIR) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Root entry '.' must be a directory");
|
||||
return (ARCHIVE_FAILED);
|
||||
}
|
||||
file->parent = file;
|
||||
if (mtree->root != NULL) {
|
||||
np = mtree->root;
|
||||
|
||||
@@ -171,3 +171,63 @@ DEFINE_TEST(test_write_format_mtree_null_deref)
|
||||
archive_write_free(a);
|
||||
free(out_buf);
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_write_format_mtree_no_set_symlink)
|
||||
{
|
||||
struct archive *a;
|
||||
size_t buffsize = 4096;
|
||||
char *buff;
|
||||
size_t used;
|
||||
assert((buff = malloc(buffsize)) != NULL);
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_write_open_memory(a, buff, buffsize, &used));
|
||||
|
||||
struct archive_entry *ae;
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_pathname(ae, "./badlink"),
|
||||
archive_entry_set_filetype(ae, AE_IFLNK);
|
||||
archive_entry_set_perm(ae, 0777);
|
||||
/* archive_entry_set_symlink(ae, "target"); (omitted) */
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
|
||||
archive_entry_free(ae);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
free(buff);
|
||||
}
|
||||
|
||||
DEFINE_TEST(test_write_format_mtree_reg_dot_root)
|
||||
{
|
||||
struct archive *a;
|
||||
size_t buffsize = 4096;
|
||||
char *buff;
|
||||
size_t used;
|
||||
assert((buff = malloc(buffsize)) != NULL);
|
||||
assert((a = archive_write_new()) != NULL);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_mtree(a));
|
||||
assertEqualIntA(a, ARCHIVE_OK,
|
||||
archive_write_open_memory(a, buff, buffsize, &used));
|
||||
|
||||
struct archive_entry *ae;
|
||||
/* Entry 1: "." with filetype AE_IFREG (not AE_IFDIR). */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_pathname(ae, "."),
|
||||
archive_entry_set_filetype(ae, AE_IFREG);
|
||||
archive_entry_set_perm(ae, 0644);
|
||||
assertEqualIntA(a, ARCHIVE_FAILED, archive_write_header(a, ae));
|
||||
archive_entry_free(ae);
|
||||
|
||||
/* Entry 2: any child path. */
|
||||
assert((ae = archive_entry_new()) != NULL);
|
||||
archive_entry_set_pathname(ae, "./foo"),
|
||||
archive_entry_set_filetype(ae, AE_IFREG);
|
||||
archive_entry_set_perm(ae, 0644);
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, ae));
|
||||
archive_entry_free(ae);
|
||||
|
||||
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
|
||||
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
|
||||
free(buff);
|
||||
}
|
||||
Reference in new issue
Block a user