mirror of
https://github.com/Kitware/CMake.git
synced 2026-08-09 17:18:18 +00:00
libarchive: Backport "Fix crash on failure to convert WCS/UTF-8 pathname"
Backport libarchive commit `d4cf95cdac` (archive_write: Fix crash on failure to convert WCS/UTF-8 pathname to MBS, 2026-02-04) and supporting parent commits from libarchive PR 2856 [1]. [1] https://github.com/libarchive/libarchive/pull/2856 Issue: #26903
This commit is contained in:
committed by
Alex Overchenko
parent
c19aaaab8b
commit
e5c6c121c6
@@ -777,7 +777,7 @@ archive_string_append_from_wcs_in_codepage(struct archive_string *as,
|
||||
int r;
|
||||
|
||||
defchar_used = 0;
|
||||
if (to_cp == CP_UTF8 || sc == NULL)
|
||||
if (to_cp == CP_UTF8)
|
||||
dp = NULL;
|
||||
else
|
||||
dp = &defchar_used;
|
||||
@@ -1878,6 +1878,9 @@ archive_string_conversion_free(struct archive *a)
|
||||
const char *
|
||||
archive_string_conversion_charset_name(struct archive_string_conv *sc)
|
||||
{
|
||||
if (sc == NULL) {
|
||||
return "current locale";
|
||||
}
|
||||
if (sc->flag & SCONV_TO_CHARSET)
|
||||
return (sc->to_charset);
|
||||
else
|
||||
@@ -4128,7 +4131,12 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
|
||||
* character-set. */
|
||||
if ((aes->aes_set & AES_SET_MBS) == 0) {
|
||||
const char *pm; /* unused */
|
||||
archive_mstring_get_mbs(a, aes, &pm); /* ignore errors, we'll handle it later */
|
||||
if (archive_mstring_get_mbs(a, aes, &pm) != 0) {
|
||||
/* We have another form, but failed to convert it to
|
||||
* the native locale. Transitively, we've failed to
|
||||
* convert it to the specified character set. */
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
/* If we already have an MBS form, use it to be translated to
|
||||
* specified character-set. */
|
||||
@@ -4146,6 +4154,8 @@ archive_mstring_get_mbs_l(struct archive *a, struct archive_mstring *aes,
|
||||
if (length != NULL)
|
||||
*length = aes->aes_mbs_in_locale.length;
|
||||
} else {
|
||||
/* Either we have no string in any form,
|
||||
* or conversion failed and set 'ret != 0'. */
|
||||
*p = NULL;
|
||||
if (length != NULL)
|
||||
*length = 0;
|
||||
|
||||
@@ -293,6 +293,17 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
} else
|
||||
sconv = gnutar->opt_sconv;
|
||||
|
||||
/* Sanity check. */
|
||||
if (archive_entry_pathname(entry) == NULL
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
&& archive_entry_pathname_w(entry) == NULL
|
||||
#endif
|
||||
) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't record entry in tar file without pathname");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
|
||||
/* Only regular files (not hardlinks) have data. */
|
||||
if (archive_entry_hardlink(entry) != NULL ||
|
||||
archive_entry_symlink(entry) != NULL ||
|
||||
@@ -385,17 +396,30 @@ archive_write_gnutar_header(struct archive_write *a,
|
||||
r = archive_entry_pathname_l(entry, &(gnutar->pathname),
|
||||
&(gnutar->pathname_length), sconv);
|
||||
if (r != 0) {
|
||||
const char* p_mbs;
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for pathname");
|
||||
ret = ARCHIVE_FATAL;
|
||||
goto exit_write_header;
|
||||
}
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s",
|
||||
archive_entry_pathname(entry),
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
ret2 = ARCHIVE_WARN;
|
||||
p_mbs = archive_entry_pathname(entry);
|
||||
if (p_mbs) {
|
||||
/* We have a wrongly-encoded MBS pathname.
|
||||
* Warn and use it. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s", p_mbs,
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
ret2 = ARCHIVE_WARN;
|
||||
} else {
|
||||
/* We have no MBS pathname. Fail. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname to %s",
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
}
|
||||
r = archive_entry_uname_l(entry, &(gnutar->uname),
|
||||
&(gnutar->uname_length), sconv);
|
||||
|
||||
@@ -254,11 +254,11 @@ archive_write_ustar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
sconv = ustar->opt_sconv;
|
||||
|
||||
/* Sanity check. */
|
||||
if (archive_entry_pathname(entry) == NULL
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
if (archive_entry_pathname_w(entry) == NULL) {
|
||||
#else
|
||||
if (archive_entry_pathname(entry) == NULL) {
|
||||
&& archive_entry_pathname_w(entry) == NULL
|
||||
#endif
|
||||
) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't record entry in tar file without pathname");
|
||||
return (ARCHIVE_FAILED);
|
||||
@@ -409,15 +409,28 @@ __archive_write_format_header_ustar(struct archive_write *a, char h[512],
|
||||
*/
|
||||
r = archive_entry_pathname_l(entry, &pp, ©_length, sconv);
|
||||
if (r != 0) {
|
||||
const char* p_mbs;
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for Pathname");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s",
|
||||
pp, archive_string_conversion_charset_name(sconv));
|
||||
ret = ARCHIVE_WARN;
|
||||
p_mbs = archive_entry_pathname(entry);
|
||||
if (p_mbs) {
|
||||
/* We have a wrongly-encoded MBS pathname.
|
||||
* Warn and use it. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s", p_mbs,
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
ret = ARCHIVE_WARN;
|
||||
} else {
|
||||
/* We have no MBS pathname. Fail. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname to %s",
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
}
|
||||
if (copy_length <= USTAR_name_size)
|
||||
memcpy(h + USTAR_name_offset, pp, copy_length);
|
||||
|
||||
@@ -232,7 +232,11 @@ archive_write_v7tar_header(struct archive_write *a, struct archive_entry *entry)
|
||||
sconv = v7tar->opt_sconv;
|
||||
|
||||
/* Sanity check. */
|
||||
if (archive_entry_pathname(entry) == NULL) {
|
||||
if (archive_entry_pathname(entry) == NULL
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
&& archive_entry_pathname_w(entry) == NULL
|
||||
#endif
|
||||
) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't record entry in tar file without pathname");
|
||||
return (ARCHIVE_FAILED);
|
||||
@@ -382,15 +386,28 @@ format_header_v7tar(struct archive_write *a, char h[512],
|
||||
*/
|
||||
r = archive_entry_pathname_l(entry, &pp, ©_length, sconv);
|
||||
if (r != 0) {
|
||||
const char* p_mbs;
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for Pathname");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s",
|
||||
pp, archive_string_conversion_charset_name(sconv));
|
||||
ret = ARCHIVE_WARN;
|
||||
p_mbs = archive_entry_pathname(entry);
|
||||
if (p_mbs) {
|
||||
/* We have a wrongly-encoded MBS pathname.
|
||||
* Warn and use it. */
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s", p_mbs,
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
ret = ARCHIVE_WARN;
|
||||
} else {
|
||||
/* We have no MBS pathname. Fail. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname to %s",
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
}
|
||||
if (strict && copy_length < V7TAR_name_size)
|
||||
memcpy(h + V7TAR_name_offset, pp, copy_length);
|
||||
|
||||
@@ -802,6 +802,17 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
|
||||
int version_needed = 10;
|
||||
#define MIN_VERSION_NEEDED(x) do { if (version_needed < x) { version_needed = x; } } while (0)
|
||||
|
||||
/* Sanity check. */
|
||||
if (archive_entry_pathname(entry) == NULL
|
||||
#if defined(_WIN32) && !defined(__CYGWIN__)
|
||||
&& archive_entry_pathname_w(entry) == NULL
|
||||
#endif
|
||||
) {
|
||||
archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC,
|
||||
"Can't record entry in zip file without pathname");
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
|
||||
/* Ignore types of entries that we don't support. */
|
||||
type = archive_entry_filetype(entry);
|
||||
if (type != AE_IFREG && type != AE_IFDIR && type != AE_IFLNK) {
|
||||
@@ -882,22 +893,33 @@ archive_write_zip_header(struct archive_write *a, struct archive_entry *entry)
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
|
||||
if (sconv != NULL) {
|
||||
{
|
||||
const char *p;
|
||||
size_t len;
|
||||
|
||||
if (archive_entry_pathname_l(zip->entry, &p, &len, sconv) != 0) {
|
||||
const char* p_mbs;
|
||||
if (errno == ENOMEM) {
|
||||
archive_set_error(&a->archive, ENOMEM,
|
||||
"Can't allocate memory for Pathname");
|
||||
return (ARCHIVE_FATAL);
|
||||
}
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate Pathname '%s' to %s",
|
||||
archive_entry_pathname(zip->entry),
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
ret2 = ARCHIVE_WARN;
|
||||
p_mbs = archive_entry_pathname(zip->entry);
|
||||
if (p_mbs) {
|
||||
/* We have a wrongly-encoded MBS pathname. Warn and use it. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname '%s' to %s", p_mbs,
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
ret2 = ARCHIVE_WARN;
|
||||
} else {
|
||||
/* We have no MBS pathname. Fail. */
|
||||
archive_set_error(&a->archive,
|
||||
ARCHIVE_ERRNO_FILE_FORMAT,
|
||||
"Can't translate pathname to %s",
|
||||
archive_string_conversion_charset_name(sconv));
|
||||
return ARCHIVE_FAILED;
|
||||
}
|
||||
}
|
||||
if (len > 0)
|
||||
archive_entry_set_pathname(zip->entry, p);
|
||||
|
||||
Reference in New Issue
Block a user