diff --git a/src/fstapi.c b/src/fstapi.c index 7c67459..1a8ea98 100644 --- a/src/fstapi.c +++ b/src/fstapi.c @@ -3791,7 +3791,8 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc) } gzclose(zhandle); } else if (htyp == FST_BL_HIER_LZ4DUO) { - unsigned char *lz4_cmem = (unsigned char *)malloc(clen); + /* extra null byte to catch any unterminated varint */ + unsigned char *lz4_cmem = (unsigned char *)calloc(1, (uint64_t)clen + 1); unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); unsigned char *lz4_ucmem2; uint64_t uclen2; @@ -3800,8 +3801,10 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc) fstFread(lz4_cmem, clen, 1, xc->f); uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); + lz4_ucmem2 = (unsigned char *)malloc(uclen2); pass_status = + (skiplen2 <= (int)clen) && (uclen2 == (uint64_t)LZ4_decompress_safe_partial((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2, clen - skiplen2, diff --git a/tests/data/malformed/hierarchy_lz4duo_shorter_than_its_varint.fst b/tests/data/malformed/hierarchy_lz4duo_shorter_than_its_varint.fst new file mode 100644 index 0000000..4af215b Binary files /dev/null and b/tests/data/malformed/hierarchy_lz4duo_shorter_than_its_varint.fst differ diff --git a/tests/meson.build b/tests/meson.build index 8a7dadb..bc49406 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -27,6 +27,7 @@ malformed_cases = [ 'chain_table_unterminated', 'chain_uncompresses_past_traversal', 'chain_varint_pair_past_traversal', + 'hierarchy_lz4duo_shorter_than_its_varint', 'geometry_short', 'geometry_varint_unterminated', 'frame_maxhandle_too_big', diff --git a/tests/reader_malformed_files.c b/tests/reader_malformed_files.c index 08f6eae..aaf305c 100644 --- a/tests/reader_malformed_files.c +++ b/tests/reader_malformed_files.c @@ -47,6 +47,11 @@ * continuation bytes, including the last byte, so its varint is * unterminated * + * hierarchy_lz4duo_shorter_than_its_varint.fst + * a doubly LZ4 packed hierarchy section whose data is the single byte + * 0x81, a continuation byte, so the varint in front of its data does not + * end inside the section + * * geometry_short.fst * a geometry section that announces three handles but holds the width * of only one