- RAR v5 extra area parsing: fix wrong loop boundary (used advanced `p`
instead of `ex + extra_sz`), wrong advancement (`cur_sz` alone didn't
account for the size vint bytes), and wrong remain calculation for the
second vint read. Add bounds validation for `cur_sz`.
- 7zip codec ID: validate `p + sz <= end` before reading codec ID bytes
to prevent out-of-bounds read with malformed archives.
p + fname_len + extra_sz < end) {
/* Try to find encryption record in extra field */
const unsigned char *ex = p + fname_len;
p + fname_len + extra_sz < end) {
/* Try to find encryption record in extra field */
const unsigned char *ex = p + fname_len;
+ const unsigned char *extra_end = ex + extra_sz;
- while (ex < p + extra_sz) {
+ while (ex < extra_end) {
const unsigned char *t;
int64_t cur_sz = 0, sec_type = 0;
const unsigned char *t;
int64_t cur_sz = 0, sec_type = 0;
- r = rspamd_archive_rar_read_vint(ex, extra_sz, &cur_sz);
- if (r == -1) {
+ vint_len = rspamd_archive_rar_read_vint(ex, extra_end - ex, &cur_sz);
+ if (vint_len == -1) {
msg_debug_archive("rar archive is invalid (bad vint)");
return;
}
msg_debug_archive("rar archive is invalid (bad vint)");
return;
}
+ if (cur_sz <= 0 || ex + vint_len + cur_sz > extra_end) {
+ msg_debug_archive("rar archive is invalid (bad extra record size)");
+ break;
+ }
+
+ t = ex + vint_len;
- r = rspamd_archive_rar_read_vint(t, extra_sz - r, &sec_type);
+ r = rspamd_archive_rar_read_vint(t, cur_sz, &sec_type);
if (r == -1) {
msg_debug_archive("rar archive is invalid (bad vint)");
return;
if (r == -1) {
msg_debug_archive("rar archive is invalid (bad vint)");
return;
+ ex += vint_len + cur_sz;
t = *p;
SZ_SKIP_BYTES(1);
sz = t & 0xF;
t = *p;
SZ_SKIP_BYTES(1);
sz = t & 0xF;
+ /* Codec ID - validate bounds before reading */
+ if (end - p < (goffset) sz) {
+ msg_debug_archive("7zip archive is invalid (codec id truncated)");
+ return NULL;
+ }
tmp = 0;
for (j = 0; j < sz; j++) {
tmp <<= 8;
tmp = 0;
for (j = 0; j < sz; j++) {
tmp <<= 8;