mirror of
https://github.com/amadvance/snapraid.git
synced 2026-10-26 02:49:02 -04:00
Fix binary varint decoders to reject values overflowing uint32_t/uint64_t declared widths
This commit is contained in:
parent
02413b756c
commit
05884d7aa0
2 changed files with 99 additions and 4 deletions
|
|
@ -13,6 +13,7 @@
|
|||
#include "elem.h"
|
||||
#include "state.h"
|
||||
#include "support.h"
|
||||
#include "stream.h"
|
||||
#include "tommyds/tommyhash.h"
|
||||
#include "tommyds/tommyarray.h"
|
||||
#include "tommyds/tommyarrayblkof.h"
|
||||
|
|
@ -994,6 +995,85 @@ static void test_smart_ignore(void)
|
|||
}
|
||||
}
|
||||
|
||||
static void test_stream(void)
|
||||
{
|
||||
STREAM f;
|
||||
uint32_t v32;
|
||||
uint64_t v64;
|
||||
|
||||
/* 32-bit valid boundary */
|
||||
unsigned char buf_v32[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x8f };
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.pos = buf_v32;
|
||||
f.end = buf_v32 + sizeof(buf_v32);
|
||||
if (sgetb32(&f, &v32) != 0 || v32 != 0xffffffffU) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "test_stream: valid uint32 max failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* 32-bit overflow payload in 5th terminal byte */
|
||||
unsigned char buf_o32[] = { 0x00, 0x00, 0x00, 0x00, 0xf1 };
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.pos = buf_o32;
|
||||
f.end = buf_o32 + sizeof(buf_o32);
|
||||
if (sgetb32(&f, &v32) == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "test_stream: uint32 overflow accepted\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* 32-bit 5th byte non-terminal */
|
||||
unsigned char buf_nt32[] = { 0x00, 0x00, 0x00, 0x00, 0x01, 0x80 };
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.pos = buf_nt32;
|
||||
f.end = buf_nt32 + sizeof(buf_nt32);
|
||||
if (sgetb32(&f, &v32) == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "test_stream: uint32 5th non-terminal accepted\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* 64-bit valid boundary */
|
||||
unsigned char buf_v64[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x81 };
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.pos = buf_v64;
|
||||
f.end = buf_v64 + sizeof(buf_v64);
|
||||
if (sgetb64(&f, &v64) != 0 || v64 != 0xffffffffffffffffULL) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "test_stream: valid uint64 max failed\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* 64-bit overflow payload in 10th terminal byte */
|
||||
unsigned char buf_o64[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83 };
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.pos = buf_o64;
|
||||
f.end = buf_o64 + sizeof(buf_o64);
|
||||
if (sgetb64(&f, &v64) == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "test_stream: uint64 overflow accepted\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
|
||||
/* 64-bit 10th byte non-terminal */
|
||||
unsigned char buf_nt64[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x80 };
|
||||
memset(&f, 0, sizeof(f));
|
||||
f.pos = buf_nt64;
|
||||
f.end = buf_nt64 + sizeof(buf_nt64);
|
||||
if (sgetb64(&f, &v64) == 0) {
|
||||
/* LCOV_EXCL_START */
|
||||
log_fatal(EINTERNAL, "test_stream: uint64 10th non-terminal accepted\n");
|
||||
exit(EXIT_FAILURE);
|
||||
/* LCOV_EXCL_STOP */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void selftest(void)
|
||||
{
|
||||
|
|
@ -1019,6 +1099,7 @@ void selftest(void)
|
|||
test_hash();
|
||||
test_crc32c();
|
||||
test_tommy();
|
||||
test_stream();
|
||||
test_wnmatch();
|
||||
test_parse_smartctl();
|
||||
test_smart_ignore();
|
||||
|
|
|
|||
|
|
@ -586,7 +586,7 @@ int sgetb32(STREAM* f, uint32_t* value)
|
|||
{
|
||||
uint32_t v;
|
||||
unsigned char b;
|
||||
unsigned char s;
|
||||
unsigned s;
|
||||
int c;
|
||||
|
||||
v = 0;
|
||||
|
|
@ -603,7 +603,7 @@ loop:
|
|||
if ((b & 0x80) == 0) {
|
||||
v |= (uint32_t)b << s;
|
||||
s += 7;
|
||||
if (s >= 32) {
|
||||
if (tommy_unlikely(s >= 32)) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
|
@ -611,6 +611,13 @@ loop:
|
|||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for overflow: at s == 28 only 4 bits (0x0f) fit in uint32_t
|
||||
*/
|
||||
if (tommy_unlikely(s == 28 && (b & 0x70) != 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
v |= (uint32_t)(b & 0x7f) << s;
|
||||
|
||||
*value = v;
|
||||
|
|
@ -622,7 +629,7 @@ int sgetb64(STREAM* f, uint64_t* value)
|
|||
{
|
||||
uint64_t v;
|
||||
unsigned char b;
|
||||
unsigned char s;
|
||||
unsigned s;
|
||||
int c;
|
||||
|
||||
v = 0;
|
||||
|
|
@ -639,7 +646,7 @@ loop:
|
|||
if ((b & 0x80) == 0) {
|
||||
v |= (uint64_t)b << s;
|
||||
s += 7;
|
||||
if (s >= 64) {
|
||||
if (tommy_unlikely(s >= 64)) {
|
||||
/* LCOV_EXCL_START */
|
||||
return -1;
|
||||
/* LCOV_EXCL_STOP */
|
||||
|
|
@ -647,6 +654,13 @@ loop:
|
|||
goto loop;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for overflow: at s == 63 only 1 bit (0x01) fits in uint64_t
|
||||
*/
|
||||
if (tommy_unlikely(s == 63 && (b & 0x7e) != 0)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
v |= (uint64_t)(b & 0x7f) << s;
|
||||
|
||||
*value = v;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue