libarchive: patch CVE-2025-5918

Pick commits per [1]

Additionally pick a commit needed to apply these cleanly.

[1] https://security-tracker.debian.org/tracker/CVE-2025-5918

(From OE-Core rev: 20687d6eed86003eacd5c91ebfd1101f6413ee3f)

Signed-off-by: Peter Marko <peter.marko@siemens.com>
Signed-off-by: Steve Sakoman <steve@sakoman.com>
This commit is contained in:
Peter Marko
2025-08-23 23:51:06 +02:00
committed by Steve Sakoman
parent 3c89580ab0
commit 1828ecc19f
4 changed files with 590 additions and 0 deletions

View File

@@ -0,0 +1,319 @@
From 89b8c35ff4b5addc08a85bf5df02b407f8af1f6c Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <stoeckmann@users.noreply.github.com>
Date: Sun, 6 Apr 2025 22:34:37 +0200
Subject: [PATCH] Improve lseek handling (#2564)
The skip functions are limited to 1 GB for cases in which libarchive
runs on a system with an off_t or long with 32 bits. This has negative
impact on 64 bit systems.
Instead, make sure that _all_ subsequent functions truncate properly.
Some of them already did and some had regressions for over 10 years.
Tests pass on Debian 12 i686 configured with --disable-largefile, i.e.
running with an off_t with 32 bits.
Casts added where needed to still pass MSVC builds.
Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/89b8c35ff4b5addc08a85bf5df02b407f8af1f6c]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---------
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
---
libarchive/archive_read.c | 6 ----
libarchive/archive_read_disk_posix.c | 3 +-
libarchive/archive_read_open_fd.c | 29 +++++++++++++------
libarchive/archive_read_open_file.c | 35 ++++++++++++-----------
libarchive/archive_read_open_filename.c | 37 ++++++++++++++++++-------
libarchive/test/read_open_memory.c | 2 +-
libarchive/test/test_sparse_basic.c | 6 ++--
libarchive/test/test_tar_large.c | 2 +-
8 files changed, 75 insertions(+), 45 deletions(-)
diff --git a/libarchive/archive_read.c b/libarchive/archive_read.c
index 822c534b..50db8701 100644
--- a/libarchive/archive_read.c
+++ b/libarchive/archive_read.c
@@ -176,15 +176,9 @@ client_skip_proxy(struct archive_read_filter *self, int64_t request)
return 0;
if (self->archive->client.skipper != NULL) {
- /* Seek requests over 1GiB are broken down into
- * multiple seeks. This avoids overflows when the
- * requests get passed through 32-bit arguments. */
- int64_t skip_limit = (int64_t)1 << 30;
int64_t total = 0;
for (;;) {
int64_t get, ask = request;
- if (ask > skip_limit)
- ask = skip_limit;
get = (self->archive->client.skipper)
(&self->archive->archive, self->data, ask);
total += get;
diff --git a/libarchive/archive_read_disk_posix.c b/libarchive/archive_read_disk_posix.c
index 09965eb9..4839d62b 100644
--- a/libarchive/archive_read_disk_posix.c
+++ b/libarchive/archive_read_disk_posix.c
@@ -778,7 +778,8 @@ _archive_read_data_block(struct archive *_a, const void **buff,
*/
if (t->current_sparse->offset > t->entry_total) {
if (lseek(t->entry_fd,
- (off_t)t->current_sparse->offset, SEEK_SET) < 0) {
+ (off_t)t->current_sparse->offset, SEEK_SET) !=
+ t->current_sparse->offset) {
archive_set_error(&a->archive, errno, "Seek error");
r = ARCHIVE_FATAL;
a->archive.state = ARCHIVE_STATE_FATAL;
diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c
index debfde20..3fd536d5 100644
--- a/libarchive/archive_read_open_fd.c
+++ b/libarchive/archive_read_open_fd.c
@@ -131,7 +131,7 @@ static int64_t
file_skip(struct archive *a, void *client_data, int64_t request)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
- int64_t skip = request;
+ off_t skip = (off_t)request;
int64_t old_offset, new_offset;
int skip_bits = sizeof(skip) * 8 - 1; /* off_t is a signed type. */
@@ -140,15 +140,15 @@ file_skip(struct archive *a, void *client_data, int64_t request)
/* Reduce a request that would overflow the 'skip' variable. */
if (sizeof(request) > sizeof(skip)) {
- int64_t max_skip =
+ const int64_t max_skip =
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
if (request > max_skip)
- skip = max_skip;
+ skip = (off_t)max_skip;
}
- /* Reduce request to the next smallest multiple of block_size */
- request = (request / mine->block_size) * mine->block_size;
- if (request == 0)
+ /* Reduce 'skip' to the next smallest multiple of block_size */
+ skip = (off_t)(((int64_t)skip / mine->block_size) * mine->block_size);
+ if (skip == 0)
return (0);
if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
@@ -178,11 +178,24 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_fd_data *mine = (struct read_fd_data *)client_data;
+ off_t seek = (off_t)request;
int64_t r;
+ int seek_bits = sizeof(seek) * 8 - 1; /* off_t is a signed type. */
/* We use off_t here because lseek() is declared that way. */
- /* See above for notes about when off_t is less than 64 bits. */
- r = lseek(mine->fd, request, whence);
+
+ /* Reduce a request that would overflow the 'seek' variable. */
+ 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;
+ }
+
+ r = lseek(mine->fd, seek, whence);
if (r >= 0)
return r;
diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
index ecd56dce..2829b9a5 100644
--- a/libarchive/archive_read_open_file.c
+++ b/libarchive/archive_read_open_file.c
@@ -145,7 +145,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
/* If request is too big for a long or an off_t, reduce it. */
if (sizeof(request) > sizeof(skip)) {
- int64_t max_skip =
+ const int64_t max_skip =
(((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
if (request > max_skip)
skip = max_skip;
@@ -176,39 +176,42 @@ FILE_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_FILE_data *mine = (struct read_FILE_data *)client_data;
#if HAVE__FSEEKI64
- int64_t skip = request;
+ int64_t seek = request;
#elif HAVE_FSEEKO
- off_t skip = (off_t)request;
+ off_t seek = (off_t)request;
#else
- long skip = (long)request;
+ long seek = (long)request;
#endif
- int skip_bits = sizeof(skip) * 8 - 1;
+ int seek_bits = sizeof(seek) * 8 - 1;
(void)a; /* UNUSED */
- /* If request is too big for a long or an off_t, reduce it. */
- if (sizeof(request) > sizeof(skip)) {
- int64_t max_skip =
- (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
- if (request > max_skip)
- skip = max_skip;
+ /* Reduce a request that would overflow the 'seek' variable. */
+ 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;
}
#ifdef __ANDROID__
/* Newer Android versions have fseeko...to meditate. */
- int64_t ret = lseek(fileno(mine->f), skip, whence);
+ int64_t ret = lseek(fileno(mine->f), seek, whence);
if (ret >= 0) {
return ret;
}
#elif HAVE__FSEEKI64
- if (_fseeki64(mine->f, skip, whence) == 0) {
+ if (_fseeki64(mine->f, seek, whence) == 0) {
return _ftelli64(mine->f);
}
#elif HAVE_FSEEKO
- if (fseeko(mine->f, skip, whence) == 0) {
+ if (fseeko(mine->f, seek, whence) == 0) {
return ftello(mine->f);
}
#else
- if (fseek(mine->f, skip, whence) == 0) {
+ if (fseek(mine->f, seek, whence) == 0) {
return ftell(mine->f);
}
#endif
@@ -226,4 +229,4 @@ FILE_close(struct archive *a, void *client_data)
free(mine->buffer);
free(mine);
return (ARCHIVE_OK);
-}
\ No newline at end of file
+}
diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c
index 05f0ffbd..3894b15c 100644
--- a/libarchive/archive_read_open_filename.c
+++ b/libarchive/archive_read_open_filename.c
@@ -479,20 +479,24 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
struct read_file_data *mine = (struct read_file_data *)client_data;
#if defined(_WIN32) && !defined(__CYGWIN__)
/* We use _lseeki64() on Windows. */
- int64_t old_offset, new_offset;
+ int64_t old_offset, new_offset, skip = request;
#else
- off_t old_offset, new_offset;
+ off_t old_offset, new_offset, skip = (off_t)request;
#endif
+ int skip_bits = sizeof(skip) * 8 - 1;
/* We use off_t here because lseek() is declared that way. */
- /* TODO: Deal with case where off_t isn't 64 bits.
- * This shouldn't be a problem on Linux or other POSIX
- * systems, since the configuration logic for libarchive
- * tries to obtain a 64-bit off_t.
- */
+ /* Reduce a request that would overflow the 'skip' variable. */
+ if (sizeof(request) > sizeof(skip)) {
+ const int64_t max_skip =
+ (((int64_t)1 << (skip_bits - 1)) - 1) * 2 + 1;
+ if (request > max_skip)
+ skip = max_skip;
+ }
+
if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
- (new_offset = lseek(mine->fd, request, SEEK_CUR)) >= 0)
+ (new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
return (new_offset - old_offset);
/* If lseek() fails, don't bother trying again. */
@@ -540,11 +544,24 @@ static int64_t
file_seek(struct archive *a, void *client_data, int64_t request, int whence)
{
struct read_file_data *mine = (struct read_file_data *)client_data;
+ off_t seek = (off_t)request;
int64_t r;
+ int seek_bits = sizeof(seek) * 8 - 1;
/* We use off_t here because lseek() is declared that way. */
- /* See above for notes about when off_t is less than 64 bits. */
- r = lseek(mine->fd, request, whence);
+
+ /* Reduce a request that would overflow the 'seek' variable. */
+ 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;
+ }
+
+ r = lseek(mine->fd, seek, whence);
if (r >= 0)
return r;
diff --git a/libarchive/test/read_open_memory.c b/libarchive/test/read_open_memory.c
index 6d2468cd..9262ab9d 100644
--- a/libarchive/test/read_open_memory.c
+++ b/libarchive/test/read_open_memory.c
@@ -167,7 +167,7 @@ memory_read_skip(struct archive *a, void *client_data, int64_t skip)
(void)a; /* UNUSED */
/* We can't skip by more than is available. */
- if ((off_t)skip > (off_t)(mine->end - mine->p))
+ if (skip > mine->end - mine->p)
skip = mine->end - mine->p;
/* Always do small skips by prime amounts. */
if (skip > 71)
diff --git a/libarchive/test/test_sparse_basic.c b/libarchive/test/test_sparse_basic.c
index 23cde567..93710cb6 100644
--- a/libarchive/test/test_sparse_basic.c
+++ b/libarchive/test/test_sparse_basic.c
@@ -608,7 +608,8 @@ DEFINE_TEST(test_sparse_basic)
verify_sparse_file(a, "file2", sparse_file2, 20);
/* Encoded non sparse; expect a data block but no sparse entries. */
verify_sparse_file(a, "file3", sparse_file3, 0);
- verify_sparse_file(a, "file4", sparse_file4, 2);
+ if (sizeof(off_t) > 4)
+ verify_sparse_file(a, "file4", sparse_file4, 2);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
@@ -635,7 +636,8 @@ DEFINE_TEST(test_sparse_basic)
verify_sparse_file(a, "file1", sparse_file1, 0);
verify_sparse_file(a, "file2", sparse_file2, 0);
verify_sparse_file(a, "file3", sparse_file3, 0);
- verify_sparse_file(a, "file4", sparse_file4, 0);
+ if (sizeof(off_t) > 4)
+ verify_sparse_file(a, "file4", sparse_file4, 0);
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
diff --git a/libarchive/test/test_tar_large.c b/libarchive/test/test_tar_large.c
index c1f37916..1cde3218 100644
--- a/libarchive/test/test_tar_large.c
+++ b/libarchive/test/test_tar_large.c
@@ -175,7 +175,7 @@ memory_read_skip(struct archive *a, void *_private, int64_t skip)
}
if (private->filebytes > 0) {
if (private->filebytes < skip)
- skip = (off_t)private->filebytes;
+ skip = private->filebytes;
private->filebytes -= skip;
} else {
skip = 0;

View File

@@ -0,0 +1,217 @@
From dcbf1e0ededa95849f098d154a25876ed5754bcf Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <stoeckmann@users.noreply.github.com>
Date: Tue, 15 Apr 2025 06:02:17 +0200
Subject: [PATCH] Do not skip past EOF while reading (#2584)
Make sure to not skip past end of file for better error messages. One
such example is now visible with rar testsuite. You can see the
difference already by an actually not useless use of cat:
```
$ cat .../test_read_format_rar_ppmd_use_after_free.rar | bsdtar -t
bsdtar: Archive entry has empty or unreadable filename ... skipping.
bsdtar: Archive entry has empty or unreadable filename ... skipping.
bsdtar: Truncated input file (needed 119 bytes, only 0 available)
bsdtar: Error exit delayed from previous errors.
```
compared to
```
$ bsdtar -tf .../test_read_format_rar_ppmd_use_after_free.rar
bsdtar: Archive entry has empty or unreadable filename ... skipping.
bsdtar: Archive entry has empty or unreadable filename ... skipping.
bsdtar: Error exit delayed from previous errors.
```
Since the former cannot lseek, the error is a different one
(ARCHIVE_FATAL vs ARCHIVE_EOF). The piped version states explicitly that
truncation occurred, while the latter states EOF because the skip past
the end of file was successful.
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
CVE: CVE-2025-5918
Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/dcbf1e0ededa95849f098d154a25876ed5754bcf]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
libarchive/archive_read_open_fd.c | 13 +++++++---
libarchive/archive_read_open_file.c | 33 +++++++++++++++++++------
libarchive/archive_read_open_filename.c | 16 +++++++++---
libarchive/test/test_read_format_rar.c | 6 ++---
4 files changed, 50 insertions(+), 18 deletions(-)
diff --git a/libarchive/archive_read_open_fd.c b/libarchive/archive_read_open_fd.c
index 3fd536d5..dc7c9e52 100644
--- a/libarchive/archive_read_open_fd.c
+++ b/libarchive/archive_read_open_fd.c
@@ -52,6 +52,7 @@
struct read_fd_data {
int fd;
size_t block_size;
+ int64_t size;
char use_lseek;
void *buffer;
};
@@ -95,6 +96,7 @@ archive_read_open_fd(struct archive *a, int fd, size_t block_size)
if (S_ISREG(st.st_mode)) {
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
mine->use_lseek = 1;
+ mine->size = st.st_size;
}
#if defined(__CYGWIN__) || defined(_WIN32)
setmode(mine->fd, O_BINARY);
@@ -151,9 +153,14 @@ file_skip(struct archive *a, void *client_data, int64_t request)
if (skip == 0)
return (0);
- if (((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) &&
- ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0))
- return (new_offset - old_offset);
+ if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
+ if (old_offset >= mine->size ||
+ skip > mine->size - old_offset) {
+ /* Do not seek past end of file. */
+ errno = ESPIPE;
+ } else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
+ return (new_offset - old_offset);
+ }
/* If seek failed once, it will probably fail again. */
mine->use_lseek = 0;
diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
index 2829b9a5..6ed18a0c 100644
--- a/libarchive/archive_read_open_file.c
+++ b/libarchive/archive_read_open_file.c
@@ -52,6 +52,7 @@
struct read_FILE_data {
FILE *f;
size_t block_size;
+ int64_t size;
void *buffer;
char can_skip;
};
@@ -91,6 +92,7 @@ archive_read_open_FILE(struct archive *a, FILE *f)
archive_read_extract_set_skip_file(a, st.st_dev, st.st_ino);
/* Enable the seek optimization only for regular files. */
mine->can_skip = 1;
+ mine->size = st.st_size;
}
#if defined(__CYGWIN__) || defined(_WIN32)
@@ -130,6 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
#else
long skip = (long)request;
#endif
+ int64_t old_offset, new_offset;
int skip_bits = sizeof(skip) * 8 - 1;
(void)a; /* UNUSED */
@@ -153,19 +156,33 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
#ifdef __ANDROID__
/* fileno() isn't safe on all platforms ... see above. */
- if (lseek(fileno(mine->f), skip, SEEK_CUR) < 0)
+ old_offset = lseek(fileno(mine->f), 0, SEEK_CUR);
#elif HAVE__FSEEKI64
- if (_fseeki64(mine->f, skip, SEEK_CUR) != 0)
+ old_offset = _ftelli64(mine->f);
#elif HAVE_FSEEKO
- if (fseeko(mine->f, skip, SEEK_CUR) != 0)
+ old_offset = ftello(mine->f);
#else
- if (fseek(mine->f, skip, SEEK_CUR) != 0)
+ old_offset = ftell(mine->f);
#endif
- {
- mine->can_skip = 0;
- return (0);
+ if (old_offset >= 0) {
+ if (old_offset < mine->size &&
+ skip <= mine->size - old_offset) {
+#ifdef __ANDROID__
+ new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
+#elif HAVE__FSEEKI64
+ new_offset = _fseeki64(mine->f, skip, SEEK_CUR);
+#elif HAVE_FSEEKO
+ new_offset = fseeko(mine->f, skip, SEEK_CUR);
+#else
+ new_offset = fseek(mine->f, skip, SEEK_CUR);
+#endif
+ if (new_offset >= 0)
+ return (new_offset - old_offset);
+ }
}
- return (request);
+
+ mine->can_skip = 0;
+ return (0);
}
/*
diff --git a/libarchive/archive_read_open_filename.c b/libarchive/archive_read_open_filename.c
index 3894b15c..5f5b3f1f 100644
--- a/libarchive/archive_read_open_filename.c
+++ b/libarchive/archive_read_open_filename.c
@@ -74,6 +74,7 @@ struct read_file_data {
size_t block_size;
void *buffer;
mode_t st_mode; /* Mode bits for opened file. */
+ int64_t size;
char use_lseek;
enum fnt_e { FNT_STDIN, FNT_MBS, FNT_WCS } filename_type;
union {
@@ -400,8 +401,10 @@ file_open(struct archive *a, void *client_data)
mine->st_mode = st.st_mode;
/* Disk-like inputs can use lseek(). */
- if (is_disk_like)
+ if (is_disk_like) {
mine->use_lseek = 1;
+ mine->size = st.st_size;
+ }
return (ARCHIVE_OK);
fail:
@@ -495,9 +498,14 @@ file_skip_lseek(struct archive *a, void *client_data, int64_t request)
skip = max_skip;
}
- if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0 &&
- (new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
- return (new_offset - old_offset);
+ if ((old_offset = lseek(mine->fd, 0, SEEK_CUR)) >= 0) {
+ if (old_offset >= mine->size ||
+ skip > mine->size - old_offset) {
+ /* Do not seek past end of file. */
+ errno = ESPIPE;
+ } else if ((new_offset = lseek(mine->fd, skip, SEEK_CUR)) >= 0)
+ return (new_offset - old_offset);
+ }
/* If lseek() fails, don't bother trying again. */
mine->use_lseek = 0;
diff --git a/libarchive/test/test_read_format_rar.c b/libarchive/test/test_read_format_rar.c
index dce567af..fce44a9d 100644
--- a/libarchive/test/test_read_format_rar.c
+++ b/libarchive/test/test_read_format_rar.c
@@ -3829,8 +3829,8 @@ DEFINE_TEST(test_read_format_rar_ppmd_use_after_free)
assertA(ARCHIVE_OK == archive_read_next_header(a, &ae));
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
- /* Test EOF */
- assertA(1 == archive_read_next_header(a, &ae));
+ /* Test for truncation */
+ assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
@@ -3856,7 +3856,7 @@ DEFINE_TEST(test_read_format_rar_ppmd_use_after_free2)
assertA(archive_read_data(a, buf, sizeof(buf)) <= 0);
/* Test EOF */
- assertA(1 == archive_read_next_header(a, &ae));
+ assertA(ARCHIVE_FATAL == archive_read_next_header(a, &ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));

View File

@@ -0,0 +1,51 @@
From 51b4c35bb38b7df4af24de7f103863dd79129b01 Mon Sep 17 00:00:00 2001
From: Tobias Stoeckmann <tobias@stoeckmann.org>
Date: Tue, 27 May 2025 17:09:12 +0200
Subject: [PATCH] Fix FILE_skip regression
The fseek* family of functions return 0 on success, not the new offset.
This is only true for lseek.
Fixes https://github.com/libarchive/libarchive/issues/2641
Fixes dcbf1e0ededa95849f098d154a25876ed5754bcf
Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
CVE: CVE-2025-5918
Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/51b4c35bb38b7df4af24de7f103863dd79129b01]
Signed-off-by: Peter Marko <peter.marko@siemens.com>
---
libarchive/archive_read_open_file.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/libarchive/archive_read_open_file.c b/libarchive/archive_read_open_file.c
index 6ed18a0c..742923ab 100644
--- a/libarchive/archive_read_open_file.c
+++ b/libarchive/archive_read_open_file.c
@@ -132,7 +132,7 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
#else
long skip = (long)request;
#endif
- int64_t old_offset, new_offset;
+ int64_t old_offset, new_offset = -1;
int skip_bits = sizeof(skip) * 8 - 1;
(void)a; /* UNUSED */
@@ -170,11 +170,14 @@ FILE_skip(struct archive *a, void *client_data, int64_t request)
#ifdef __ANDROID__
new_offset = lseek(fileno(mine->f), skip, SEEK_CUR);
#elif HAVE__FSEEKI64
- new_offset = _fseeki64(mine->f, skip, SEEK_CUR);
+ if (_fseeki64(mine->f, skip, SEEK_CUR) == 0)
+ new_offset = _ftelli64(mine->f);
#elif HAVE_FSEEKO
- new_offset = fseeko(mine->f, skip, SEEK_CUR);
+ if (fseeko(mine->f, skip, SEEK_CUR) == 0)
+ new_offset = ftello(mine->f);
#else
- new_offset = fseek(mine->f, skip, SEEK_CUR);
+ if (fseek(mine->f, skip, SEEK_CUR) == 0)
+ new_offset = ftell(mine->f);
#endif
if (new_offset >= 0)
return (new_offset - old_offset);

View File

@@ -34,6 +34,9 @@ SRC_URI = "https://libarchive.org/downloads/libarchive-${PV}.tar.gz \
file://CVE-2025-5915.patch \
file://CVE-2025-5916.patch \
file://CVE-2025-5917.patch \
file://0001-Improve-lseek-handling-2564.patch \
file://CVE-2025-5918-01.patch \
file://CVE-2025-5918-02.patch \
"
UPSTREAM_CHECK_URI = "http://libarchive.org/"