Skip to content

Commit

Permalink
Fixed: Possible out of bounds read in lzp_decode_block. Mark exit b…
Browse files Browse the repository at this point in the history
…ranches as unlikely.
  • Loading branch information
Sewer56 committed Dec 14, 2024
1 parent 5174b4e commit 66cde0b
Showing 1 changed file with 13 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/libbz3.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@
*/

#include "libbz3.h"

#include <stdlib.h>
#include <string.h>

#include "libsais.h"

#if defined(__GNUC__) || defined(__clang__)
#define LIKELY(x) __builtin_expect(!!(x), 1)
#define UNLIKELY(x) __builtin_expect(!!(x), 0)
#else
#define LIKELY(x) (x)
#define UNLIKELY(x) (x)
#endif

/* CRC32 implementation. Since CRC32 generally takes less than 1% of the runtime on real-world data (e.g. the
Silesia corpus), I decided against using hardware CRC32. This implementation is simple, fast, fool-proof and
good enough to be used with bzip3. */
Expand Down Expand Up @@ -201,21 +207,23 @@ static s32 lzp_decode_block(const u8 * RESTRICT in, const u8 * in_end, s32 * RES

while (in < in_end && out < out_end) {
u32 idx = (ctx >> 15 ^ ctx ^ ctx >> 3) & ((s32)(1 << LZP_DICTIONARY) - 1);
s32 val = lut[idx];
s32 val = lut[idx]; // SAFETY: guaranteed to be in-bounds by & mask.
lut[idx] = (s32)(out - outs);
if (*in == MATCH && val > 0) {
in++;
// SAFETY: 'in' is advanced here, but it may have been at last index in the case of untrusted bad data.
if (UNLIKELY(in == in_end)) return -1;
if (*in != 255) {
s32 len = LZP_MIN_MATCH;
while (1) {
if (in == in_end) return -1;
if (UNLIKELY(in == in_end)) return -1;
len += *in;
if (*in++ != 254) break;
}

const u8 * ref = outs + val;
const u8 * oe = out + len;
if (oe > out_end) oe = out_end;
if (UNLIKELY(oe > out_end)) oe = out_end;

while (out < oe) *out++ = *ref++;

Expand Down

0 comments on commit 66cde0b

Please sign in to comment.