Example #1
0
size_t FSE_decompress_wksp(void* dst, size_t dstCapacity, const void* cSrc, size_t cSrcSize, FSE_DTable* workSpace, unsigned maxLog)
{
    const BYTE* const istart = (const BYTE*)cSrc;
    const BYTE* ip = istart;
    short counting[FSE_MAX_SYMBOL_VALUE+1];
    unsigned tableLog;
    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;

    /* normal FSE decoding mode */
    size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
    if (FSE_isError(NCountLength)) return NCountLength;
    //if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size; supposed to be already checked in NCountLength, only remaining case : NCountLength==cSrcSize */
    if (tableLog > maxLog) return ERROR(tableLog_tooLarge);
    ip += NCountLength;
    cSrcSize -= NCountLength;

    CHECK_F( FSE_buildDTable (workSpace, counting, maxSymbolValue, tableLog) );

    return FSE_decompress_usingDTable (dst, dstCapacity, ip, cSrcSize, workSpace);   /* always return, even if it is an error code */
}
size_t FSE_decompress(void* dst, size_t maxDstSize, const void* cSrc, size_t cSrcSize)
{
    const BYTE* const istart = (const BYTE*)cSrc;
    const BYTE* ip = istart;
    short counting[FSE_MAX_SYMBOL_VALUE+1];
    DTable_max_t dt;   /* Static analyzer seems unable to understand this table will be properly initialized later */
    unsigned tableLog;
    unsigned maxSymbolValue = FSE_MAX_SYMBOL_VALUE;

    if (cSrcSize<2) return ERROR(srcSize_wrong);   /* too small input size */

    /* normal FSE decoding mode */
    {   size_t const NCountLength = FSE_readNCount (counting, &maxSymbolValue, &tableLog, istart, cSrcSize);
        if (FSE_isError(NCountLength)) return NCountLength;
        if (NCountLength >= cSrcSize) return ERROR(srcSize_wrong);   /* too small input size */
        ip += NCountLength;
        cSrcSize -= NCountLength;
    }

    CHECK_F( FSE_buildDTable (dt, counting, maxSymbolValue, tableLog) );

    return FSE_decompress_usingDTable (dst, maxDstSize, ip, cSrcSize, dt);   /* always return, even if it is an error code */
}
Example #3
0
static void unitTest(void)
{
    BYTE* testBuff = (BYTE*)malloc(TBSIZE);
    BYTE* cBuff = (BYTE*)malloc(FSE_COMPRESSBOUND(TBSIZE));
    BYTE* verifBuff = (BYTE*)malloc(TBSIZE);
    size_t errorCode;
    U32 seed=0, testNb=0, lseed=0;
    U32 count[256];

    if ((!testBuff) || (!cBuff) || (!verifBuff))
    {
        DISPLAY("Not enough memory, exiting ... \n");
        free(testBuff);
        free(cBuff);
        free(verifBuff);
        return;
    }

    /* FSE_count */
    {
        U32 max, i;
        for (i=0; i< TBSIZE; i++) testBuff[i] = (FUZ_rand(&lseed) & 63) + '0';
        max = '0' + 63;
        errorCode = FSE_count(count, &max, testBuff, TBSIZE);
        CHECK(FSE_isError(errorCode), "Error : FSE_count() should have worked");
        max -= 1;
        errorCode = FSE_count(count, &max, testBuff, TBSIZE);
        CHECK(!FSE_isError(errorCode), "Error : FSE_count() should have failed : value > max");
        max = 65000;
        errorCode = FSE_count(count, &max, testBuff, TBSIZE);
        CHECK(FSE_isError(errorCode), "Error : FSE_count() should have worked");
    }

    /* FSE_optimalTableLog */
    {
        U32 max, i, tableLog=12;
        size_t testSize = 999;
        for (i=0; i< testSize; i++) testBuff[i] = (BYTE)FUZ_rand(&lseed);
        max = 256;
        FSE_count(count, &max, testBuff, testSize);
        tableLog = FSE_optimalTableLog(tableLog, testSize, max);
        CHECK(tableLog<=8, "Too small tableLog");
    }

    /* FSE_normalizeCount */
    {
        S16 norm[256];
        U32 max = 256;
        FSE_count(count, &max, testBuff, TBSIZE);
        errorCode = FSE_normalizeCount(norm, 10, count, TBSIZE, max);
        CHECK(FSE_isError(errorCode), "Error : FSE_normalizeCount() should have worked");
        errorCode = FSE_normalizeCount(norm, 8, count, TBSIZE, 256);
        CHECK(!FSE_isError(errorCode), "Error : FSE_normalizeCount() should have failed (max >= 1<<tableLog)");
        /* limit corner case : try to make internal rank overflow */
        {
            U32 i;
            U32 total = 0;
            count[0] =  940;
            count[1] =  910;
            count[2] =  470;
            count[3] =  190;
            count[4] =   90;
            for(i=5; i<=255; i++) count[i] = 6;
            for (i=0; i<=255; i++) total += count[i];
            errorCode = FSE_normalizeCount(norm, 10, count, total, 255);
            CHECK(FSE_isError(errorCode), "Error : FSE_normalizeCount() should have worked");
            count[0] =  300;
            count[1] =  300;
            count[2] =  300;
            count[3] =  300;
            count[4] =   50;
            for(i=5; i<=80; i++) count[i] = 4;
            total = 0; for (i=0; i<=80; i++) total += count[i];
            errorCode = FSE_normalizeCount(norm, 10, count, total, 80);
            CHECK(FSE_isError(errorCode), "Error : FSE_normalizeCount() should have worked");
        }
    }

    /* FSE_writeNCount, FSE_readNCount */
    {
        S16 norm[129];
        BYTE header[513];
        U32 max, tableLog, i;
        size_t headerSize;

        for (i=0; i< TBSIZE; i++) testBuff[i] = i % 127;
        max = 128;
        errorCode = FSE_count(count, &max, testBuff, TBSIZE);
        CHECK(FSE_isError(errorCode), "Error : FSE_count() should have worked");
        tableLog = FSE_optimalTableLog(0, TBSIZE, max);
        errorCode = FSE_normalizeCount(norm, tableLog, count, TBSIZE, max);
        CHECK(FSE_isError(errorCode), "Error : FSE_normalizeCount() should have worked");

        headerSize = FSE_NCountWriteBound(max, tableLog);

        headerSize = FSE_writeNCount(header, 513, norm, max, tableLog);
        CHECK(FSE_isError(headerSize), "Error : FSE_writeNCount() should have worked");

        header[headerSize-1] = 0;
        errorCode = FSE_writeNCount(header, headerSize-1, norm, max, tableLog);
        CHECK(!FSE_isError(errorCode), "Error : FSE_writeNCount() should have failed");
        CHECK (header[headerSize-1] != 0, "Error : FSE_writeNCount() buffer overwrite");

        errorCode = FSE_writeNCount(header, headerSize+1, norm, max, tableLog);
        CHECK(FSE_isError(errorCode), "Error : FSE_writeNCount() should have worked");

        max = 129;
        errorCode = FSE_readNCount(norm, &max, &tableLog, header, headerSize);
        CHECK(FSE_isError(errorCode), "Error : FSE_readNCount() should have worked : (error %s)", FSE_getErrorName(errorCode));

        max = 64;
        errorCode = FSE_readNCount(norm, &max, &tableLog, header, headerSize);
        CHECK(!FSE_isError(errorCode), "Error : FSE_readNCount() should have failed (max too small)");

        max = 129;
        errorCode = FSE_readNCount(norm, &max, &tableLog, header, headerSize-1);
        CHECK(!FSE_isError(errorCode), "Error : FSE_readNCount() should have failed (size too small)");

        {
            void* smallBuffer = malloc(headerSize-1);   /* outbound read can be caught by valgrind */
            CHECK(smallBuffer==NULL, "Error : Not enough memory (FSE_readNCount unit test)");
            memcpy(smallBuffer, header, headerSize-1);
            max = 129;
            errorCode = FSE_readNCount(norm, &max, &tableLog, smallBuffer, headerSize-1);
            CHECK(!FSE_isError(errorCode), "Error : FSE_readNCount() should have failed (size too small)");
            free(smallBuffer);
        }
    }


    /* FSE_buildCTable_raw & FSE_buildDTable_raw */
    {
        U32 ct[FSE_CTABLE_SIZE_U32(8, 256)];
        U32 dt[FSE_DTABLE_SIZE_U32(8)];
        U64 crcOrig, crcVerif;
        size_t cSize, verifSize;

        U32 i;
        for (i=0; i< TBSIZE; i++) testBuff[i] = (FUZ_rand(&seed) & 63) + '0';
        crcOrig = XXH64(testBuff, TBSIZE, 0);

        errorCode = FSE_buildCTable_raw(ct, 8);
        CHECK(FSE_isError(errorCode), "FSE_buildCTable_raw should have worked");
        errorCode = FSE_buildDTable_raw(dt, 8);
        CHECK(FSE_isError(errorCode), "FSE_buildDTable_raw should have worked");

        cSize = FSE_compress_usingCTable(cBuff, FSE_COMPRESSBOUND(TBSIZE), testBuff, TBSIZE, ct);
        CHECK(FSE_isError(cSize), "FSE_compress_usingCTable should have worked using raw CTable");

        verifSize = FSE_decompress_usingDTable(verifBuff, TBSIZE, cBuff, cSize, dt);
        CHECK(FSE_isError(verifSize), "FSE_decompress_usingDTable should have worked using raw DTable");

        crcVerif = XXH64(verifBuff, verifSize, 0);
        CHECK(crcOrig != crcVerif, "Raw regenerated data is corrupted");
    }

    /* known corner case */
    {
        BYTE sample8[8] = { 0, 0, 0, 2, 0, 0, 0, 0 };
        BYTE* rBuff;
        errorCode = FSE_compress(cBuff, TBSIZE, sample8, 8);
        CHECK(FSE_isError(errorCode), "FSE_compress failed compressing sample8");
        rBuff = (BYTE*)malloc(errorCode);   /* in order to catch read overflow with Valgrind */
        CHECK(rBuff==NULL, "Not enough memory for rBuff");
        memcpy(rBuff, cBuff, errorCode);
        errorCode = FSE_decompress(verifBuff, sizeof(sample8), rBuff, errorCode);
        CHECK(errorCode != sizeof(sample8), "FSE_decompress failed regenerating sample8");
        free(rBuff);
    }

    free(testBuff);
    free(cBuff);
    free(verifBuff);
    DISPLAY("Unit tests completed\n");
}