Hi,
I am using LZMA SDK to compress/decompress data as a plugin for IBM MQ. I have tested it on AIX, HP-UX, IBM i (OS/400), Linux x86, x64, POWER & z/System, Solaris SPARC & x64 and Windows.
The decompress routine crashes on IBM i (OS/400).
The compression appears to work. Here is a code snippet of it:
int res;
size_t propsSize = LZMA_PROPS_SIZE;
CLzmaEncProps props;
ISzAlloc my_g_Alloc = { SzAlloc, SzFree };
ISzAlloc my_g_BigAlloc = { SzBigAlloc, SzBigFree };
LzmaEncProps_Init(&props);
props.level = 4;
props.dictSize = 65536;
props.lc = 3;
props.lp = 0;
props.pb = 2;
props.fb = 32;
props.numThreads = 1;
res = LzmaEncode(pTgt + LZMA_PROPS_SIZE,
targetLength,
pSrc,
sourceLength,
&props,
pTgt, // out props
&propsSize, // out props size
0,
NULL,
&my_g_Alloc,
&my_g_BigAlloc);
And here is what I'm using to decompress it:
int res;
ELzmaStatus status;
size_t compressed_size = sourceLength - LZMA_PROPS_SIZE;
ISzAlloc my_g_Alloc = { SzAlloc, SzFree };
res = LzmaDecode(pTgt,
targetLength,
pSrc + LZMA_PROPS_SIZE,
&compressed_size,
pSrc, // props
LZMA_PROPS_SIZE,
LZMA_FINISH_ANY,
&status,
&my_g_Alloc);
I spent serveral days trying to figure this out but I'm stumped.
At first I thought it was CLzmaDec p
in the LzmaDecode
subroutine, so I change it to a pointer and allocate memory for it. But it didn't fix the issue of crashing. So, I put printfs everywhere and tracked it done to LZMA_DECODE_REAL
subroutine. Specifically, it is in the define IF_BIT_0(prob)
where ttt = *(prob);
is used.
Note: It is on the first pass in LZMA_DECODE_REAL
subroutine. Here is the output from the last 3 printfs before it crashes (p, probs & prob are outputted as a pointer i.e. %p):
LZMA_DECODE_REAL 1 p=SPP:0000 :0000 :0:0:1d : sizeof(CLzmaProb)=2
LZMA_DECODE_REAL 2 probs=SPP:0000 :0000 :0:1:1d : IsMatch=-256 : COMBINED_PS_STATE=0
LZMA_DECODE_REAL 3 prob=SPP:0000 :0000 :0:2:1d
Printf #1 is right before entering the do while loop (line # 238).
Printf #2 is right before setting prob
(line # 245).
Printf #3 is right before IF_BIT_0(prob)
(line # 247).
I expanded IF_BIT_0(prob)
into its 4 parts and put printfs after each one.
The code crahed on ttt = *(p);
aka ttt = *(prob);
because printf # 4 was not executed because of the crash.
The only compile define that I am using is _7ZIP_ST
but that define is not used by LzmaDec.c.
I thought maybe it was a Big Endian isue but the code runs fine on AIX and Solaris SPARC. The other odd thing I noticed when running it on AIX and Solaris SPARC, is that IsMatch
is always -256.
Is there some other define I should be setting to get it to work on IBM i (OS/400)?
Regards,
Roger
try to look
sizeof(UInt32)
.it must be 4.
to debug the code, you can simplify situation.
1) find the smallest file with failure.
2) reduce the properties with
props.lc = 0
;3) call Lzma decoder in loop, where each itaration decompresses only one byte with LzmaDec_DecodeToDic().
LzmaDec_Construct()
LzmaDec_Allocate()
LzmaDec_Init()
LzmaDec_DecodeToDic()
LzmaDec_DecodeToDic()
LzmaDec_DecodeToDic()
you can printf() partial or full state including probs array after each decoded byte to text file.
Then compare text files for normal decoding and decoding with failure. That can show the exact step with difference.