Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/fluent-bit/flb_snappy.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,8 @@ int flb_snappy_uncompress(char *in_data, size_t in_len,
int flb_snappy_uncompress_framed_data(char *in_data, size_t in_len,
char **out_data, size_t *out_len);

/* Decode raw or framed Snappy within limit; returns FLB_DECOMPRESSOR_* status. */
int flb_snappy_uncompress_bounded(char **out_data, size_t *out_len,
char *in_data, size_t in_len, size_t limit);

#endif
117 changes: 1 addition & 116 deletions src/flb_compression.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
#include <fluent-bit/flb_zstd.h>
#include <fluent-bit/flb_compression.h>
#include <fluent-bit/flb_snappy.h>
#include <snappy.h>
#include <cfl/cfl_checksum.h>

struct flb_snappy_decompression_context {
char *buffer;
Expand Down Expand Up @@ -305,119 +303,6 @@ int flb_decompress(struct flb_decompression_context *context,
return FLB_DECOMPRESSOR_SUCCESS;
}

static uint32_t decompression_read_le32(const unsigned char *buffer)
{
return ((uint32_t) buffer[0]) | ((uint32_t) buffer[1] << 8) |
((uint32_t) buffer[2] << 16) | ((uint32_t) buffer[3] << 24);
}

static int decompress_snappy_bounded(char **output_buffer, size_t *output_size,
char *input_buffer, size_t input_size, size_t limit)
{
size_t offset;
size_t length;
size_t expanded;
size_t total = 0;
size_t output_offset = 0;
int pass;
unsigned char type;
unsigned char *frame;
uint32_t checksum;
char *buffer = NULL;

if (input_size == 0) {
return FLB_DECOMPRESSOR_FAILURE;
}
if (input_size < 10 ||
(unsigned char) input_buffer[0] != FLB_SNAPPY_FRAME_TYPE_STREAM_IDENTIFIER ||
input_buffer[1] != 6 || input_buffer[2] != 0 || input_buffer[3] != 0 ||
memcmp(input_buffer + 4, FLB_SNAPPY_STREAM_IDENTIFIER_STRING, 6) != 0) {
if (!snappy_uncompressed_length(input_buffer, input_size, &expanded)) {
return FLB_DECOMPRESSOR_FAILURE;
}
if (expanded > limit) {
return FLB_DECOMPRESSOR_LIMIT_EXCEEDED;
}
return flb_snappy_uncompress(input_buffer, input_size, output_buffer, output_size) == 0 ?
0 : FLB_DECOMPRESSOR_FAILURE;
}

/* Inspect every framed chunk before allocating a single bounded output. */
for (pass = 0; pass < 2; pass++) {
offset = 0;
while (offset < input_size) {
if (input_size - offset < 4) {
goto invalid;
}
frame = (unsigned char *) input_buffer + offset;
type = frame[0];
length = ((size_t) frame[1]) | ((size_t) frame[2] << 8) |
((size_t) frame[3] << 16);
if (length > input_size - offset - 4) {
goto invalid;
}
frame += 4;
if (type == FLB_SNAPPY_FRAME_TYPE_STREAM_IDENTIFIER) {
if (length != 6 || memcmp(frame, FLB_SNAPPY_STREAM_IDENTIFIER_STRING, 6) != 0) {
goto invalid;
}
}
else if (type == FLB_SNAPPY_FRAME_TYPE_COMPRESSED_DATA ||
type == FLB_SNAPPY_FRAME_TYPE_UNCOMPRESSED_DATA) {
if (length < 4 || length > FLB_SNAPPY_FRAME_SIZE_LIMIT) {
goto invalid;
}
expanded = length - 4;
if (type == FLB_SNAPPY_FRAME_TYPE_COMPRESSED_DATA &&
!snappy_uncompressed_length((char *) frame + 4, length - 4, &expanded)) {
goto invalid;
}
if (pass == 0) {
if (expanded > limit - total) {
return FLB_DECOMPRESSOR_LIMIT_EXCEEDED;
}
total += expanded;
}
else {
if (type == FLB_SNAPPY_FRAME_TYPE_COMPRESSED_DATA) {
if (snappy_uncompress((char *) frame + 4, length - 4,
buffer + output_offset) != 0) {
goto invalid;
}
}
else {
memcpy(buffer + output_offset, frame + 4, expanded);
}
checksum = cfl_checksum_crc32c((unsigned char *) buffer + output_offset,
expanded);
checksum = ((checksum >> 15) | (checksum << 17)) + 0xa282ead8;
if (checksum != decompression_read_le32(frame)) {
goto invalid;
}
output_offset += expanded;
}
}
else if (type < FLB_SNAPPY_FRAME_TYPE_RESERVED_SKIPPABLE_BASE) {
goto invalid;
}
offset += 4 + length;
}
if (pass == 0) {
buffer = flb_malloc(total == 0 ? 1 : total);
if (buffer == NULL) {
return FLB_DECOMPRESSOR_FAILURE;
}
}
}
*output_buffer = buffer;
*output_size = total;
return 0;

invalid:
flb_free(buffer);
return FLB_DECOMPRESSOR_FAILURE;
}

static int decompress_snappy_dispatch(struct flb_decompression_context *context,
void *output_buffer, size_t *output_size)
{
Expand All @@ -427,7 +312,7 @@ static int decompress_snappy_dispatch(struct flb_decompression_context *context,

*output_size = 0;
if (snappy->buffer == NULL) {
ret = decompress_snappy_bounded(&snappy->buffer, &snappy->length,
ret = flb_snappy_uncompress_bounded(&snappy->buffer, &snappy->length,
(char *) context->read_buffer,
context->input_buffer_length,
context->output_limit - context->output_size);
Expand Down
Loading
Loading