Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.3k views
in Technique[技术] by (71.8m points)

compression - ZStd. Heap corruption after decompression

In most cases it work good. For example, I compress 3D mesh. Almost all models compressdecompress good. But 2 or 3 models can give error when program try decompress it. It decompress good, but error when I free memory

    // how I read my files
    u8* compressed_v = nullptr;
    u8* compressed_i = nullptr;
    if(!meshhead.m_dataComressSize_i)
    {
        YY_PRINT_FAILED;
        return nullptr;
    }
    if(!meshhead.m_dataComressSize_v)
    {
        YY_PRINT_FAILED;
        return nullptr;
    }
    
    compressed_v = (u8*)yyMemAlloc(meshhead.m_dataComressSize_v);
    compressed_i = (u8*)yyMemAlloc(meshhead.m_dataComressSize_i);
                            
    in.read((char*)compressed_v, meshhead.m_dataComressSize_v);
    in.read((char*)compressed_i, meshhead.m_dataComressSize_i);
    u32 outsize = 0;
    new_mesh.m_data->m_vertices = yyDecompressData(compressed_v, meshhead.m_dataComressSize_v, outsize, yyCompressType::ZStd);
    new_mesh.m_data->m_indices = (u8*)yyDecompressData(compressed_i, meshhead.m_dataComressSize_i, outsize, yyCompressType::ZStd);
    
    ...
    yyMemFree(compressed_v);
    yyMemFree(compressed_i); // ERROR HERE

yyMemAlloc and yyMemFree it's just malloc and free from mylib.dll

Now ZStd code. Please check.

    u8* Engine::compressData_zstd( u8* in_data, u32 in_data_size, u32& out_data_size)
    {
        u8* out_data = (u8*)yyMemAlloc(in_data_size); // malloc
        if( !out_data )
        {
            YY_PRINT_FAILED;
            return nullptr;
        }
    
        auto compressBound = ZSTD_compressBound(in_data_size);
    
        size_t const cSize = ZSTD_compressCCtx( m_cctx, out_data, compressBound, in_data, in_data_size, 1);
        if( ZSTD_isError(cSize) )
        {
            yyMemFree(out_data); // free
            return nullptr;
        }
    
        //yyMemRealloc(out_data,(u32)cSize); // this give errors so I removed it
        out_data_size = (u32)cSize;
        return out_data;
    }
    
    u8* Engine::decompressData_zstd( u8* in_data, u32 in_data_size, u32& out_data_size)
    {
        unsigned long long const rSize = ZSTD_getFrameContentSize(in_data, in_data_size);
        u8* out_data = (u8*)yyMemAlloc((u32)rSize);
        if( !out_data )
        {
            YY_PRINT_FAILED;
            return nullptr;
        }
    
        size_t const dSize = ZSTD_decompress(out_data, (size_t)rSize, in_data, in_data_size);
        out_data_size = (u32)dSize;
        return out_data;
    }

Or maybe ZStd code is good, and problem somewhere else?

It looks like problem in yyMemAlloc and yyMemFree but it just malloc and free and I use it everywhere in different modules (.exe and many .dll) and all ok.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

If in_data is not compressible, it will need more than in_data_size to be represented.

The actual worst case is calculated by the way, in the value compressBound.

So allocate compressBound bytes for out_data, instead of in_data_size.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...