Merge pull request #474 from terrelln/compression-segfault

Fix compression segfault
dev
Yann Collet 2016-12-11 22:28:24 +01:00 committed by GitHub
commit e93f1f5893
4 changed files with 96 additions and 3 deletions

View File

@ -2277,7 +2277,7 @@ static size_t ZSTD_compress_generic (ZSTD_CCtx* cctx,
if (cctx->lowLimit > (1<<30)) { if (cctx->lowLimit > (1<<30)) {
U32 const btplus = (cctx->params.cParams.strategy == ZSTD_btlazy2) | (cctx->params.cParams.strategy == ZSTD_btopt) | (cctx->params.cParams.strategy == ZSTD_btopt2); U32 const btplus = (cctx->params.cParams.strategy == ZSTD_btlazy2) | (cctx->params.cParams.strategy == ZSTD_btopt) | (cctx->params.cParams.strategy == ZSTD_btopt2);
U32 const chainMask = (1 << (cctx->params.cParams.chainLog - btplus)) - 1; U32 const chainMask = (1 << (cctx->params.cParams.chainLog - btplus)) - 1;
U32 const supLog = MAX(cctx->params.cParams.chainLog, 17 /* blockSize */); U32 const supLog = MAX(cctx->params.cParams.windowLog, 17 /* blockSize */);
U32 const newLowLimit = (cctx->lowLimit & chainMask) + (1 << supLog); /* preserve position % chainSize, ensure current-repcode doesn't underflow */ U32 const newLowLimit = (cctx->lowLimit & chainMask) + (1 << supLog); /* preserve position % chainSize, ensure current-repcode doesn't underflow */
U32 const correction = cctx->lowLimit - newLowLimit; U32 const correction = cctx->lowLimit - newLowLimit;
ZSTD_reduceIndex(cctx, correction); ZSTD_reduceIndex(cctx, correction);

1
tests/.gitignore vendored
View File

@ -11,6 +11,7 @@ datagen
paramgrill paramgrill
paramgrill32 paramgrill32
roundTripCrash roundTripCrash
longmatch
# Tmp test directory # Tmp test directory
zstdtest zstdtest

View File

@ -124,6 +124,9 @@ datagen : $(PRGDIR)/datagen.c datagencli.c
roundTripCrash : $(ZSTD_FILES) roundTripCrash.c roundTripCrash : $(ZSTD_FILES) roundTripCrash.c
$(CC) $(FLAGS) $^ -o $@$(EXT) $(CC) $(FLAGS) $^ -o $@$(EXT)
longmatch : $(ZSTD_FILES) longmatch.c
$(CC) $(FLAGS) $^ -o $@$(EXT)
namespaceTest: namespaceTest:
if $(CC) namespaceTest.c ../lib/common/xxhash.c -o $@ ; then echo compilation should fail; exit 1 ; fi if $(CC) namespaceTest.c ../lib/common/xxhash.c -o $@ ; then echo compilation should fail; exit 1 ; fi
$(RM) $@ $(RM) $@
@ -140,7 +143,7 @@ clean:
fullbench-lib$(EXT) fullbench-dll$(EXT) \ fullbench-lib$(EXT) fullbench-dll$(EXT) \
fuzzer$(EXT) fuzzer32$(EXT) zbufftest$(EXT) zbufftest32$(EXT) \ fuzzer$(EXT) fuzzer32$(EXT) zbufftest$(EXT) zbufftest32$(EXT) \
zstreamtest$(EXT) zstreamtest32$(EXT) \ zstreamtest$(EXT) zstreamtest32$(EXT) \
datagen$(EXT) paramgrill$(EXT) roundTripCrash$(EXT) datagen$(EXT) paramgrill$(EXT) roundTripCrash$(EXT) longmatch$(EXT)
@echo Cleaning completed @echo Cleaning completed
@ -180,7 +183,7 @@ zstd-playTests: datagen
file $(ZSTD) file $(ZSTD)
ZSTD="$(QEMU_SYS) $(ZSTD)" ./playTests.sh $(ZSTDRTTEST) ZSTD="$(QEMU_SYS) $(ZSTD)" ./playTests.sh $(ZSTDRTTEST)
test: test-zstd test-fullbench test-fuzzer test-zstream test: test-zstd test-fullbench test-fuzzer test-zstream test-longmatch
test32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32 test32: test-zstd32 test-fullbench32 test-fuzzer32 test-zstream32
@ -237,4 +240,7 @@ test-zstream: zstreamtest
test-zstream32: zstreamtest32 test-zstream32: zstreamtest32
$(QEMU_SYS) ./zstreamtest32 $(ZSTREAM_TESTTIME) $(QEMU_SYS) ./zstreamtest32 $(ZSTREAM_TESTTIME)
test-longmatch: longmatch
$(QEMU_SYS) ./longmatch
endif endif

86
tests/longmatch.c Normal file
View File

@ -0,0 +1,86 @@
#define ZSTD_STATIC_LINKING_ONLY
#include "zstd.h"
#include "mem.h"
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
int compress(ZSTD_CStream *ctx, ZSTD_outBuffer out, const void *data, size_t size) {
ZSTD_inBuffer in = { data, size, 0 };
while (in.pos < in.size) {
ZSTD_outBuffer tmp = out;
const size_t rc = ZSTD_compressStream(ctx, &tmp, &in);
if (ZSTD_isError(rc)) {
return 1;
}
}
{
ZSTD_outBuffer tmp = out;
const size_t rc = ZSTD_flushStream(ctx, &tmp);
if (rc != 0) { return 1; }
}
return 0;
}
int main(int argc, const char** argv) {
ZSTD_CStream *ctx;
ZSTD_parameters params;
size_t rc;
unsigned windowLog;
(void)argc;
(void)argv;
/* Create stream */
ctx = ZSTD_createCStream();
if (!ctx) { return 1; }
/* Set parameters */
memset(&params, 0, sizeof(params));
params.cParams.windowLog = 18;
params.cParams.chainLog = 13;
params.cParams.hashLog = 14;
params.cParams.searchLog = 1;
params.cParams.searchLength = 7;
params.cParams.targetLength = 16;
params.cParams.strategy = ZSTD_fast;
windowLog = params.cParams.windowLog;
/* Initialize stream */
rc = ZSTD_initCStream_advanced(ctx, NULL, 0, params, 0);
if (ZSTD_isError(rc)) { return 2; }
{
U64 compressed = 0;
const U64 toCompress = ((U64)1) << 33;
const size_t size = 1 << windowLog;
size_t pos = 0;
char *srcBuffer = (char*) malloc(1 << windowLog);
char *dstBuffer = (char*) malloc(ZSTD_compressBound(1 << windowLog));
ZSTD_outBuffer out = { dstBuffer, ZSTD_compressBound(1 << windowLog), 0 };
const char match[] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
const size_t randomData = (1 << windowLog) - 2*sizeof(match);
size_t i;
for (i = 0; i < sizeof(match); ++i) {
srcBuffer[i] = match[i];
}
for (i = 0; i < randomData; ++i) {
srcBuffer[sizeof(match) + i] = (char)(rand() & 0xFF);
}
for (i = 0; i < sizeof(match); ++i) {
srcBuffer[sizeof(match) + randomData + i] = match[i];
}
if (compress(ctx, out, srcBuffer, size)) {
return 1;
}
compressed += size;
while (compressed < toCompress) {
const size_t block = rand() % (size - pos + 1);
if (pos == size) { pos = 0; }
if (compress(ctx, out, srcBuffer + pos, block)) {
return 1;
}
pos += block;
compressed += block;
}
free(srcBuffer);
free(dstBuffer);
}
return 0;
}