mirror of
https://github.com/ckolivas/lrzip.git
synced 2026-03-09 22:43:53 +01:00
Implement write bounds checking within libzpaq to prevent corrupt or malicious input attempting to write beyond buffer size.
This commit is contained in:
parent
843fa4168a
commit
56ac0f1a51
|
|
@ -503,13 +503,35 @@ struct bufRead: public libzpaq::Reader {
|
|||
struct bufWrite: public libzpaq::Writer {
|
||||
uchar *c_buf;
|
||||
i64 *c_len;
|
||||
bufWrite(uchar *buf_, i64 *n_): c_buf(buf_), c_len(n_) {}
|
||||
i64 max_len;
|
||||
bufWrite(uchar *buf_, i64 *n_, i64 max_ = -1LL): c_buf(buf_), c_len(n_), max_len(max_) {}
|
||||
|
||||
void put(int c) {
|
||||
c_buf[(*c_len)++] = (uchar)c;
|
||||
//c_buf[(*c_len)++] = (uchar)c;
|
||||
if (*c_len < 0) return;
|
||||
if (max_len >= 0 && *c_len >= max_len) {
|
||||
*c_len = -1;
|
||||
return;
|
||||
}
|
||||
c_buf[(*c_len)++] = static_cast<uchar>(c);
|
||||
}
|
||||
|
||||
void write(const char *buf, int n) {
|
||||
if (n <= 0 || *c_len < 0) return;
|
||||
if (max_len < 0) {
|
||||
memcpy(c_buf + *c_len, buf, n);
|
||||
*c_len += n;
|
||||
return;
|
||||
}
|
||||
i64 avail = max_len - *c_len;
|
||||
if (avail <= 0) {
|
||||
*c_len = -1;
|
||||
return;
|
||||
}
|
||||
if ((i64)n > avail) {
|
||||
*c_len = -1;
|
||||
return;
|
||||
}
|
||||
memcpy(c_buf + *c_len, buf, n);
|
||||
*c_len += n;
|
||||
}
|
||||
|
|
@ -527,16 +549,19 @@ extern "C" void zpaq_compress(uchar *c_buf, i64 *c_len, uchar *s_buf, i64 s_len,
|
|||
compress (&bufR, &bufW, level);
|
||||
}
|
||||
|
||||
extern "C" void zpaq_decompress(uchar *s_buf, i64 *d_len, uchar *c_buf, i64 c_len,
|
||||
FILE *msgout, bool progress, long thread)
|
||||
extern "C" int zpaq_decompress(uchar *s_buf, i64 *d_len, uchar *c_buf, i64 c_len,
|
||||
FILE *msgout, bool progress, long thread,
|
||||
i64 expected_len)
|
||||
{
|
||||
i64 total_len = c_len;
|
||||
int last_pct = 100;
|
||||
|
||||
bufRead bufR(c_buf, &c_len, total_len, &last_pct, progress, thread, msgout);
|
||||
bufWrite bufW(s_buf, d_len);
|
||||
bufWrite bufW(s_buf, d_len, expected_len);
|
||||
|
||||
decompress(&bufR, &bufW);
|
||||
if (*d_len < 0) return -1; // overflow attempt detected
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif // LIBZPAQ_H
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2006-2016,2022 Con Kolivas
|
||||
Copyright (C) 2006-2016,2022,2026 Con Kolivas
|
||||
Copyright (C) 2011 Peter Hyman
|
||||
Copyright (C) 1998-2003 Andrew Tridgell
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ bool initialise_control(rzip_control *control);
|
|||
#define initialize_control(_control) initialise_control(_control)
|
||||
extern void zpaq_compress(uchar *c_buf, i64 *c_len, uchar *s_buf, i64 s_len, int level,
|
||||
FILE *msgout, bool progress, long thread);
|
||||
extern void zpaq_decompress(uchar *s_buf, i64 *d_len, uchar *c_buf, i64 c_len,
|
||||
FILE *msgout, bool progress, long thread);
|
||||
extern int zpaq_decompress(uchar *s_buf, i64 *d_len, uchar *c_buf, i64 c_len,
|
||||
FILE *msgout, bool progress, long thread, i64 expected_len);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
12
stream.c
12
stream.c
|
|
@ -441,7 +441,7 @@ static int zpaq_decompress_buf(rzip_control *control __UNUSED__, struct uncomp_t
|
|||
{
|
||||
i64 dlen = ucthread->u_len;
|
||||
uchar *c_buf;
|
||||
int ret = 0;
|
||||
int zd_ret, ret = 0;
|
||||
|
||||
c_buf = ucthread->s_buf;
|
||||
ucthread->s_buf = malloc(round_up_page(control, dlen));
|
||||
|
|
@ -452,9 +452,15 @@ static int zpaq_decompress_buf(rzip_control *control __UNUSED__, struct uncomp_t
|
|||
}
|
||||
|
||||
dlen = 0;
|
||||
zpaq_decompress(ucthread->s_buf, &dlen, c_buf, ucthread->c_len,
|
||||
control->msgout, SHOW_PROGRESS ? true: false, thread);
|
||||
zd_ret = zpaq_decompress(ucthread->s_buf, &dlen, c_buf, ucthread->c_len,
|
||||
control->msgout, SHOW_PROGRESS ? true: false, thread,
|
||||
ucthread->u_len);
|
||||
|
||||
if (unlikely(zd_ret < 0)) {
|
||||
print_err("Attempted to write beyond expected output size, corrupted input.\n");
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
if (unlikely(dlen != ucthread->u_len)) {
|
||||
print_err("Inconsistent length after decompression. Got %ld bytes, expected %"PRId64"\n", dlen, ucthread->u_len);
|
||||
ret = -1;
|
||||
|
|
|
|||
Loading…
Reference in a new issue