From: Tobias Stoeckmann Date: Sat, 16 May 2026 19:21:36 +0000 (+0200) Subject: xar: Fix OOB accesses with fflags X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=583b5e4d2f9a7f169dd2c47472ebab484bd5ecb4;p=thirdparty%2Flibarchive.git xar: Fix OOB accesses with fflags If multiple fflags are added to archive, a stack out of boundary is triggered due to insufficient array allocation. Also, if flags with long names are supplied, an out of boundary read can occur. Resolves GHSA-wfvr-54j8-47r9. Signed-off-by: Tobias Stoeckmann --- diff --git a/libarchive/archive_write_set_format_xar.c b/libarchive/archive_write_set_format_xar.c index c9d9d686d..134238d5e 100644 --- a/libarchive/archive_write_set_format_xar.c +++ b/libarchive/archive_write_set_format_xar.c @@ -1110,30 +1110,27 @@ make_fflags_entry(struct archive_write *a, struct xml_writer *writer, { NULL, NULL} }; const struct flagentry *fe, *flagentry; -#define FLAGENTRY_MAXSIZE ((sizeof(flagbsd)+sizeof(flagext2))/sizeof(flagbsd)) - const struct flagentry *avail[FLAGENTRY_MAXSIZE]; const char *p; - int i, n, r; + int r, started; if (strcmp(element, "ext2") == 0) flagentry = flagext2; else flagentry = flagbsd; - n = 0; p = fflags_text; + started = 0; do { - const char *cp; + const char *cp, *name = NULL; cp = strchr(p, ','); if (cp == NULL) cp = p + strlen(p); for (fe = flagentry; fe->name != NULL; fe++) { - if (fe->name[cp - p] != '\0' - || p[0] != fe->name[0]) - continue; if (strncmp(p, fe->name, cp - p) == 0) { - avail[n++] = fe; + if (fe->name[cp - p] != '\0') + continue; + name = fe->xarname; break; } } @@ -1141,23 +1138,26 @@ make_fflags_entry(struct archive_write *a, struct xml_writer *writer, p = cp + 1; else p = NULL; - } while (p != NULL); - if (n > 0) { - r = xml_writer_start_element(writer, element); - if (r < 0) { - archive_set_error(&a->archive, - ARCHIVE_ERRNO_MISC, - "xml_writer_start_element() failed: %d", r); - return (ARCHIVE_FATAL); - } - for (i = 0; i < n; i++) { - r = xmlwrite_string(a, writer, - avail[i]->xarname, NULL); + if (name != NULL) { + if (!started) { + r = xml_writer_start_element(writer, element); + if (r < 0) { + archive_set_error(&a->archive, + ARCHIVE_ERRNO_MISC, + "xml_writer_start_element()" + " failed: %d", r); + return (ARCHIVE_FATAL); + } + started = 1; + } + r = xmlwrite_string(a, writer, name, NULL); if (r != ARCHIVE_OK) return (r); } + } while (p != NULL); + if (started) { r = xml_writer_end_element(writer); if (r < 0) { archive_set_error(&a->archive,