mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-31 16:57:10 +00:00
Correct the layering violation in read_body_to_string. The previous
version called the higher-level archive_read_data and archive_read_data_skip functions, which screwed up state management of those functions. This bit of mis-design has existed for a long time, but became a serious issue with the recent changes to the archive_read_data APIs, which added more internal state to the high-level archive_read_data function. Most common symptom was a failure to correctly read 'L' entries (long filename) from GNU-style archives, causing the message ": Can't open: No such file or directory" with an empty filename. Pointed out by: Numerous port build failures Thanks to: Kris Kennaway
This commit is contained in:
parent
63eaecc921
commit
7a4f3ab2c4
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=130098
@ -580,30 +580,37 @@ static int
|
||||
read_body_to_string(struct archive *a, struct tar *tar,
|
||||
struct archive_string *as, const void *h)
|
||||
{
|
||||
off_t size, padded_size;
|
||||
ssize_t bytes_read, bytes_to_copy;
|
||||
const struct archive_entry_header_ustar *header;
|
||||
off_t size;
|
||||
unsigned oldstate;
|
||||
int err, err2;
|
||||
const void *src;
|
||||
char *dest;
|
||||
|
||||
(void)tar; /* UNUSED */
|
||||
header = h;
|
||||
size = tar_atol(header->size, sizeof(header->size));
|
||||
|
||||
/* Temporarily fudge internal state for read_data call. */
|
||||
oldstate = a->state;
|
||||
a->state = ARCHIVE_STATE_DATA;
|
||||
|
||||
/* Read the body into the string. */
|
||||
tar->entry_bytes_remaining = size;
|
||||
tar->entry_padding = 0x1ff & -size;
|
||||
archive_string_ensure(as, size+1);
|
||||
err = archive_read_data_into_buffer(a, as->s, size);
|
||||
as->s[size] = 0; /* Null terminate name! */
|
||||
err2 = archive_read_data_skip(a); /* Resync for next header. */
|
||||
|
||||
/* Restore the state. */
|
||||
a->state = oldstate;
|
||||
|
||||
return (err_combine(err, err2));
|
||||
padded_size = (size + 511) & ~ 511;
|
||||
dest = as->s;
|
||||
while (padded_size > 0) {
|
||||
bytes_read = (a->compression_read_ahead)(a, &src, padded_size);
|
||||
if (bytes_read < 0)
|
||||
return (ARCHIVE_FATAL);
|
||||
if (bytes_read > padded_size)
|
||||
bytes_read = padded_size;
|
||||
(a->compression_read_consume)(a, bytes_read);
|
||||
bytes_to_copy = bytes_read;
|
||||
if ((off_t)bytes_to_copy > size)
|
||||
bytes_to_copy = (ssize_t)size;
|
||||
memcpy(dest, src, bytes_to_copy);
|
||||
dest += bytes_to_copy;
|
||||
size -= bytes_to_copy;
|
||||
padded_size -= bytes_read;
|
||||
}
|
||||
*dest = '\0';
|
||||
return (ARCHIVE_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user