Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LzmaLib: compress / decompress buffer in C

I'm trying to use LzmaLib's LzmaCompress() and LzmaDecompress() with buffers, adapting the examples provided here.

I'm testing with a ~3MB buffer and the compression function seems to work fine (produces a ~1.2MB compressed buffer), but when I try to decompress, it just extracts ~300 bytes and returns SZ_ERROR_DATA.

The few extracted bytes are right, but I don't know why it stops there.

My code:

#include <stdio.h>
#include <stdlib.h>

#include "LzmaLib.h"

void compress(
    unsigned char **outBuf, size_t *dstLen,
    unsigned char *inBuf, size_t srcLen)
{
    unsigned propsSize = LZMA_PROPS_SIZE;
    *dstLen = srcLen + srcLen / 3 + 128;

    *outBuf = (unsigned char*)malloc(propsSize + *dstLen);

    int res = LzmaCompress(
        (unsigned char*)(*outBuf + LZMA_PROPS_SIZE), dstLen,
        inBuf, srcLen,
        *outBuf, &propsSize,
        -1, 0, -1, -1, -1, -1, -1);

    assert(res == SZ_OK);

    *dstLen = *dstLen + LZMA_PROPS_SIZE;
}

void uncompress(
    unsigned char **outBuf, size_t *dstLen,
    unsigned char *inBuf,  size_t srcLen
) {
    *dstLen = 5000000;
    *outBuf = (unsigned char*)malloc(*dstLen);

    srcLen = srcLen - LZMA_PROPS_SIZE;
    int res = LzmaUncompress(
        *outBuf, dstLen,
        (unsigned char*)(inBuf + LZMA_PROPS_SIZE), &srcLen,
        inBuf, LZMA_PROPS_SIZE);

    assert(res == SZ_OK);
}

void do_compress() {
    FILE* file = fopen("Module.dll", "r");
    size_t size, decSize;
    unsigned char *data, *dec = NULL;

    fseek(file, 0L, SEEK_END);
    size = ftell(file);
    fseek(file, 0L, SEEK_SET);

    data = (unsigned char*)malloc(size);
    fread(data, 1, size, file);
    fclose(file);

    compress((unsigned char**)&dec, &decSize, data, size);

    file = fopen("Module.lzma", "w");
    fwrite(dec, 1, decSize, file);
    fclose(file);
}

void do_uncompress() {
    FILE* file = fopen("Module.lzma", "r");
    size_t size, decSize;
    unsigned char *data, *dec = NULL;

    fseek(file, 0L, SEEK_END);
    size = ftell(file);
    fseek(file, 0L, SEEK_SET);

    data = (unsigned char*)malloc(size);
    fread(data, 1, size, file);
    fclose(file);

    uncompress((unsigned char**)&dec, &decSize, data, size);

    file = fopen("Module_DEC.dll", "w");
    fwrite(dec, 1, decSize, file);
    fclose(file);
}

int main()
{
    do_compress();
    do_uncompress();

    return 0;
}

If this code is not the better way to compress buffers with LzmaLib, I'm happy to accept suggestions.

like image 958
karliwson Avatar asked Nov 22 '16 02:11

karliwson


1 Answers

I bet the problem lurks in how you read/write your files. You need to open them in binary mode to prevent any substitutions during read/write operations.

Change all instances of:

  • fopen(xxx, "r") -> fopen(xxx, "rb")
  • fopen(xxx, "w") -> fopen(xxx, "wb")
like image 103
Codeguard Avatar answered Oct 22 '22 03:10

Codeguard