Thanks for reporting that. I installed the attached fix, which is more
elaborate than what you suggested but simplifies the code and should
help avoid similar problems in the future.From 78d4ccd75531ac61552a6aa97c6df7238b16cbd3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Mon, 11 Sep 2023 01:17:02 -0500
Subject: [PATCH] Fix pointer bug in drop_volume_label_suffix
Problem reported by Marc Espie in:
https://lists.gnu.org/r/bug-tar/2023-09/msg00003.html
* src/buffer.c (drop_volume_label_suffix):
Redo to not compute a pointer before the start of a buffer,
as this is not portable.
---
THANKS | 1 +
src/buffer.c | 32 ++++++++++----------------------
src/common.h | 3 ++-
3 files changed, 13 insertions(+), 23 deletions(-)
diff --git a/THANKS b/THANKS
index b51f1694..fb8634e1 100644
--- a/THANKS
+++ b/THANKS
@@ -327,6 +327,7 @@ Mads Martin Joergensen m...@suse.de
Manfred Weichel manfred.weic...@mch.sni.de
Manuel Munier manuel.mun...@loria.fr
Marc Boucher m...@cam.org
+Marc Espie marc.espie.open...@gmail.com
Marc Ewing m...@redhat.com
Marcin Matuszewski mar...@frodo.nask.org.pl
Marcus Daniels mar...@sysc.pdx.edu
diff --git a/src/buffer.c b/src/buffer.c
index 8a575f9a..7f353fa4 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -1565,33 +1565,21 @@ try_new_volume (void)
}
-#define VOLUME_TEXT " Volume "
-#define VOLUME_TEXT_LEN (sizeof VOLUME_TEXT - 1)
-
char *
drop_volume_label_suffix (const char *label)
{
- const char *p;
- size_t len = strlen (label);
-
- if (len < 1)
- return NULL;
+ static char const VOLUME_TEXT[] = " Volume ";
+ idx_t VOLUME_TEXT_LEN = sizeof VOLUME_TEXT - 1;
+ idx_t prefix_len = 0;
- for (p = label + len - 1; p > label && isdigit ((unsigned char) *p); p--)
- ;
- if (p > label && p - (VOLUME_TEXT_LEN - 1) > label)
- {
- p -= VOLUME_TEXT_LEN - 1;
- if (memcmp (p, VOLUME_TEXT, VOLUME_TEXT_LEN) == 0)
- {
- char *s = xmalloc ((len = p - label) + 1);
- memcpy (s, label, len);
- s[len] = 0;
- return s;
- }
- }
+ for (idx_t i = 0; label[i]; i++)
+ if (!isdigit ((unsigned char) label[i]))
+ prefix_len = i + 1;
- return NULL;
+ ptrdiff_t len = prefix_len - VOLUME_TEXT_LEN;
+ return (0 <= len && memcmp (label + len, VOLUME_TEXT, VOLUME_TEXT_LEN) == 0
+ ? ximemdup0 (label, len)
+ : NULL);
}
/* Check LABEL against the volume label, seen as a globbing
diff --git a/src/common.h b/src/common.h
index 89912567..55576ef3 100644
--- a/src/common.h
+++ b/src/common.h
@@ -460,7 +460,8 @@ extern uintmax_t continued_file_size;
extern uintmax_t continued_file_offset;
extern off_t records_written;
-char *drop_volume_label_suffix (const char *label);
+char *drop_volume_label_suffix (const char *label)
+ _GL_ATTRIBUTE_MALLOC _GL_ATTRIBUTE_DEALLOC_FREE;
size_t available_space_after (union block *pointer);
off_t current_block_ordinal (void);
--
2.41.0