]> git.ipfire.org Git - thirdparty/libarchive.git/commitdiff
archive_write: Set archive state to fatal if format or filters fail 2729/head
authorDag-Erling Smørgrav <des@des.no>
Mon, 8 Sep 2025 20:17:09 +0000 (22:17 +0200)
committerDag-Erling Smørgrav <des@des.no>
Mon, 8 Sep 2025 21:33:32 +0000 (23:33 +0200)
In archive_write_header(), if the format method or a filter flush method
fails, we set the archive state to fatal, but we did not do this in
archive_write_data() or archive_write_finish_entry().  There is no good
reason for this discrepancy.  Not setting the archive state to fatal
means a subsequent archive_write_free() will invoke archive_write_close()
which may retry the operation and cause archive_write_free() to return
an unexpected ARCHIVE_FATAL.

libarchive/archive_write.c

index 292f719dfc0fb91d3d1a9938db48d00db418c18d..9b9cb196f0f9c0d9bde2cdeec17d675760cafd02 100644 (file)
@@ -806,7 +806,10 @@ _archive_write_finish_entry(struct archive *_a)
        if (a->archive.state & ARCHIVE_STATE_DATA
            && a->format_finish_entry != NULL)
                ret = (a->format_finish_entry)(a);
-       a->archive.state = ARCHIVE_STATE_HEADER;
+       if (ret == ARCHIVE_FATAL)
+               a->archive.state = ARCHIVE_STATE_FATAL;
+       else
+               a->archive.state = ARCHIVE_STATE_HEADER;
        return (ret);
 }
 
@@ -818,6 +821,7 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s)
 {
        struct archive_write *a = (struct archive_write *)_a;
        const size_t max_write = INT_MAX;
+       int ret;
 
        archive_check_magic(&a->archive, ARCHIVE_WRITE_MAGIC,
            ARCHIVE_STATE_DATA, "archive_write_data");
@@ -825,7 +829,10 @@ _archive_write_data(struct archive *_a, const void *buff, size_t s)
        if (s > max_write)
                s = max_write;
        archive_clear_error(&a->archive);
-       return ((a->format_write_data)(a, buff, s));
+       ret = (a->format_write_data)(a, buff, s);
+       if (ret == ARCHIVE_FATAL)
+               a->archive.state = ARCHIVE_STATE_FATAL;
+       return (ret);
 }
 
 static struct archive_write_filter *