From 83c3383c0b13c852553cc44847e067e66af05199 Mon Sep 17 00:00:00 2001
From: Shuo Wang <wangshuo@kylinos.cn>
Date: Mon, 20 Jul 2026 11:48:48 +0800
Subject: [PATCH] Fix heap over-read in get_gnu_dumpdir and dumpdir_decoder

The dumpdir buffer is allocated with xmalloc(size)/ximalloc(size)
and filled via memcpy without appending a NUL terminator. Consumer
functions (dumpdir_size, dumpdir_ok, dumpdir_create) traverse it
with while(*p)/strlen, reading past the buffer on crafted archives
without a trailing NUL (CWE-125).

Fix: allocate size+2 and append two NUL terminators in both
get_gnu_dumpdir (incremen.c) and dumpdir_decoder (xheader.c).
Two NULs are needed because dumpdir_size() reads one byte past
the data to detect the end sentinel.
---
 src/incremen.c | 5 ++++-
 src/xheader.c  | 4 +++-
 2 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/src/incremen.c b/src/incremen.c
index 53c6b3f3..458a4f9a 100644
--- a/src/incremen.c
+++ b/src/incremen.c
@@ -1503,7 +1503,7 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info)
 
   size = stat_info->stat.st_size;
 
-  archive_dir = xmalloc (size);
+  archive_dir = xmalloc (size + 2);
   to = archive_dir;
 
   set_next_block_after (current_header);
@@ -1525,6 +1525,9 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info)
 
   mv_end ();
 
+  *to = '\0';
+  to[1] = '\0';
+
   stat_info->dumpdir = archive_dir;
   stat_info->skipped = true; /* For skip_member() and friends
 				to work correctly */
diff --git a/src/xheader.c b/src/xheader.c
index 05f905ed..c08ffec9 100644
--- a/src/xheader.c
+++ b/src/xheader.c
@@ -1483,8 +1483,10 @@ dumpdir_decoder (struct tar_stat_info *st,
 		 char const *arg,
 		 idx_t size)
 {
-  st->dumpdir = ximalloc (size);
+  st->dumpdir = ximalloc (size + 2);
   memcpy (st->dumpdir, arg, size);
+  st->dumpdir[size] = '\0';
+  st->dumpdir[size + 1] = '\0';
 }
 
 static void
-- 
2.43.0

