xar: add regression test for atou64 numeric field over-read

Exercise atou64() through a TOC numeric element (<inode>) read via the
expat backend, which hands the parser its raw, non-NUL-terminated
character-data buffer. Mirrors test_read_format_xar_base64_oob; build
with ASan for the out-of-bounds coverage.
This commit is contained in:
Kaif Khan committed 2026-06-26 13:57:11 +05:30
1 parent bad51bcc8d
commit 0352fe5033
3 files changed
+45

No files matched your search

+1
View File
@@ -1083,6 +1083,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_atou64_overread.xar.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 \
+37
View File
@@ -1003,3 +1003,40 @@ DEFINE_TEST(test_read_format_xar_base64_oob)
assertEqualIntA(a, ARCHIVE_OK, archive_read_close(a));
assertEqualInt(ARCHIVE_OK, archive_read_free(a));
}
/*
* A numeric TOC field (here <inode>) is parsed by atou64(). Under the
* expat backend that function is handed the raw, non-NUL-terminated
* character-data buffer (libxml2 masks this by passing a strlen'd copy).
* The loop fetched the next digit with *++p before checking the remaining
* count, so an all-digit field whose content ends at the parser buffer
* read one byte past the supplied range. The parsed value is unchanged;
* only the stray read is gone. Build with ASan to catch the over-read.
*/
DEFINE_TEST(test_read_format_xar_atou64_overread)
{
const char *reffile = "test_read_format_xar_atou64_overread.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("num", archive_entry_pathname(ae));
assertEqualInt(1234567890, archive_entry_ino64(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_atou64_overread.xar
M>&%R(0`<``$`````````AP````````"R`````'C:-8Y+#H,P#$3WG"+RGAKH
MCTHF['J"]@"(N%4DXE245O3VS4>L_/0THS'UJYO4E^>W]=)!O:M`L8S>6'EV
M<+]=RQ9Z7=`ZS+I0BA8_QAOH82=6UH0.9!.<#(ZU?!QAHDTOOQ?KF"=,N'DK
<WK"NF_WA>#JWEXHPFSR`L9%&,:T2IB?^<Y@PE```
`
end