Skip to content

Commit 79c077c

Browse files
committed
gzip: fix handling of concatenated payloads
Signed-off-by: Eduardo Silva <eduardo@chronosphere.io>
1 parent 2687b38 commit 79c077c

File tree

1 file changed

+80
-15
lines changed

1 file changed

+80
-15
lines changed

src/flb_gzip.c

+80-15
Original file line numberDiff line numberDiff line change
@@ -241,9 +241,8 @@ int flb_gzip_compress(void *in_data, size_t in_len,
241241
return 0;
242242
}
243243

244-
/* Uncompress (inflate) GZip data */
245-
int flb_gzip_uncompress(void *in_data, size_t in_len,
246-
void **out_data, size_t *out_len)
244+
int flb_gzip_uncompress_member(void *in_data, size_t in_len,
245+
void **out_data, size_t *out_len)
247246
{
248247
int status;
249248
uint8_t *p;
@@ -292,7 +291,7 @@ int flb_gzip_uncompress(void *in_data, size_t in_len,
292291
if (flg & FEXTRA) {
293292
xlen = read_le16(start);
294293
if (xlen > in_len - 12) {
295-
flb_error("[gzip] invalid gzip data");
294+
flb_error("[gzip] invalid gzip data (FEXTRA)");
296295
return -1;
297296
}
298297
start += xlen + 2;
@@ -321,7 +320,7 @@ int flb_gzip_uncompress(void *in_data, size_t in_len,
321320
/* Check header crc if present */
322321
if (flg & FHCRC) {
323322
if (start - p > in_len - 2) {
324-
flb_error("[gzip] invalid gzip data (FHRC)");
323+
flb_error("[gzip] invalid gzip data (FHCRC)");
325324
return -1;
326325
}
327326

@@ -414,9 +413,74 @@ int flb_gzip_uncompress(void *in_data, size_t in_len,
414413
return 0;
415414
}
416415

416+
int flb_gzip_uncompress(void *in_data, size_t in_len,
417+
void **out_data, size_t *out_len)
418+
{
419+
int i, ret;
420+
size_t *borders = NULL;
421+
size_t count = 0;
422+
size_t total = 0;
423+
size_t part_len = 0;
424+
size_t out_len_local = 0;
425+
void *out = NULL;
426+
void *final_buf = NULL;
427+
428+
count = flb_gzip_count(in_data, in_len, NULL, 0);
429+
if (count == 0) {
430+
flb_error("[gzip] no valid gzip members found");
431+
return -1;
432+
}
417433

418-
/* Stateful gzip decompressor */
434+
borders = flb_calloc(count + 1, sizeof(size_t));
435+
if (!borders) {
436+
flb_errno();
437+
return -1;
438+
}
439+
440+
ret = flb_gzip_count(in_data, in_len, &borders, count);
441+
if (ret != count) {
442+
flb_free(borders);
443+
return -1;
444+
}
445+
446+
for (i = 0; i < count; i++) {
447+
part_len = borders[i + 1] - borders[i];
448+
out = NULL;
449+
out_len_local = 0;
419450

451+
ret = flb_gzip_uncompress_member((uint8_t *)in_data + borders[i],
452+
part_len, &out, &out_len_local);
453+
if (ret != 0) {
454+
flb_free(out);
455+
flb_free(borders);
456+
flb_free(final_buf);
457+
return -1;
458+
}
459+
460+
final_buf = flb_realloc(final_buf, total + out_len_local);
461+
if (!final_buf) {
462+
flb_errno();
463+
flb_free(out);
464+
flb_free(borders);
465+
flb_errno();
466+
return -1;
467+
}
468+
469+
memcpy((uint8_t *) final_buf + total, out, out_len_local);
470+
total += out_len_local;
471+
flb_free(out);
472+
}
473+
474+
flb_free(borders);
475+
476+
*out_data = final_buf;
477+
*out_len = total;
478+
479+
return 0;
480+
}
481+
482+
483+
/* Stateful gzip decompressor */
420484
static int flb_gzip_decompressor_process_header(
421485
struct flb_decompression_context *context)
422486
{
@@ -802,7 +866,7 @@ static int vaild_os_flag(const char data)
802866

803867
size_t flb_gzip_count(const char *data, size_t len, size_t **out_borders, size_t border_count)
804868
{
805-
int i;
869+
size_t i;
806870
size_t count = 0;
807871
const uint8_t *p;
808872
size_t *borders = NULL;
@@ -812,26 +876,27 @@ size_t flb_gzip_count(const char *data, size_t len, size_t **out_borders, size_t
812876
}
813877

814878
p = (const uint8_t *) data;
815-
/* search other gzip starting bits and method. */
816-
for (i = 2; i < len &&
817-
i + 9 <= len; i++) {
818-
/* A vaild gzip payloads are larger than 18 bytes. */
879+
880+
/* Search gzip starting bits and method */
881+
for (i = 0; i + 9 <= len; i++) {
882+
/* A valid gzip payload must be at least 18 bytes long */
819883
if (len - i < 18) {
820884
break;
821885
}
822886

823887
if (p[i] == 0x1F && p[i+1] == 0x8B && p[i+2] == 8 &&
824888
vaild_os_flag(p[i+9])) {
825-
if (out_borders != NULL) {
889+
890+
if (out_borders != NULL && count < border_count) {
826891
borders[count] = i;
827892
}
828893
count++;
829894
}
830895
}
831896

832-
if (out_borders != NULL && border_count >= count) {
833-
/* The length of the last border refers to the original length. */
834-
borders[border_count] = len;
897+
/* Append total length as the end boundary */
898+
if (out_borders != NULL && count > 0 && border_count >= count) {
899+
borders[count] = len;
835900
}
836901

837902
return count;

0 commit comments

Comments
 (0)