Merge pull request #3175 from uchiha-bug-hunter/xar-base64-oob-read

xar: fix OOB read decoding odd-length base64 in strappend_base64
(cherry picked from commit 6f85565e42)
This commit is contained in:
Tim Kientzle authored and Martin Matuska committed 2026-07-26 20:08:58 +02:00
1 parent 31c306d809
commit 5aeb66ad30
4 files changed
+43 -1

No files matched your search

+1
View File
@@ -1081,6 +1081,7 @@ libarchive_test_EXTRA_DIST=\
libarchive/test/test_read_format_ustar_filename_koi8r.tar.Z.uu \
libarchive/test/test_read_format_warc.warc.uu \
libarchive/test/test_read_format_warc_incomplete.warc.uu \
libarchive/test/test_read_format_xar_base64_oob.xar.uu \
libarchive/test/test_read_format_xar_doublelink.xar.uu \
libarchive/test/test_read_format_xar_duplicate_filename_node.xar.uu \
libarchive/test/test_read_format_xar_large_mode.xar.uu \
+1 -1
View File
@@ -2631,7 +2631,7 @@ strappend_base64(struct xar *xar,
len = 0;
out = buff;
b = (const unsigned char *)s;
while (l > 0) {
while (l > 1) {
int n = 0;
if (base64[b[0]] < 0 || base64[b[1]] < 0)
+34
View File
@@ -969,3 +969,37 @@ DEFINE_TEST(test_read_format_xar_large_mode)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
/*
* A TOC with an odd-length base64-encoded <name> used to make
* strappend_base64() read one byte past the (non-NUL-terminated) expat
* character-data buffer and then underflow its size_t length counter.
* The trailing incomplete base64 character must be dropped; the rest of
* the name still decodes ("YWJjA" -> "abc").
*/
DEFINE_TEST(test_read_format_xar_base64_oob)
{
const char *reffile = "test_read_format_xar_base64_oob.xar";
struct archive_entry *ae;
struct archive *a;
int r;
extract_reference_file(reffile);
assert((a = archive_read_new()) != NULL);
assertA(0 == archive_read_support_filter_all(a));
r = archive_read_support_format_xar(a);
if (r == ARCHIVE_WARN) {
skipping("xar reading not fully supported on this platform");
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
return;
}
assertA(0 == archive_read_open_filename(a, reffile, 10240));
assertA(0 == archive_read_next_header(a, &ae));
assertEqualString("abc", archive_entry_pathname(ae));
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
@@ -0,0 +1,7 @@
begin 644 test_read_format_xar_base64_oob.xar
M>&%R(0`<``$`````````@@````````"E`````'C:L[&OR,U1*$LM*L[,S[-5
M,M0S4%)(S4O.3\G,2[=5"@UQT[50LK?CLJE(+++C4E"P*<E/!M%`5EIF3JI"
M9@I0CQ)$!"B6EYB;"M)>4EF0:JN4E%B<:F:B9!<9[I7E:*,/DH2K!*FP`QEA
7HP]F0LS4!XF`[=$'6V2C#[87`%#3+F\`
`
end