new file mode 100644
@@ -0,0 +1,115 @@
+From eac15e252010c1189a5c0f461364dbe2cd2a68b1 Mon Sep 17 00:00:00 2001
+From: "Dustin L. Howett" <dustin@howett.net>
+Date: Thu, 9 May 2024 18:59:17 -0500
+Subject: [PATCH] rar4 reader: protect copy_from_lzss_window_to_unp() (#2172)
+
+copy_from_lzss_window_to_unp unnecessarily took an `int` parameter where
+both of its callers were holding a `size_t`.
+
+A lzss opcode chain could be constructed that resulted in a negative
+copy length, which when passed into memcpy would result in a very, very
+large positive number.
+
+Switching copy_from_lzss_window_to_unp to take a `size_t` allows it to
+properly bounds-check length.
+
+In addition, this patch also ensures that `length` is not itself larger
+than the destination buffer.
+
+CVE: CVE-2024-20696
+Upstream-Status: Backport [https://github.com/libarchive/libarchive/commit/eac15e252010c1189a5c0f461364dbe2cd2a68b1]
+
+Signed-off-by: Nitin Wankhade <nitin.wankhade@kpit.com>
+---
+
+--- a/libarchive/archive_read_support_format_rar.c 2024-04-26 14:52:59.000000000 +0530
++++ b/libarchive/archive_read_support_format_rar.c 2024-12-12 07:35:33.287412704 +0530
+@@ -432,7 +432,7 @@ static int make_table_recurse(struct arc
+ struct huffman_table_entry *, int, int);
+ static int expand(struct archive_read *, int64_t *);
+ static int copy_from_lzss_window_to_unp(struct archive_read *, const void **,
+- int64_t, int);
++ int64_t, size_t);
+ static const void *rar_read_ahead(struct archive_read *, size_t, ssize_t *);
+ static int parse_filter(struct archive_read *, const uint8_t *, uint16_t,
+ uint8_t);
+@@ -2060,7 +2060,7 @@ read_data_compressed(struct archive_read
+ bs = rar->unp_buffer_size - rar->unp_offset;
+ else
+ bs = (size_t)rar->bytes_uncopied;
+- ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs);
++ ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, bs);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ rar->offset += bs;
+@@ -2213,7 +2213,7 @@ read_data_compressed(struct archive_read
+ bs = rar->unp_buffer_size - rar->unp_offset;
+ else
+ bs = (size_t)rar->bytes_uncopied;
+- ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, (int)bs);
++ ret = copy_from_lzss_window_to_unp(a, buff, rar->offset, bs);
+ if (ret != ARCHIVE_OK)
+ return (ret);
+ rar->offset += bs;
+@@ -3094,11 +3094,16 @@ copy_from_lzss_window(struct archive_rea
+
+ static int
+ copy_from_lzss_window_to_unp(struct archive_read *a, const void **buffer,
+- int64_t startpos, int length)
++ int64_t startpos, size_t length)
+ {
+ int windowoffs, firstpart;
+ struct rar *rar = (struct rar *)(a->format->data);
+
++ if (length > rar->unp_buffer_size)
++ {
++ goto fatal;
++ }
++
+ if (!rar->unp_buffer)
+ {
+ if ((rar->unp_buffer = malloc(rar->unp_buffer_size)) == NULL)
+@@ -3110,17 +3115,17 @@ copy_from_lzss_window_to_unp(struct arch
+ }
+
+ windowoffs = lzss_offset_for_position(&rar->lzss, startpos);
+- if(windowoffs + length <= lzss_size(&rar->lzss)) {
++ if(windowoffs + length <= (size_t)lzss_size(&rar->lzss)) {
+ memcpy(&rar->unp_buffer[rar->unp_offset], &rar->lzss.window[windowoffs],
+ length);
+- } else if (length <= lzss_size(&rar->lzss)) {
++ } else if (length <= (size_t)lzss_size(&rar->lzss)) {
+ firstpart = lzss_size(&rar->lzss) - windowoffs;
+ if (firstpart < 0) {
+ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+ "Bad RAR file data");
+ return (ARCHIVE_FATAL);
+ }
+- if (firstpart < length) {
++ if ((size_t)firstpart < length) {
+ memcpy(&rar->unp_buffer[rar->unp_offset],
+ &rar->lzss.window[windowoffs], firstpart);
+ memcpy(&rar->unp_buffer[rar->unp_offset + firstpart],
+@@ -3130,9 +3135,7 @@ copy_from_lzss_window_to_unp(struct arch
+ &rar->lzss.window[windowoffs], length);
+ }
+ } else {
+- archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
+- "Bad RAR file data");
+- return (ARCHIVE_FATAL);
++ goto fatal;
+ }
+ rar->unp_offset += length;
+ if (rar->unp_offset >= rar->unp_buffer_size)
+@@ -3140,6 +3143,11 @@ copy_from_lzss_window_to_unp(struct arch
+ else
+ *buffer = NULL;
+ return (ARCHIVE_OK);
++
++fatal:
++ archive_set_error(&a->archive, ARCHIVE_ERRNO_FILE_FORMAT,
++ "Bad RAR file data");
++ return (ARCHIVE_FATAL);
+ }
+
+ static const void *
@@ -33,7 +33,8 @@ SRC_URI = "http://libarchive.org/downloads/libarchive-${PV}.tar.gz"
SRC_URI += "file://configurehack.patch \
file://CVE-2024-48957.patch \
file://CVE-2024-48958.patch \
- "
+ file://CVE-2024-20696.patch \
+ "
UPSTREAM_CHECK_URI = "http://libarchive.org/"
SRC_URI[sha256sum] = "7875d49596286055b52439ed42f044bd8ad426aa4cc5aabd96bfe7abb971d5e8"