diff --git a/multiarc/src/formats/libarch/libarch_utils.cpp b/multiarc/src/formats/libarch/libarch_utils.cpp index c32172b9c..fa88ab554 100644 --- a/multiarc/src/formats/libarch/libarch_utils.cpp +++ b/multiarc/src/formats/libarch/libarch_utils.cpp @@ -119,6 +119,14 @@ LibArchOpenRead::LibArchOpenRead(const char *name, const char *cmd, const char * } _fmt = archive_format(_arc); + if (_fmt == ARCHIVE_FORMAT_MTREE && archive_filter_count(_arc) <= 1 + && !StrEndsBy(name, ".tree") && !StrEndsBy(name, ".mtree")) { + // https://github.com/elfmz/far2l/issues/1887 + // https://github.com/libarchive/libarchive/issues/1051 + EnsureClosed(); + throw std::runtime_error("mtree avoided"); + } + if (_fmt == ARCHIVE_FORMAT_RAW && _ae != nullptr) { const char *name_part = strrchr(name, '/'); std::string arc_raw_name(name_part ? name_part + 1 : name); diff --git a/utils/include/utils.h b/utils/include/utils.h index 3660a3204..98c7931e4 100644 --- a/utils/include/utils.h +++ b/utils/include/utils.h @@ -99,6 +99,17 @@ template return i; } +template + size_t StrEndsBy(const CharT *haystack, const CharT *needle) +{ + const size_t hl = tzlen(haystack); + const size_t l = tzlen(needle); + if (!l || hl < l) + return 0; + + return memcmp(haystack + hl - l, needle, l * sizeof(CharT)) ? 0 : l; +} + template size_t StrEndsBy(const StrT &haystack, const typename StrT::value_type *needle) {