fentry->flags |= RSPAMD_ARCHIVE_FILE_OBFUSCATED;
fentry->fname = g_string_new_len(in, inlen);
- return NULL;
+ return false;
}
int i = 0;
fentry->flags |= RSPAMD_ARCHIVE_FILE_OBFUSCATED;
fentry->fname = g_string_new_len(in, inlen);
- return NULL;
+ return false;
}
g_free(tmp);
struct rspamd_archive *arch;
struct rspamd_archive_file *f = NULL;
+ /*
+ * Need at least 22 bytes for a minimal EOCD record; otherwise the
+ * scan below would compute a pointer below parsed_data.begin (UB).
+ */
+ if (part->parsed_data.len < 22) {
+ return;
+ }
+
/* Zip files have interesting data at the end of archive */
p = part->parsed_data.begin + part->parsed_data.len - 1;
start = part->parsed_data.begin;
memcpy(&cd_offset, eocd + 16, sizeof(cd_offset));
cd_offset = GUINT32_FROM_LE(cd_offset);
- /* We need to check sanity as well */
- if (cd_offset + cd_size > (unsigned int) (eocd - start)) {
+ /*
+ * We need to check sanity as well. Use a 64-bit add to avoid
+ * a 32-bit wrap that would let a malicious EOCD bypass the check.
+ */
+ if ((uint64_t) cd_offset + (uint64_t) cd_size > (uint64_t) (eocd - start)) {
msg_info_task("zip archive is invalid (bad size/offset for CD)");
return;
f = NULL;
}
+ /*
+ * Bound the extra-field block using sizes rather than
+ * pointer arithmetic: extra_sz is a 64-bit varint and
+ * "p + fname_len + extra_sz" could otherwise wrap.
+ */
if (f && has_extra && extra_sz > 0 &&
- p + fname_len + extra_sz < end) {
+ fname_len <= (uint64_t) (end - p) &&
+ extra_sz <= (uint64_t) (end - p) - fname_len) {
/* Try to find encryption record in extra field */
const unsigned char *ex = p + fname_len;
const unsigned char *extra_end = ex + extra_sz;
while (proptype != 0) {
SZ_READ_VINT(proplen);
- if (p + proplen < end) {
+ /*
+ * proplen is a 64-bit varint; compare sizes to avoid
+ * a pointer-arithmetic wrap (p + proplen < end).
+ */
+ if (proplen < (uint64_t) (end - p)) {
p += proplen;
}
else {