Skip to content

Commit e8ff7d1

Browse files
committed
removed FlexArray pattern from CCtxPool
within ZSTDMT_. This pattern is flagged by less forgiving variants of ubsan notably used during compilation of the Linux Kernel. There are 2 other places in the code where this pattern is used. This fixes just one of them.
1 parent c692b8d commit e8ff7d1

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

lib/compress/zstd_compress.c

+1
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ static void ZSTD_freeCCtxContent(ZSTD_CCtx* cctx)
178178

179179
size_t ZSTD_freeCCtx(ZSTD_CCtx* cctx)
180180
{
181+
DEBUGLOG(3, "ZSTD_freeCCtx (address: %p)", (void*)cctx);
181182
if (cctx==NULL) return 0; /* support free on NULL */
182183
RETURN_ERROR_IF(cctx->staticSize, memory_allocation,
183184
"not compatible with static CCtx");

lib/compress/zstdmt_compress.c

+18-11
Original file line numberDiff line numberDiff line change
@@ -350,15 +350,16 @@ typedef struct {
350350
int totalCCtx;
351351
int availCCtx;
352352
ZSTD_customMem cMem;
353-
ZSTD_CCtx* cctx[1]; /* variable size */
353+
ZSTD_CCtx** cctxs;
354354
} ZSTDMT_CCtxPool;
355355

356-
/* note : all CCtx borrowed from the pool should be released back to the pool _before_ freeing the pool */
356+
/* note : all CCtx borrowed from the pool must be reverted back to the pool _before_ freeing the pool */
357357
static void ZSTDMT_freeCCtxPool(ZSTDMT_CCtxPool* pool)
358358
{
359359
int cid;
360360
for (cid=0; cid<pool->totalCCtx; cid++)
361-
ZSTD_freeCCtx(pool->cctx[cid]); /* note : compatible with free on NULL */
361+
ZSTD_freeCCtx(pool->cctxs[cid]); /* note : compatible with free on NULL */
362+
ZSTD_customFree(pool->cctxs, pool->cMem);
362363
ZSTD_pthread_mutex_destroy(&pool->poolMutex);
363364
ZSTD_customFree(pool, pool->cMem);
364365
}
@@ -373,14 +374,19 @@ static ZSTDMT_CCtxPool* ZSTDMT_createCCtxPool(int nbWorkers,
373374
assert(nbWorkers > 0);
374375
if (!cctxPool) return NULL;
375376
if (ZSTD_pthread_mutex_init(&cctxPool->poolMutex, NULL)) {
377+
ZSTDMT_freeCCtxPool(cctxPool);
378+
return NULL;
379+
}
380+
cctxPool->totalCCtx = nbWorkers;
381+
cctxPool->cctxs = (ZSTD_CCtx**)ZSTD_customCalloc(nbWorkers * sizeof(ZSTD_CCtx*), cMem);
382+
if (!cctxPool->cctxs) {
376383
ZSTD_customFree(cctxPool, cMem);
377384
return NULL;
378385
}
379386
cctxPool->cMem = cMem;
380-
cctxPool->totalCCtx = nbWorkers;
387+
cctxPool->cctxs[0] = ZSTD_createCCtx_advanced(cMem);
388+
if (!cctxPool->cctxs[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
381389
cctxPool->availCCtx = 1; /* at least one cctx for single-thread mode */
382-
cctxPool->cctx[0] = ZSTD_createCCtx_advanced(cMem);
383-
if (!cctxPool->cctx[0]) { ZSTDMT_freeCCtxPool(cctxPool); return NULL; }
384390
DEBUGLOG(3, "cctxPool created, with %u workers", nbWorkers);
385391
return cctxPool;
386392
}
@@ -404,14 +410,15 @@ static size_t ZSTDMT_sizeof_CCtxPool(ZSTDMT_CCtxPool* cctxPool)
404410
{ unsigned const nbWorkers = cctxPool->totalCCtx;
405411
size_t const poolSize = sizeof(*cctxPool)
406412
+ (nbWorkers-1) * sizeof(ZSTD_CCtx*);
407-
unsigned u;
413+
size_t const arraySize = cctxPool->totalCCtx * sizeof(ZSTD_CCtx*);
408414
size_t totalCCtxSize = 0;
415+
unsigned u;
409416
for (u=0; u<nbWorkers; u++) {
410-
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctx[u]);
417+
totalCCtxSize += ZSTD_sizeof_CCtx(cctxPool->cctxs[u]);
411418
}
412419
ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
413420
assert(nbWorkers > 0);
414-
return poolSize + totalCCtxSize;
421+
return poolSize + arraySize + totalCCtxSize;
415422
}
416423
}
417424

@@ -421,7 +428,7 @@ static ZSTD_CCtx* ZSTDMT_getCCtx(ZSTDMT_CCtxPool* cctxPool)
421428
ZSTD_pthread_mutex_lock(&cctxPool->poolMutex);
422429
if (cctxPool->availCCtx) {
423430
cctxPool->availCCtx--;
424-
{ ZSTD_CCtx* const cctx = cctxPool->cctx[cctxPool->availCCtx];
431+
{ ZSTD_CCtx* const cctx = cctxPool->cctxs[cctxPool->availCCtx];
425432
ZSTD_pthread_mutex_unlock(&cctxPool->poolMutex);
426433
return cctx;
427434
} }
@@ -435,7 +442,7 @@ static void ZSTDMT_releaseCCtx(ZSTDMT_CCtxPool* pool, ZSTD_CCtx* cctx)
435442
if (cctx==NULL) return; /* compatibility with release on NULL */
436443
ZSTD_pthread_mutex_lock(&pool->poolMutex);
437444
if (pool->availCCtx < pool->totalCCtx)
438-
pool->cctx[pool->availCCtx++] = cctx;
445+
pool->cctxs[pool->availCCtx++] = cctx;
439446
else {
440447
/* pool overflow : should not happen, since totalCCtx==nbWorkers */
441448
DEBUGLOG(4, "CCtx pool overflow : free cctx");

tests/fuzzer.c

+8-6
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,9 @@ static int basicUnitTests(U32 const seed, double compressibility)
11191119
size_t const srcSize1 = kWindowSize / 2;
11201120
size_t const srcSize2 = kWindowSize * 10;
11211121

1122+
CHECK(cctx!=NULL);
1123+
CHECK(dctx!=NULL);
1124+
CHECK(dict!=NULL);
11221125
if (CNBuffSize < dictSize) goto _output_error;
11231126

11241127
RDG_genBuffer(dict, dictSize, 0.5, 0.5, seed);
@@ -1140,6 +1143,7 @@ static int basicUnitTests(U32 const seed, double compressibility)
11401143
cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize1);
11411144
CHECK_Z(cSize);
11421145
CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));
1146+
11431147
cSize = ZSTD_compress2(cctx, compressedBuffer, compressedBufferSize, CNBuffer, srcSize2);
11441148
/* Streaming decompression to catch out of bounds offsets. */
11451149
{
@@ -1153,24 +1157,22 @@ static int basicUnitTests(U32 const seed, double compressibility)
11531157
CHECK_Z(ZSTD_CCtx_setParameter(cctx, ZSTD_c_nbWorkers, 2));
11541158
/* Round trip once with a dictionary. */
11551159
CHECK_Z(ZSTD_CCtx_refPrefix(cctx, dict, dictSize));
1156-
{
1157-
ZSTD_inBuffer in = {CNBuffer, srcSize1, 0};
1160+
{ ZSTD_inBuffer in = {CNBuffer, srcSize1, 0};
11581161
ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};
11591162
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
11601163
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
11611164
cSize = out.pos;
11621165
}
11631166
CHECK_Z(ZSTD_decompress_usingDict(dctx, decodedBuffer, CNBuffSize, compressedBuffer, cSize, dict, dictSize));
1164-
{
1165-
ZSTD_inBuffer in = {CNBuffer, srcSize2, 0};
1167+
1168+
{ ZSTD_inBuffer in = {CNBuffer, srcSize2, 0};
11661169
ZSTD_outBuffer out = {compressedBuffer, compressedBufferSize, 0};
11671170
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_flush));
11681171
CHECK_Z(ZSTD_compressStream2(cctx, &out, &in, ZSTD_e_end));
11691172
cSize = out.pos;
11701173
}
11711174
/* Streaming decompression to catch out of bounds offsets. */
1172-
{
1173-
ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
1175+
{ ZSTD_inBuffer in = {compressedBuffer, cSize, 0};
11741176
ZSTD_outBuffer out = {decodedBuffer, CNBuffSize, 0};
11751177
size_t const dSize = ZSTD_decompressStream(dctx, &out, &in);
11761178
CHECK_Z(dSize);

0 commit comments

Comments
 (0)