File wireshark-0102-CVE-2024-4855.patch of Package wireshark.33874

commit 00bc42b4cfe4b59ced0c1b79bd39d2b8db1c68cf
Author: John Thacker <johnthacker@gmail.com>
Date:   Fri Apr 19 09:47:45 2024 -0400

    editcap, libwiretap: Don't use array of initial DSBs after freeing
    
    wtap_dump_close frees the passed in GArray of initial DSBs, used
    by editcap for injecting DSBs from a file or list of files.
    
    Add functions to increment and decrement the reference count of
    an array of wtap blocks. Dereference the block of initial DSBs
    in wtap_dump_close() instead of freeing it. In editcap, before
    closing the dump file in cases where we intend to open a new
    file (e.g., with a maximum time value or a maximum packet count),
    reference the block.
    
    Fix #19782, #19783, #19784.
    
    (backported from commit be3550b3b138f39bebb87ac0b8490e75fc8cc847)

diff --git a/editcap.c b/editcap.c
index f64a815557..5d6a300662 100644
--- a/editcap.c
+++ b/editcap.c
@@ -1858,6 +1858,10 @@ main(int argc, char *argv[])
                 }
                 while (nstime_cmp(&rec->ts, &block_next) > 0) { /* time for the next file */
 
+                    /* We presumably want to write the DSBs from files given
+                     * on the command line to every file.
+                     */
+                    wtap_block_array_ref(params.dsbs_initial);
                     if (!wtap_dump_close(pdh, &write_err, &write_err_info)) {
                         cfile_close_failure_message(filename, write_err,
                                                     write_err_info);
@@ -1890,6 +1894,11 @@ main(int argc, char *argv[])
         if (split_packet_count != 0) {
             /* time for the next file? */
             if (written_count > 0 && (written_count % split_packet_count) == 0) {
+
+                /* We presumably want to write the DSBs from files given
+                 * on the command line to every file.
+                 */
+                wtap_block_array_ref(params.dsbs_initial);
                 if (!wtap_dump_close(pdh, &write_err, &write_err_info)) {
                     cfile_close_failure_message(filename, write_err,
                                                 write_err_info);
diff --git a/wiretap/file_access.c b/wiretap/file_access.c
index 80cf308b95..4218941257 100644
--- a/wiretap/file_access.c
+++ b/wiretap/file_access.c
@@ -2660,7 +2660,7 @@ wtap_dump_close_new_temp(wtap_dumper *wdh, gboolean *needs_reload,
 		*needs_reload = wdh->needs_reload;
 	g_free(wdh->priv);
 	wtap_block_array_free(wdh->interface_data);
-	wtap_block_array_free(wdh->dsbs_initial);
+	wtap_block_array_unref(wdh->dsbs_initial);
 	g_free(wdh);
 	return ret;
 }
diff --git a/wiretap/wtap.h b/wiretap/wtap.h
index d592884d17..75e4fc65eb 100644
--- a/wiretap/wtap.h
+++ b/wiretap/wtap.h
@@ -1419,7 +1419,8 @@ typedef struct addrinfo_lists {
  * @note The shb_hdr, idb_inf, and nrb_hdr arguments will be used until
  *     wtap_dump_close() is called, but will not be free'd by the dumper. If
  *     you created them, you must free them yourself after wtap_dump_close().
- *     dsbs_initial will be freed by wtap_dump_close(),
+ *     dsbs_initial will be unreferenced by wtap_dump_close(), so to reuse
+ *     them for another dump file, call wtap_block_array_ref() before closing.
  *     dsbs_growing typically refers to another wth->dsbs.
  *
  * @see wtap_dump_params_init, wtap_dump_params_cleanup.
diff --git a/wiretap/wtap_opttypes.c b/wiretap/wtap_opttypes.c
index 270553309e..135781b5be 100644
--- a/wiretap/wtap_opttypes.c
+++ b/wiretap/wtap_opttypes.c
@@ -436,6 +436,32 @@ void wtap_block_array_free(GArray* block_array)
     g_array_free(block_array, TRUE);
 }
 
+void wtap_block_array_ref(GArray* block_array)
+{
+    unsigned block;
+
+    if (block_array == NULL)
+        return;
+
+    for (block = 0; block < block_array->len; block++) {
+        wtap_block_ref(g_array_index(block_array, wtap_block_t, block));
+    }
+    g_array_ref(block_array);
+}
+
+void wtap_block_array_unref(GArray* block_array)
+{
+    unsigned block;
+
+    if (block_array == NULL)
+        return;
+
+    for (block = 0; block < block_array->len; block++) {
+        wtap_block_unref(g_array_index(block_array, wtap_block_t, block));
+    }
+    g_array_unref(block_array);
+}
+
 /*
  * Make a copy of a block.
  */
diff --git a/wiretap/wtap_opttypes.h b/wiretap/wtap_opttypes.h
index 15975d8a6b..b15b71cd5a 100644
--- a/wiretap/wtap_opttypes.h
+++ b/wiretap/wtap_opttypes.h
@@ -585,6 +585,29 @@ wtap_block_unref(wtap_block_t block);
 WS_DLL_PUBLIC void
 wtap_block_array_free(GArray* block_array);
 
+/** Decrement the reference count of an array of blocks
+ *
+ * Decrement the reference count of each block in the array
+ * and the GArray itself. Any element whose reference count
+ * drops to 0 will be freed. If the GArray and every block
+ * has a reference count of 1, this is the same as
+ * wtap_block_array_free().
+ *
+ * @param[in] block_array Array of blocks to be dereferenced
+ */
+WS_DLL_PUBLIC void
+wtap_block_array_unref(GArray* block_array);
+
+/** Increment the reference count of an array of blocks
+ *
+ * Increment the reference count of each block in the array
+ * and the GArray itself.
+ *
+ * @param[in] block_array Array of blocks to be referenced
+ */
+WS_DLL_PUBLIC void
+wtap_block_array_ref(GArray* block_array);
+
 /** Provide type of a block
  *
  * @param[in] block Block from which to retrieve mandatory data
openSUSE Build Service is sponsored by