From: SanjayR Date: Fri, 22 May 2026 05:36:50 +0000 (+0530) Subject: 7zip writer: free file->utf16name on symlink UTF-8 conversion failure X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb4153fbc4e6cce16d3ddf94a4894d3341670b9f;p=thirdparty%2Flibarchive.git 7zip writer: free file->utf16name on symlink UTF-8 conversion failure file_new() at archive_write_set_format_7zip.c:1688 calls free(file) on the symlink-UTF8-failure branch, leaving file->utf16name (allocated at line 1666) leaked. The two earlier free(file) calls in this function (lines 1656, 1668) are correct because they happen BEFORE utf16name is allocated, but the third one happens after. The rest of the function uses file_free() on every other post-utf16name error path; file_free() does free(file->utf16name) followed by free(file), which is the cleanup convention. Replacing free(file) with file_free(file) makes the symlink-error branch consistent with everything else. Reproduces with bsdtar in a non-UTF-8 locale with a non-UTF-8 symlink target: ln -s "$(printf 'broken_\\xff\\xfe_link')" sym LC_ALL=C ASAN_OPTIONS=detect_leaks=1 \ bsdtar --format=7zip -cf out.7z sym => LeakSanitizer: 30-48 byte direct leak; allocation site is file_new (archive_write_set_format_7zip.c:1666). Equivalent trigger: any libarchive caller that sets AE_IFLNK filetype on an entry without ever calling archive_entry_set_symlink() (then archive_entry_symlink_utf8() returns NULL and the error branch fires). Code unchanged since the 7zip writer's introduction; no existing test exercises this error path. Identified by Neurolog, a code-analysis tool the reporter is developing that combines Souffle Datalog with LLM-assisted fact extraction. The reproducer was separately validated under LeakSanitizer against current master. --- diff --git a/libarchive/archive_write_set_format_7zip.c b/libarchive/archive_write_set_format_7zip.c index 1bbd24d63..a0dcc5376 100644 --- a/libarchive/archive_write_set_format_7zip.c +++ b/libarchive/archive_write_set_format_7zip.c @@ -1685,7 +1685,7 @@ file_new(struct archive_write *a, struct archive_entry *entry, const char* linkpath; linkpath = archive_entry_symlink_utf8(entry); if (linkpath == NULL) { - free(file); + file_free(file); archive_set_error(&a->archive, ARCHIVE_ERRNO_MISC, "symlink path could not be converted to UTF-8"); return (ARCHIVE_FAILED);