void
archive_entry_set_gid(struct archive_entry *entry, la_int64_t g)
{
+ if (g < 0) {
+ g = 0;
+ }
entry->stat_valid = 0;
entry->ae_stat.aest_gid = g;
entry->ae_set |= AE_SET_GID;
void
archive_entry_set_ino(struct archive_entry *entry, la_int64_t ino)
{
+ if (ino < 0) {
+ ino = 0;
+ }
entry->stat_valid = 0;
entry->ae_set |= AE_SET_INO;
entry->ae_stat.aest_ino = ino;
void
archive_entry_set_ino64(struct archive_entry *entry, la_int64_t ino)
{
+ if (ino < 0) {
+ ino = 0;
+ }
entry->stat_valid = 0;
entry->ae_set |= AE_SET_INO;
entry->ae_stat.aest_ino = ino;
void
archive_entry_set_size(struct archive_entry *entry, la_int64_t s)
{
+ if (s < 0) {
+ s = 0;
+ }
entry->stat_valid = 0;
entry->ae_stat.aest_size = s;
entry->ae_set |= AE_SET_SIZE;
void
archive_entry_set_uid(struct archive_entry *entry, la_int64_t u)
{
+ if (u < 0) {
+ u = 0;
+ }
entry->stat_valid = 0;
entry->ae_stat.aest_uid = u;
entry->ae_set |= AE_SET_UID;
header_afiol(struct archive_read *a, struct cpio *cpio,
struct archive_entry *entry, size_t *namelength, size_t *name_pad)
{
+ int64_t t;
const void *h;
const char *header;
archive_entry_set_dev(entry,
(dev_t)atol16(header + afiol_dev_offset, afiol_dev_size));
- archive_entry_set_ino(entry, atol16(header + afiol_ino_offset, afiol_ino_size));
+ t = atol16(header + afiol_ino_offset, afiol_ino_size);
+ if (t < 0) {
+ archive_set_error(&a->archive, 0, "Nonsensical ino value");
+ return (ARCHIVE_FATAL);
+ }
+ archive_entry_set_ino(entry, t);
archive_entry_set_mode(entry,
(mode_t)atol8(header + afiol_mode_offset, afiol_mode_size));
archive_entry_set_uid(entry, atol16(header + afiol_uid_offset, afiol_uid_size));
*namelength = (size_t)atol16(header + afiol_namesize_offset, afiol_namesize_size);
*name_pad = 0; /* No padding of filename. */
- cpio->entry_bytes_remaining =
- atol16(header + afiol_filesize_offset, afiol_filesize_size);
+ t = atol16(header + afiol_filesize_offset, afiol_filesize_size);
+ if (t < 0) {
+ archive_set_error(&a->archive, 0, "Nonsensical file size");
+ return (ARCHIVE_FATAL);
+ }
+ cpio->entry_bytes_remaining = t;
archive_entry_set_size(entry, cpio->entry_bytes_remaining);
cpio->entry_padding = 0;
__archive_read_consume(a, afiol_header_size);
static int64_t
atol8(const char *p, unsigned char_cnt)
{
- int64_t l;
+ uint64_t l;
int digit;
l = 0;
if (*p >= '0' && *p <= '7')
digit = *p - '0';
else
- return (l);
+ return ((int64_t)l);
p++;
l <<= 3;
l |= digit;
}
- return (l);
+ return ((int64_t)l);
}
static int64_t
atol16(const char *p, unsigned char_cnt)
{
- int64_t l;
+ uint64_t l;
int digit;
l = 0;
else if (*p >= '0' && *p <= '9')
digit = *p - '0';
else
- return (l);
+ return ((int64_t)l);
p++;
l <<= 4;
l |= digit;
}
- return (l);
+ return ((int64_t)l);
}
static int
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};
-/*
- * XXX This must be removed when we use int64_t for uid.
- */
-static int
-uid_size(void)
-{
- return (sizeof(uid_t));
-}
-
DEFINE_TEST(test_read_format_cpio_afio)
{
unsigned char *p;
*/
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualInt(17, archive_entry_size(ae));
- if (uid_size() > 4)
- assertEqualInt(65536, archive_entry_uid(ae));
+ assertEqualInt(65536, archive_entry_uid(ae));
assertEqualInt(archive_entry_is_encrypted(ae), 0);
assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);
assertA(archive_filter_code(a, 0) == ARCHIVE_FILTER_NONE);
free(p);
}
+
+// From OSS Fuzz Issue 70019:
+static unsigned char archive2[] = "070727bbbBbbbBabbbbbbcbcbbbbbbm726f777f777ffffffff518402ffffbbbabDDDDDDDDD7c7Ddd7DDDDnDDDdDDDB7777s77777777777C7727:";
+
+DEFINE_TEST(test_read_format_cpio_afio_broken)
+{
+ struct archive *a;
+ struct archive_entry *ae;
+
+ assert((a = archive_read_new()) != NULL);
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_filter_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_support_format_all(a));
+ assertEqualIntA(a, ARCHIVE_OK, archive_read_open_memory(a, archive2, sizeof(archive2)));
+ assertEqualIntA(a, ARCHIVE_FATAL, archive_read_next_header(a, &ae));
+ assertEqualInt(archive_filter_code(a, 0), ARCHIVE_FILTER_NONE);
+ assertEqualInt(archive_format(a), ARCHIVE_FORMAT_CPIO_AFIO_LARGE);
+ archive_read_free(a);
+}
/* TODO: Mtree reader should probably return ARCHIVE_WARN for this. */
assertEqualIntA(a, ARCHIVE_OK, archive_read_next_header(a, &ae));
assertEqualString(archive_entry_pathname(ae), "dir2/toosmallfile");
- assertEqualInt(archive_entry_size(ae), -1);
+ assertEqualInt(archive_entry_size(ae), 0);
assertEqualInt(archive_entry_is_encrypted(ae), 0);
assertEqualIntA(a, archive_read_has_encrypted_entries(a), ARCHIVE_READ_FORMAT_ENCRYPTION_UNSUPPORTED);