From: Tobias Stoeckmann Date: Fri, 27 Jun 2025 15:24:15 +0000 (+0200) Subject: Do not truncate seek requests X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3997a5f28a3988f3ec6a288dc5f9f5abb3439249;p=thirdparty%2Flibarchive.git Do not truncate seek requests If a seek cannot be fulfilled, fail directly with EOVERFLOW to match regular lseek behavior. Signed-off-by: Tobias Stoeckmann --- diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c index edb78b032..c85a62a3e 100644 --- a/libarchive/archive_read_open_fd.c +++ b/libarchive/archive_read_open_fd.c @@ -193,21 +193,22 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence) /* We use off_t here because lseek() is declared that way. */ - /* Reduce a request that would overflow the 'seek' variable. */ + /* Do not perform a seek which cannot be fulfilled. */ if (sizeof(request) > sizeof(seek)) { const int64_t max_seek = (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1; const int64_t min_seek = ~max_seek; - if (request > max_seek) - seek = (off_t)max_seek; - else if (request < min_seek) - seek = (off_t)min_seek; + if (request < min_seek || request > max_seek) { + errno = EOVERFLOW; + goto err; + } } r = lseek(mine->fd, seek, whence); if (r >= 0) return r; +err: if (errno == ESPIPE) { archive_set_error(a, errno, "A file descriptor(%d) is not seekable(PIPE)", mine->fd); diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c index b0eb5b0ea..6ca2ff191 100644 --- a/libarchive/archive_read_open_file.c +++ b/libarchive/archive_read_open_file.c @@ -206,15 +206,15 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence) int seek_bits = sizeof(seek) * 8 - 1; (void)a; /* UNUSED */ - /* Reduce a request that would overflow the 'seek' variable. */ + /* Do not perform a seek which cannot be fulfilled. */ if (sizeof(request) > sizeof(seek)) { const int64_t max_seek = (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1; const int64_t min_seek = ~max_seek; - if (request > max_seek) - seek = max_seek; - else if (request < min_seek) - seek = min_seek; + if (request < min_seek || request > max_seek) { + errno = EOVERFLOW; + goto err; + } } #ifdef __ANDROID__ @@ -237,6 +237,7 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence) } #endif /* If we arrive here, the input is corrupted or truncated so fail. */ +err: archive_set_error(a, errno, "Error seeking in FILE* pointer"); return (ARCHIVE_FATAL); } diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c index b9d30bf44..a910eefcb 100644 --- a/libarchive/archive_read_open_filename.c +++ b/libarchive/archive_read_open_filename.c @@ -564,15 +564,15 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence) /* We use off_t here because lseek() is declared that way. */ - /* Reduce a request that would overflow the 'seek' variable. */ + /* Do not perform a seek which cannot be fulfilled. */ if (sizeof(request) > sizeof(seek)) { const int64_t max_seek = (((int64_t)1 << (seek_bits - 1)) - 1) * 2 + 1; const int64_t min_seek = ~max_seek; - if (request > max_seek) - seek = (off_t)max_seek; - else if (request < min_seek) - seek = (off_t)min_seek; + if (request < min_seek || request > max_seek) { + errno = EOVERFLOW; + goto err; + } } r = lseek(mine->fd, seek, whence); @@ -580,6 +580,7 @@ file_seek(struct archive *a, void *client_data, int64_t request, int whence) return r; /* If the input is corrupted or truncated, fail. */ +err: if (mine->filename_type == FNT_STDIN) archive_set_error(a, errno, "Error seeking in stdin"); else if (mine->filename_type == FNT_MBS)