summaryrefslogtreecommitdiffstats
path: root/fluent-bit/src/flb_gzip.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 12:08:03 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-05 12:08:18 +0000
commit5da14042f70711ea5cf66e034699730335462f66 (patch)
tree0f6354ccac934ed87a2d555f45be4c831cf92f4a /fluent-bit/src/flb_gzip.c
parentReleasing debian version 1.44.3-2. (diff)
downloadnetdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz
netdata-5da14042f70711ea5cf66e034699730335462f66.zip
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/src/flb_gzip.c')
-rw-r--r--fluent-bit/src/flb_gzip.c747
1 files changed, 0 insertions, 747 deletions
diff --git a/fluent-bit/src/flb_gzip.c b/fluent-bit/src/flb_gzip.c
deleted file mode 100644
index 4b9b761fe..000000000
--- a/fluent-bit/src/flb_gzip.c
+++ /dev/null
@@ -1,747 +0,0 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-
-/* Fluent Bit
- * ==========
- * Copyright (C) 2015-2022 The Fluent Bit Authors
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <fluent-bit/flb_info.h>
-#include <fluent-bit/flb_mem.h>
-#include <fluent-bit/flb_log.h>
-#include <fluent-bit/flb_gzip.h>
-#include <fluent-bit/flb_compression.h>
-#include <miniz/miniz.h>
-
-#define FLB_GZIP_HEADER_OFFSET 10
-#define FLB_GZIP_HEADER_SIZE FLB_GZIP_HEADER_OFFSET
-
-#define FLB_GZIP_MAGIC_NUMBER 0x8B1F
-
-typedef enum {
- FTEXT = 1,
- FHCRC = 2,
- FEXTRA = 4,
- FNAME = 8,
- FCOMMENT = 16
-} flb_tinf_gzip_flag;
-
-#pragma pack(push, 1)
-struct flb_gzip_header {
- uint16_t magic_number;
- uint8_t compression_method;
- uint8_t header_flags;
- uint32_t timestamp;
- uint8_t compression_flags;
- uint8_t operating_system_id;
-};
-#pragma pack(pop)
-
-struct flb_gzip_decompression_context {
- struct flb_gzip_header gzip_header;
- mz_stream miniz_stream;
-};
-
-static unsigned int read_le16(const unsigned char *p)
-{
- return ((unsigned int) p[0]) | ((unsigned int) p[1] << 8);
-}
-
-static unsigned int read_le32(const unsigned char *p)
-{
- return ((unsigned int) p[0])
- | ((unsigned int) p[1] << 8)
- | ((unsigned int) p[2] << 16)
- | ((unsigned int) p[3] << 24);
-}
-
-static inline void gzip_header(void *buf)
-{
- uint8_t *p;
-
- /* GZip Magic bytes */
- p = buf;
- *p++ = 0x1F;
- *p++ = 0x8B;
- *p++ = 8;
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
- *p++ = 0;
- *p++ = 0xFF;
-}
-
-
-#include <ctype.h>
-
-static inline void flb_hex_dump(uint8_t *buffer, size_t buffer_length, size_t line_length) {
- char *printable_line;
- size_t buffer_index;
- size_t filler_index;
-
- if (40 < line_length)
- {
- line_length = 40;
- }
-
- printable_line = alloca(line_length + 1);
-
- if (NULL == printable_line)
- {
- printf("Alloca returned NULL\n");
-
- return;
- }
-
- memset(printable_line, '\0', line_length + 1);
-
- for (buffer_index = 0 ; buffer_index < buffer_length ; buffer_index++) {
- if (0 != buffer_index &&
- 0 == (buffer_index % line_length)) {
-
- printf("%s\n", printable_line);
-
- memset(printable_line, '\0', line_length + 1);
- }
-
- if (0 != isprint(buffer[buffer_index])) {
- printable_line[(buffer_index % line_length)] = buffer[buffer_index];
- }
- else {
- printable_line[(buffer_index % line_length)] = '.';
- }
-
- printf("%02X ", buffer[buffer_index]);
- }
-
- if (0 != buffer_index &&
- 0 != (buffer_index % line_length)) {
-
- for (filler_index = 0 ;
- filler_index < (line_length - (buffer_index % line_length)) ;
- filler_index++) {
- printf(" ");
- }
-
- printf("%s\n", printable_line);
-
- memset(printable_line, '.', line_length);
- }
-}
-
-
-int flb_gzip_compress(void *in_data, size_t in_len,
- void **out_data, size_t *out_len)
-{
- int flush;
- int status;
- int footer_start;
- uint8_t *pb;
- size_t out_size;
- void *out_buf;
- z_stream strm;
- mz_ulong crc;
-
- /*
- * Calculating the upper bound for a gzip compression is
- * non-trivial, so we rely on miniz's own calculation
- * to guarantee memory safety.
- */
- out_size = compressBound(in_len);
- out_buf = flb_malloc(out_size);
-
- if (!out_buf) {
- flb_errno();
- flb_error("[gzip] could not allocate outgoing buffer");
- return -1;
- }
-
- /* Initialize streaming buffer context */
- memset(&strm, '\0', sizeof(strm));
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
- strm.next_in = in_data;
- strm.avail_in = in_len;
- strm.total_out = 0;
-
- /* Deflate mode */
- deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
- Z_DEFLATED, -Z_DEFAULT_WINDOW_BITS, 9, Z_DEFAULT_STRATEGY);
-
- /*
- * Miniz don't support GZip format directly, instead we will:
- *
- * - append manual GZip magic bytes
- * - deflate raw content
- * - append manual CRC32 data
- */
- gzip_header(out_buf);
-
- /* Header offset */
- pb = (uint8_t *) out_buf + FLB_GZIP_HEADER_OFFSET;
-
- flush = Z_NO_FLUSH;
- while (1) {
- strm.next_out = pb + strm.total_out;
- strm.avail_out = out_size - (pb - (uint8_t *) out_buf);
-
- if (strm.avail_in == 0) {
- flush = Z_FINISH;
- }
-
- status = deflate(&strm, flush);
- if (status == Z_STREAM_END) {
- break;
- }
- else if (status != Z_OK) {
- deflateEnd(&strm);
- return -1;
- }
- }
-
- if (deflateEnd(&strm) != Z_OK) {
- flb_free(out_buf);
- return -1;
- }
- *out_len = strm.total_out;
-
- /* Construct the gzip checksum (CRC32 footer) */
- footer_start = FLB_GZIP_HEADER_OFFSET + *out_len;
- pb = (uint8_t *) out_buf + footer_start;
-
- crc = mz_crc32(MZ_CRC32_INIT, in_data, in_len);
- *pb++ = crc & 0xFF;
- *pb++ = (crc >> 8) & 0xFF;
- *pb++ = (crc >> 16) & 0xFF;
- *pb++ = (crc >> 24) & 0xFF;
- *pb++ = in_len & 0xFF;
- *pb++ = (in_len >> 8) & 0xFF;
- *pb++ = (in_len >> 16) & 0xFF;
- *pb++ = (in_len >> 24) & 0xFF;
-
- /* Set the real buffer size for the caller */
- *out_len += FLB_GZIP_HEADER_OFFSET + 8;
- *out_data = out_buf;
-
- return 0;
-}
-
-/* Uncompress (inflate) GZip data */
-int flb_gzip_uncompress(void *in_data, size_t in_len,
- void **out_data, size_t *out_len)
-{
- int status;
- uint8_t *p;
- void *out_buf;
- size_t out_size = 0;
- void *zip_data;
- size_t zip_len;
- unsigned char flg;
- unsigned int xlen, hcrc;
- unsigned int dlen, crc;
- mz_ulong crc_out;
- mz_stream stream;
- const unsigned char *start;
-
- /* Minimal length: header + crc32 */
- if (in_len < 18) {
- flb_error("[gzip] unexpected content length");
- return -1;
- }
-
- /* Magic bytes */
- p = in_data;
- if (p[0] != 0x1F || p[1] != 0x8B) {
- flb_error("[gzip] invalid magic bytes");
- return -1;
- }
-
- if (p[2] != 8) {
- flb_error("[gzip] invalid method");
- return -1;
- }
-
- /* Flag byte */
- flg = p[3];
-
- /* Reserved bits */
- if (flg & 0xE0) {
- flb_error("[gzip] invalid flag");
- return -1;
- }
-
- /* Skip base header of 10 bytes */
- start = p + FLB_GZIP_HEADER_OFFSET;
-
- /* Skip extra data if present */
- if (flg & FEXTRA) {
- xlen = read_le16(start);
- if (xlen > in_len - 12) {
- flb_error("[gzip] invalid gzip data");
- return -1;
- }
- start += xlen + 2;
- }
-
- /* Skip file name if present */
- if (flg & FNAME) {
- do {
- if (start - p >= in_len) {
- flb_error("[gzip] invalid gzip data (FNAME)");
- return -1;
- }
- } while (*start++);
- }
-
- /* Skip file comment if present */
- if (flg & FCOMMENT) {
- do {
- if (start - p >= in_len) {
- flb_error("[gzip] invalid gzip data (FCOMMENT)");
- return -1;
- }
- } while (*start++);
- }
-
- /* Check header crc if present */
- if (flg & FHCRC) {
- if (start - p > in_len - 2) {
- flb_error("[gzip] invalid gzip data (FHRC)");
- return -1;
- }
-
- hcrc = read_le16(start);
- crc = mz_crc32(MZ_CRC32_INIT, p, start - p) & 0x0000FFFF;
- if (hcrc != crc) {
- flb_error("[gzip] invalid gzip header CRC");
- return -1;
- }
- start += 2;
- }
-
- /* Get decompressed length */
- dlen = read_le32(&p[in_len - 4]);
-
- /* Limit decompressed length to 100MB */
- if (dlen > 100000000) {
- flb_error("[gzip] maximum decompression size is 100MB");
- return -1;
- }
-
- /* Get CRC32 checksum of original data */
- crc = read_le32(&p[in_len - 8]);
-
- /* Decompress data */
- if ((p + in_len) - p < 8) {
- flb_error("[gzip] invalid gzip CRC32 checksum");
- return -1;
- }
-
- /* Allocate outgoing buffer */
- out_buf = flb_malloc(dlen);
- if (!out_buf) {
- flb_errno();
- return -1;
- }
- out_size = dlen;
-
- /* Ensure size is above 0 */
- if (((p + in_len) - start - 8) <= 0) {
- flb_free(out_buf);
- return -1;
- }
-
- /* Map zip content */
- zip_data = (uint8_t *) start;
- zip_len = (p + in_len) - start - 8;
-
- memset(&stream, 0, sizeof(stream));
- stream.next_in = zip_data;
- stream.avail_in = zip_len;
- stream.next_out = out_buf;
- stream.avail_out = out_size;
-
- status = mz_inflateInit2(&stream, -Z_DEFAULT_WINDOW_BITS);
- if (status != MZ_OK) {
- flb_free(out_buf);
- return -1;
- }
-
- status = mz_inflate(&stream, MZ_FINISH);
- if (status != MZ_STREAM_END) {
- mz_inflateEnd(&stream);
- flb_free(out_buf);
- return -1;
- }
-
- if (stream.total_out != dlen) {
- mz_inflateEnd(&stream);
- flb_free(out_buf);
- flb_error("[gzip] invalid gzip data size");
- return -1;
- }
-
- /* terminate the stream, it's not longer required */
- mz_inflateEnd(&stream);
-
- /* Validate message CRC vs inflated data CRC */
- crc_out = mz_crc32(MZ_CRC32_INIT, out_buf, dlen);
- if (crc_out != crc) {
- flb_free(out_buf);
- flb_error("[gzip] invalid GZip checksum (CRC32)");
- return -1;
- }
-
- /* set the uncompressed data */
- *out_len = dlen;
- *out_data = out_buf;
-
- return 0;
-}
-
-
-/* Stateful gzip decompressor */
-
-static int flb_gzip_decompressor_process_header(
- struct flb_decompression_context *context)
-{
- struct flb_gzip_decompression_context *inner_context;
-
- inner_context = (struct flb_gzip_decompression_context *) \
- context->inner_context;
-
- /* Minimal length: header + crc32 */
- if (context->input_buffer_length < FLB_GZIP_HEADER_SIZE) {
- flb_error("[gzip] unexpected content length");
-
- return FLB_DECOMPRESSOR_FAILURE;
- }
-
- memcpy(&inner_context->gzip_header,
- context->read_buffer,
- FLB_GZIP_HEADER_SIZE);
-
- context->read_buffer = &context->read_buffer[FLB_GZIP_HEADER_SIZE];
- context->input_buffer_length -= FLB_GZIP_HEADER_SIZE;
-
- /* Magic bytes */
- if (inner_context->gzip_header.magic_number != FLB_GZIP_MAGIC_NUMBER) {
- context->state = FLB_DECOMPRESSOR_STATE_FAILED;
-
- flb_error("[gzip] invalid magic bytes : %04x",
- inner_context->gzip_header.magic_number);
-
- return FLB_DECOMPRESSOR_FAILURE;
- }
-
- if (inner_context->gzip_header.compression_method != MZ_DEFLATED) {
- context->state = FLB_DECOMPRESSOR_STATE_FAILED;
-
- flb_error("[gzip] invalid method : %u",
- inner_context->gzip_header.compression_method);
-
- return FLB_DECOMPRESSOR_FAILURE;
- }
-
- /* Flag processing */
- /* Reserved bits */
- if (inner_context->gzip_header.header_flags & 0xE0) {
- context->state = FLB_DECOMPRESSOR_STATE_FAILED;
-
- flb_error("[gzip] invalid flag mask : %x",
- inner_context->gzip_header.header_flags);
-
- return FLB_DECOMPRESSOR_FAILURE;
- }
-
- context->state = FLB_DECOMPRESSOR_STATE_EXPECTING_OPTIONAL_HEADERS;
-
- return FLB_DECOMPRESSOR_SUCCESS;
-}
-
-static int flb_gzip_decompressor_process_optional_headers(
- struct flb_decompression_context *context)
-{
- struct flb_gzip_decompression_context *inner_context;
- int status;
- uint16_t hcrc;
- uint16_t xlen;
- uint16_t crc;
-
- inner_context = (struct flb_gzip_decompression_context *) \
- context->inner_context;
-
- /* Skip extra data if present */
- if (inner_context->gzip_header.header_flags & FEXTRA) {
- if (context->input_buffer_length <= sizeof(uint16_t)) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- xlen = sizeof(uint16_t) + read_le16(context->read_buffer);
-
- if (context->input_buffer_length < xlen) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- context->read_buffer = &context->read_buffer[xlen];
- context->input_buffer_length -= xlen;
-
- inner_context->gzip_header.header_flags &= (~FEXTRA);
- }
-
- if (inner_context->gzip_header.header_flags != 0 &&
- context->input_buffer_length == 0) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- /* Skip file name if present */
- if (inner_context->gzip_header.header_flags & FNAME) {
- xlen = strnlen((char *) context->read_buffer,
- context->input_buffer_length);
-
- if (xlen == 0 ||
- xlen == context->input_buffer_length) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- xlen++;
-
- context->read_buffer = &context->read_buffer[xlen];
- context->input_buffer_length -= xlen;
-
- inner_context->gzip_header.header_flags &= (~FNAME);
- }
-
- if (inner_context->gzip_header.header_flags != 0 &&
- context->input_buffer_length == 0) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- /* Skip file comment if present */
- if (inner_context->gzip_header.header_flags & FCOMMENT) {
- xlen = strnlen((char *) context->read_buffer,
- context->input_buffer_length);
-
- if (xlen == 0 ||
- xlen == context->input_buffer_length) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- context->read_buffer = &context->read_buffer[xlen];
- context->input_buffer_length -= xlen;
-
- inner_context->gzip_header.header_flags &= (~FCOMMENT);
- }
-
- if (inner_context->gzip_header.header_flags != 0 &&
- context->input_buffer_length == 0) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- /* Check header crc if present (lower 16 bits of the checksum)*/
- if (inner_context->gzip_header.header_flags & FHCRC) {
- if (context->input_buffer_length <= sizeof(uint16_t)) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- hcrc = read_le16(context->read_buffer);
-
- crc = mz_crc32(MZ_CRC32_INIT,
- (const unsigned char *) &inner_context->gzip_header,
- FLB_GZIP_HEADER_SIZE);
-
- crc &= 0x0000FFFF;
-
- if (hcrc != crc) {
- context->state = FLB_DECOMPRESSOR_STATE_FAILED;
-
- return FLB_DECOMPRESSOR_CORRUPTED_HEADER;
- }
-
- xlen = sizeof(uint16_t);
-
- context->read_buffer = &context->read_buffer[xlen];
- context->input_buffer_length -= xlen;
-
- inner_context->gzip_header.header_flags &= (~FHCRC);
- }
-
- status = mz_inflateInit2(&inner_context->miniz_stream,
- -Z_DEFAULT_WINDOW_BITS);
-
- if (status != MZ_OK) {
- context->state = FLB_DECOMPRESSOR_STATE_FAILED;
-
- return FLB_DECOMPRESSOR_FAILURE;
- }
-
- context->state = FLB_DECOMPRESSOR_STATE_EXPECTING_BODY;
-
- return FLB_DECOMPRESSOR_SUCCESS;
-}
-
-static int flb_gzip_decompressor_process_body_chunk(
- struct flb_decompression_context *context,
- void *output_buffer,
- size_t *output_length)
-{
- size_t processed_bytes;
- struct flb_gzip_decompression_context *inner_context;
- int status;
-
- if (*output_length == 0) {
- return FLB_DECOMPRESSOR_SUCCESS;
- }
-
- inner_context = (struct flb_gzip_decompression_context *) \
- context->inner_context;
-
- inner_context->miniz_stream.next_in = context->read_buffer;
- inner_context->miniz_stream.avail_in = context->input_buffer_length;
- inner_context->miniz_stream.next_out = output_buffer;
- inner_context->miniz_stream.avail_out = *output_length;
-
- status = mz_inflate(&inner_context->miniz_stream, MZ_PARTIAL_FLUSH);
-
- if (status != MZ_OK && status != MZ_STREAM_END) {
- context->state = FLB_DECOMPRESSOR_STATE_FAILED;
-
- mz_inflateEnd(&inner_context->miniz_stream);
-
- *output_length = 0;
-
- return FLB_DECOMPRESSOR_FAILURE;
- }
-
- processed_bytes = context->input_buffer_length;;
- processed_bytes -= inner_context->miniz_stream.avail_in;
-
- *output_length -= inner_context->miniz_stream.avail_out;
-
-#ifdef FLB_DECOMPRESSOR_ERASE_DECOMPRESSED_DATA
- if (processed_bytes > 0) {
- memset(context->read_buffer, processed_bytes);
- }
-#endif
-
- context->read_buffer = &context->read_buffer[processed_bytes];
- context->input_buffer_length = inner_context->miniz_stream.avail_in;
-
- if (status == MZ_STREAM_END) {
- mz_inflateEnd(&inner_context->miniz_stream);
-
- context->state = FLB_DECOMPRESSOR_STATE_EXPECTING_FOOTER;
-
- memset(&inner_context->miniz_stream, 0, sizeof(mz_stream));
- }
-
- return FLB_DECOMPRESSOR_SUCCESS;
-}
-
-
-static int flb_gzip_decompressor_process_footer(
- struct flb_decompression_context *context)
-{
- if (context->input_buffer_length < (sizeof(uint32_t) * 2)) {
- return FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- context->input_buffer_length -= (sizeof(uint32_t) * 2);
-
- if (context->input_buffer_length > 0) {
- context->read_buffer = &context->read_buffer[sizeof(uint32_t) * 2];
- }
- else {
- context->read_buffer = context->input_buffer;
- }
-
- context->state = FLB_DECOMPRESSOR_STATE_EXPECTING_HEADER;
-
- return FLB_DECOMPRESSOR_SUCCESS;
-}
-
-int flb_gzip_decompressor_dispatch(struct flb_decompression_context *context,
- void *output_buffer,
- size_t *output_length)
-{
- size_t output_buffer_size;
- int status;
-
- output_buffer_size = *output_length;
-
- *output_length = 0;
-
- status = FLB_DECOMPRESSOR_SUCCESS;
-
- if (context == NULL ||
- context->inner_context == NULL) {
- status = FLB_DECOMPRESSOR_FAILURE;
- }
-
- if (context->input_buffer_length == 0) {
- flb_debug("[gzip] unexpected call with an empty input buffer");
-
- status = FLB_DECOMPRESSOR_INSUFFICIENT_DATA;
- }
-
- if (status == FLB_DECOMPRESSOR_SUCCESS &&
- context->state == FLB_DECOMPRESSOR_STATE_EXPECTING_HEADER) {
- status = flb_gzip_decompressor_process_header(context);
- }
-
- if (status == FLB_DECOMPRESSOR_SUCCESS &&
- context->state == FLB_DECOMPRESSOR_STATE_EXPECTING_OPTIONAL_HEADERS) {
- status = flb_gzip_decompressor_process_optional_headers(context);
- }
-
- if (status == FLB_DECOMPRESSOR_SUCCESS &&
- context->state == FLB_DECOMPRESSOR_STATE_EXPECTING_BODY) {
- *output_length = output_buffer_size;
-
- status = flb_gzip_decompressor_process_body_chunk(
- context,
- output_buffer,
- output_length);
- }
-
- if (status == FLB_DECOMPRESSOR_SUCCESS &&
- context->state == FLB_DECOMPRESSOR_STATE_EXPECTING_FOOTER) {
- status = flb_gzip_decompressor_process_footer(context);
- }
-
- return status;
-}
-
-void *flb_gzip_decompression_context_create()
-{
- struct flb_gzip_decompression_context *context;
-
- context = flb_calloc(1, sizeof(struct flb_gzip_decompression_context));
-
- if (context == NULL) {
- flb_errno();
- }
-
- return (void *) context;
-}
-
-void flb_gzip_decompression_context_destroy(void *context)
-{
- if (context != NULL) {
- flb_free(context);
- }
-}