cpio: test synthetic newc inode values

Exercise large inode values that collide after 32-bit truncation,
hardlink identity, and distinct device IDs. Update bsdcpio expectations
so successful synthesis produces no truncation warnings.
This commit is contained in:
Darren Carreras committed 2026-08-08 17:50:29 -04:00
1 parent f5509ae993
commit 48fc018080
2 files changed
+65 -38

No files matched your search

+2 -38
View File
@@ -113,42 +113,6 @@ DEFINE_TEST(test_format_newc)
/* Setup result message. */
memset(result, 0, sizeof(result));
if (is_LargeInode("file1")) {
strncat(result,
"bsdcpio: file1: large inode number truncated: ",
sizeof(result) - strlen(result) -1);
strncat(result, strerror(ERANGE),
sizeof(result) - strlen(result) -1);
strncat(result, "\n",
sizeof(result) - strlen(result) -1);
}
if (canSymlink() && is_LargeInode("symlink")) {
strncat(result,
"bsdcpio: symlink: large inode number truncated: ",
sizeof(result) - strlen(result) -1);
strncat(result, strerror(ERANGE),
sizeof(result) - strlen(result) -1);
strncat(result, "\n",
sizeof(result) - strlen(result) -1);
}
if (is_LargeInode("dir")) {
strncat(result,
"bsdcpio: dir: large inode number truncated: ",
sizeof(result) - strlen(result) -1);
strncat(result, strerror(ERANGE),
sizeof(result) - strlen(result) -1);
strncat(result, "\n",
sizeof(result) - strlen(result) -1);
}
if (is_LargeInode("hardlink")) {
strncat(result,
"bsdcpio: hardlink: large inode number truncated: ",
sizeof(result) - strlen(result) -1);
strncat(result, strerror(ERANGE),
sizeof(result) - strlen(result) -1);
strncat(result, "\n",
sizeof(result) - strlen(result) -1);
}
/* Record some facts about what we just created: */
now = time(NULL); /* They were all created w/in last two seconds. */
@@ -225,7 +189,7 @@ DEFINE_TEST(test_format_newc)
/* "symlink" pointing to "file1" */
assert(is_hex(e, 110));
assertEqualMem(e + 0, "070701", 6); /* Magic */
assert(is_hex(e + 6, 8)); /* ino */
assert(ino != from_hex(e + 6, 8)); /* ino */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Mode: Group members bits and others bits do not work. */
assertEqualInt(0xa180, from_hex(e + 14, 8) & 0xffc0);
@@ -258,7 +222,7 @@ DEFINE_TEST(test_format_newc)
/* "dir" */
assert(is_hex(e, 110));
assertEqualMem(e + 0, "070701", 6); /* Magic */
assert(is_hex(e + 6, 8)); /* ino */
assert(ino != from_hex(e + 6, 8)); /* ino */
#if defined(_WIN32) && !defined(__CYGWIN__)
/* Group members bits and others bits do not work. */
assertEqualInt(0x41c0, from_hex(e + 14, 8) & 0xffc0); /* Mode */
@@ -42,6 +42,24 @@ is_hex(const char *p, size_t l)
return (1);
}
static void
write_newc_entry(struct archive *a, const char *path, int64_t dev, int64_t ino,
int nlink)
{
struct archive_entry *entry;
assert((entry = archive_entry_new()) != NULL);
archive_entry_set_pathname(entry, path);
archive_entry_set_mode(entry, AE_IFREG | 0644);
archive_entry_set_size(entry, 0);
archive_entry_set_dev(entry, dev);
archive_entry_set_ino64(entry, ino);
archive_entry_set_nlink(entry, nlink);
assertEqualIntA(a, ARCHIVE_OK, archive_write_header(a, entry));
assertEqualIntA(a, ARCHIVE_OK, archive_write_finish_entry(a));
archive_entry_free(entry);
}
/*
* Detailed verification that cpio 'newc' archives are written with
* the correct format.
@@ -205,3 +223,48 @@ DEFINE_TEST(test_write_format_cpio_newc)
free(buff);
}
DEFINE_TEST(test_write_format_cpio_newc_large_inode)
{
struct archive *a;
char *buff;
const char *first, *again, *other, *small_inode, *different_device;
size_t buffsize = 10000;
size_t used;
buff = malloc(buffsize);
assert(buff != NULL);
assert((a = archive_write_new()) != NULL);
assertEqualIntA(a, ARCHIVE_OK, archive_write_set_format_cpio_newc(a));
assertEqualIntA(a, ARCHIVE_OK, archive_write_add_filter_none(a));
assertEqualIntA(a, ARCHIVE_OK,
archive_write_open_memory(a, buff, buffsize, &used));
write_newc_entry(a, "first", 12, INT64_C(0x100000001), 2);
write_newc_entry(a, "again", 12, INT64_C(0x100000001), 2);
write_newc_entry(a, "other", 12, INT64_C(0x200000001), 2);
write_newc_entry(a, "small", 12, 1, 1);
write_newc_entry(a, "dev13", 13, INT64_C(0x100000001), 2);
assertEqualIntA(a, ARCHIVE_OK, archive_write_close(a));
assertEqualInt(ARCHIVE_OK, archive_write_free(a));
/* Each entry is a 110-byte header plus a padded six-byte name. */
first = buff + 6;
again = buff + 116 + 6;
other = buff + 232 + 6;
small_inode = buff + 348 + 6;
different_device = buff + 464 + 6;
assertEqualMem(first, again, 8);
assert(memcmp(first, other, 8) != 0);
assert(memcmp(first, small_inode, 8) != 0);
assert(memcmp(first, different_device, 8) != 0);
assert(memcmp(other, small_inode, 8) != 0);
assert(memcmp(other, different_device, 8) != 0);
assert(memcmp(small_inode, different_device, 8) != 0);
assert(memcmp(first, "00000000", 8) != 0);
assert(memcmp(other, "00000000", 8) != 0);
assert(memcmp(small_inode, "00000000", 8) != 0);
assert(memcmp(different_device, "00000000", 8) != 0);
free(buff);
}