Check if the dumpdir read from the archive is well-formed before using it.

* src/common.h (dumpdir_ok): New proto.
* src/incremen.c (dumpdir_ok): Take size as the second argument.
Verify if the last byte is 0 and the dumpdir contains 0 or more
nul-terminated strings.
(get_gnu_dumpdir): Check if the obtained dumpdir is ok. Clear the
is_dumpdir flag if it is not.
* src/xheader.c (dumpdir_decoder) Verify if the obtained dumpdir is
ok.
This commit is contained in:
Sergey Poznyakoff
2026-07-21 22:49:04 +03:00
parent 08c3fc2e93
commit 87819f9f0a
3 changed files with 25 additions and 9 deletions
+1
View File
@@ -589,6 +589,7 @@ void purge_directory (char const *directory_name);
void list_dumpdir (char *buffer, idx_t size);
void update_parent_directory (struct tar_stat_info *st);
bool dumpdir_ok (char const *dumpdir, idx_t size);
idx_t dumpdir_size (const char *p);
bool is_dumpdir (struct tar_stat_info *stat_info);
void clear_directory_table (void);
+17 -7
View File
@@ -123,6 +123,7 @@ dir_set_flag (struct directory *d, int f)
{
d->flags |= f;
}
static void
dir_clear_flag (struct directory *d, int f)
{
@@ -1525,6 +1526,12 @@ get_gnu_dumpdir (struct tar_stat_info *stat_info)
mv_end ();
if (!dumpdir_ok (archive_dir, stat_info->stat.st_size))
{
stat_info->is_dumpdir = false;
free (archive_dir);
archive_dir = NULL;
}
stat_info->dumpdir = archive_dir;
stat_info->skipped = true; /* For skip_member() and friends
to work correctly */
@@ -1541,13 +1548,20 @@ is_dumpdir (struct tar_stat_info *stat_info)
return stat_info->is_dumpdir;
}
static bool
dumpdir_ok (char *dumpdir)
bool
dumpdir_ok (char const *dumpdir, idx_t size)
{
char *p;
char const *p;
bool has_tempdir = false;
char expect = '\0';
if (!(size > 0 &&
dumpdir[size-1] == 0 && (size == 1 || dumpdir[size-2] == 0)))
{
paxerror (0, _("Malformed dumpdir: missing terminator"));
return false;
}
for (p = dumpdir; *p; p += strlen (p) + 1)
{
if (expect && *p != expect)
@@ -1640,10 +1654,6 @@ purge_directory (char const *directory_name)
case, we don't have to delete any files out of it. */
return;
/* Verify if dump directory is sane */
if (!dumpdir_ok (current_stat_info.dumpdir))
return;
/* Process renames */
for (arc = current_stat_info.dumpdir; *arc; arc += strlen (arc) + 1)
{
+7 -2
View File
@@ -1483,8 +1483,13 @@ dumpdir_decoder (struct tar_stat_info *st,
char const *arg,
idx_t size)
{
st->dumpdir = ximalloc (size);
memcpy (st->dumpdir, arg, size);
if (dumpdir_ok (arg, size))
{
st->dumpdir = ximalloc (size);
memcpy (st->dumpdir, arg, size);
}
else
paxerror (0, _("Malformed dumpdir: missing terminator"));
}
static void