rspamd_archive_7zip_read_vint had two defects in the multi-byte path:
the destination uint64_t was left uninitialised before a partial
memcpy, and the "shift back" used sizeof(tgt) (bytes) mixed with
NBBY * intlen (bits). For intlen >= 2 that expression underflows the
unsigned size_t and produces a shift of 64 or more, which is
undefined behavior.
Zero-initialise the value and drop the bogus shift: with a zeroed
target the little-endian memcpy already yields the intlen-byte value
directly.
else {
int cur_bit = 6, intlen = 1;
const unsigned char bmask = 0xFF;
- uint64_t tgt;
+ uint64_t tgt = 0;
while (cur_bit > 0) {
if (!isset(&t, cur_bit)) {
if (remain >= intlen + 1) {
memcpy(&tgt, start + 1, intlen);
tgt = GUINT64_FROM_LE(tgt);
- /* Shift back */
- tgt >>= sizeof(tgt) - NBBY * intlen;
+ /*
+ * tgt was zero-initialised, so it now holds the
+ * intlen-byte little-endian value directly.
+ */
/* Add masked value */
tgt += (uint64_t) (t & (bmask >> (NBBY - cur_bit)))
<< (NBBY * intlen);