Port more code to UBSan, and fix alignment bug

Problem with extract_file reported by Kirill Furman in:
https://lists.gnu.org/r/bug-tar/2025-07/msg00003.html
Since the UBSan thing seems to be a recurring issue,
I fixed other instances of the problem that I found.
Also, I noticed that the same line of code had another failure to
conform to C23’s rules for pointers (an alignment issue not caught
by UBSan), so I fixed that too.  None of these issues matter on
practical production hosts.
* src/common.h (charptr): New function.
* src/buffer.c (available_space_after, short_read, flush_archive)
(backspace_output, try_new_volume, simple_flush_read)
(_gnu_flush_read, _gnu_flush_write):
* src/compare.c (read_and_process):
* src/create.c (write_eot, write_gnu_long_link)
(dump_regular_file, dump_dir0):
* src/extract.c (extract_file):
* src/incremen.c (get_gnu_dumpdir):
* src/list.c (read_header):
* src/sparse.c (sparse_dump_region, sparse_extract_region):
* src/system.c (sys_write_archive_buffer)
(sys_child_open_for_compress, sys_child_open_for_uncompress):
* src/update.c (append_file, update_archive):
Use it.
* src/buffer.c (set_next_block_after): Arg is now void *,
not union block *, since it need not be a valid union block * pointer
and this can matter on unusual or debugging implementations.
Turn a loop into an if so that the code is O(1) not O(N).
This commit is contained in:
Paul Eggert
2025-07-26 02:20:53 -07:00
parent 8921131877
commit 75735940f1
11 changed files with 80 additions and 62 deletions
+11 -11
View File
@@ -473,7 +473,7 @@ write_eot (void)
memset (pointer->buffer, 0, BLOCKSIZE);
set_next_block_after (pointer);
pointer = find_next_block ();
memset (pointer->buffer, 0, available_space_after (pointer));
memset (charptr (pointer), 0, available_space_after (pointer));
set_next_block_after (pointer);
}
@@ -540,16 +540,16 @@ write_gnu_long_link (struct tar_stat_info *st, const char *p, char type)
while (bufsize < size)
{
memcpy (header->buffer, p, bufsize);
memcpy (charptr (header), p, bufsize);
p += bufsize;
size -= bufsize;
set_next_block_after (header + ((bufsize - 1) >> LG_BLOCKSIZE));
set_next_block_after (charptr (header) + bufsize - 1);
header = find_next_block ();
bufsize = available_space_after (header);
}
memcpy (header->buffer, p, size);
memset (header->buffer + size, 0, bufsize - size);
set_next_block_after (header + ((size - 1) >> LG_BLOCKSIZE));
memcpy (charptr (header), p, size);
memset (charptr (header) + size, 0, bufsize - size);
set_next_block_after (charptr (header) + size - 1);
}
static int
@@ -1047,16 +1047,16 @@ dump_regular_file (int fd, struct tar_stat_info *st)
}
idx_t count = (fd <= 0 ? bufsize
: blocking_read (fd, blk->buffer, bufsize));
: blocking_read (fd, charptr (blk), bufsize));
size_left -= count;
set_next_block_after (blk + ((bufsize - 1) >> LG_BLOCKSIZE));
set_next_block_after (charptr (blk) + bufsize - 1);
if (count != bufsize)
{
if (errno)
read_diag_details (st->orig_file_name,
st->stat.st_size - size_left, bufsize);
memset (blk->buffer + count, 0, bufsize - count);
memset (charptr (blk) + count, 0, bufsize - count);
warnopt (WARN_FILE_SHRANK, 0,
ngettext (("%s: File shrank by %jd byte;"
" padding with zeros"),
@@ -1134,10 +1134,10 @@ dump_dir0 (struct tar_stat_info *st, char const *directory)
if (count)
memset (blk->buffer + size_left, 0, BLOCKSIZE - count);
}
memcpy (blk->buffer, p_buffer, bufsize);
memcpy (charptr (blk), p_buffer, bufsize);
size_left -= bufsize;
p_buffer += bufsize;
set_next_block_after (blk + ((bufsize - 1) >> LG_BLOCKSIZE));
set_next_block_after (charptr (blk) + bufsize - 1);
}
}
return;