CSparseStream::Read() contains several subtractions that can wrap based on user input, eg:
UInt64 rem = item.Size - virtPos;
Please add checks before the subtractions to ensure the left hand value is >= the right hand value.
This was found using AFL fuzzer.
PoC that causes a hang attached:
$ ./bin/7za t -ttar /tmp/0409fc2b39432e7c82fc61f21e579c23a7c2c124736ccd918d53e45298945d63.tar
7-Zip (a) [64] 15.09 beta : Copyright (c) 1999-2015 Igor Pavlov : 2015-10-16
p7zip Version 15.09 beta (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,64 bits,12 CPUs x64)
Scanning the drive for archives:
1 file, 102437 bytes (101 KiB)
Testing archive: /tmp/0409fc2b39432e7c82fc61f21e579c23a7c2c124736ccd918d53e45298945d63.tar
ERRORS:
Headers Error
WARNINGS:
There are data after the end of archive
WARNING:
/tmp/0409fc2b39432e7c82fc61f21e579c23a7c2c124736ccd918d53e45298945d63.tar
The archive is open with offset
--
Path = /tmp/0409fc2b39432e7c82fc61f21e579c23a7c2c124736ccd918d53e45298945d63.tar
Warning: The archive is open with offset
Type = tar
ERRORS:
Headers Error
WARNINGS:
There are data after the end of archive
Offset = 53543
Physical Size = 41984
Tail Size = 6910
Headers Size = 1024
Code Page = UTF-8
0% T gnu/sparse
I don't see any BUG in that code.
It just looks like BIG sparse file.
So it decompress.
If you think that some line in code is incorrect, please write about that line.
You're right that I misdiagnosed the hang. The size of the sparse file (item.Size) is 3472896743739240448 bytes. Once that many bytes have been output parsing terminates.