diff options
author | Joerg Sonnenberger <joerg@bec.de> | 2021-10-07 00:24:30 +0200 |
---|---|---|
committer | Joerg Sonnenberger <joerg@bec.de> | 2021-10-07 00:54:15 +0200 |
commit | 7c20f946d4a328bd73710be81b56537fb5b813a2 (patch) | |
tree | a7b641a6a4148f6d330d0d0d567364fe392ced17 /libarchive/archive_write_disk_windows.c | |
parent | dc321febde83dd0f31158e1be61a7aedda65e7a2 (diff) | |
download | libarchive-7c20f946d4a328bd73710be81b56537fb5b813a2.tar.gz |
Support ARCHIVE_EXTRACT_SECURE_NODOTDOT on Windows
Diffstat (limited to 'libarchive/archive_write_disk_windows.c')
-rw-r--r-- | libarchive/archive_write_disk_windows.c | 29 |
1 files changed, 21 insertions, 8 deletions
diff --git a/libarchive/archive_write_disk_windows.c b/libarchive/archive_write_disk_windows.c index 0c600176..0cfc9283 100644 --- a/libarchive/archive_write_disk_windows.c +++ b/libarchive/archive_write_disk_windows.c @@ -213,7 +213,7 @@ static int check_symlinks(struct archive_write_disk *); static int create_filesystem_object(struct archive_write_disk *); static struct fixup_entry *current_fixup(struct archive_write_disk *, const wchar_t *pathname); -static int cleanup_pathname(struct archive_write_disk *); +static int cleanup_pathname(struct archive_write_disk *, wchar_t *); static int create_dir(struct archive_write_disk *, wchar_t *); static int create_parent_dir(struct archive_write_disk *, wchar_t *); static int la_chmod(const wchar_t *, mode_t); @@ -854,7 +854,7 @@ _archive_write_disk_header(struct archive *_a, struct archive_entry *entry) * dir restores; the dir restore logic otherwise gets messed * up by nonsense like "dir/.". */ - ret = cleanup_pathname(a); + ret = cleanup_pathname(a, a->name); if (ret != ARCHIVE_OK) return (ret); @@ -1671,9 +1671,22 @@ create_filesystem_object(struct archive_write_disk *a) /* Since link(2) and symlink(2) don't handle modes, we're done here. */ linkname = archive_entry_hardlink_w(a->entry); if (linkname != NULL) { - wchar_t *linkfull, *namefull; - - linkfull = __la_win_permissive_name_w(linkname); + wchar_t *linksanitized, *linkfull, *namefull; + size_t l = (wcslen(linkname) + 1) * sizeof(wchar_t); + linksanitized = malloc(l); + if (linksanitized == NULL) { + archive_set_error(&a->archive, ENOMEM, + "Can't allocate memory for hardlink target"); + return (-1); + } + memcpy(linksanitized, linkname, l); + r = cleanup_pathname(a, linksanitized); + if (r != ARCHIVE_OK) { + free(linksanitized); + return (r); + } + linkfull = __la_win_permissive_name_w(linksanitized); + free(linksanitized); namefull = __la_win_permissive_name_w(a->name); if (linkfull == NULL || namefull == NULL) { errno = EINVAL; @@ -2184,12 +2197,12 @@ guidword(wchar_t *p, int n) * set) any '..' in the path. */ static int -cleanup_pathname(struct archive_write_disk *a) +cleanup_pathname(struct archive_write_disk *a, wchar_t *name) { wchar_t *dest, *src, *p, *top; wchar_t separator = L'\0'; - p = a->name; + p = name; if (*p == L'\0') { archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "Invalid empty pathname"); @@ -2201,7 +2214,7 @@ cleanup_pathname(struct archive_write_disk *a) if (*p == L'/') *p = L'\\'; } - p = a->name; + p = name; /* Skip leading "\\.\" or "\\?\" or "\\?\UNC\" or * "\\?\Volume{GUID}\" |