Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exception "Unable to open archive" received when opening valid 7z archives #54

Closed
jhaerig opened this issue Sep 24, 2021 · 7 comments
Closed

Comments

@jhaerig
Copy link

jhaerig commented Sep 24, 2021

Hello,

I recently found this project and tried to implement it in a download/extractor tool for 7z files.
The implementation worked flawless as there is almost nothing that could go wrong.

Then I ran into a problem that some 7z files I tried to unpack failed with "Unable to open archive". Other archives show no problem. I checked these bad archives with the original 7z Manager and no error was found.
What I tried so far:

  • Analyzed the bad archives with older and latest version of 7z Manager --> No issue found
  • Exchange the 7z.dll with the latest or way older versions --> No effect
  • Analyzed the header and end header of the bad archives in a hex editor, according to the info from this page: https://www.7-zip.org/recover.html--> Archive seems to be valid as the length matches.

These are the infos about one of the bad archives:
Size: 16 988 619 434
Packed Size: 10 451 321 462
Folders: 41
Files: 834
CRC: 18147D68
Type: 7z
Physical Size: 10 451 328 505
Headers Size: 7 043
Method: LZMA2:24
Solid: +
Blocks: 9

Header
000000000 37 7A BC AF 27 1C 00 04 44 B9 FA 12 B2 9D F2 6E
000000010 02 00 00 00 27 00 00 00 00 00 00 00 85 30 51 92

End Header
26EF29DD0 00 00 17 06 F2 76 82 F2 6E 01 09 9B 3C 00 07 0B
26EF29DE0 01 00 01 23 03 01 01 05 5D 00 80 01 00 0C C1 4E
26EF29DF0 58 0A 01 52 87 74 D0 00 00

My last action was to pull the code and used the "Example"-Project to open the bad archive and see where it exactly fails.
All I see is, that this function call in "ArchiveFile.cs:155" returns 0x00000001
int open = this.archive.Open(this.archiveStream, ref checkPos, null);
this.archiveStream.Position is 0x0000000000000020

I'm not generating the archives on my own, therefore I can't tell what could causes the archives to get in this state.
Any help appreciated.

@adoconnection
Copy link
Owner

Can you upload archive itself so I can use it in unit test please.

@jhaerig
Copy link
Author

jhaerig commented Sep 27, 2021

I found a easy way to generate an 7z archive to cause this issue.
Basically it's necessary to generate a 7z archive with a 5GByte large uncompressable binary blob file inside and then try to extract it.

The easiest way for me to generate a uncompressable binary file with specific size was to use VeraCrypt.
https://www.veracrypt.fr/en/Downloads.html

  1. Generate VeraCrypt file with 5GB
  2. Put that file in an 7z archive (Compression: Fastest, Method: LZMA2, Dict size: 64k, Word size: 32, Block size: 16MB)
  3. Try to extract archive with Example project --> "Error: Unable to open archive"

@adoconnection
Copy link
Owner

This is still open problem, it is reproducible but I have no idea how to proceed.

@Pyroluk
Copy link

Pyroluk commented Mar 31, 2022

I am facing the same problem. Large archives are failing on the above-mentioned method. I tested the same archive with https://github.com/squid-box/SevenZipSharp and it worked flawlessly. Maybe their implementation of the open call can hint in the correct direction to solve the problem? Seems like they are using the callback of the function instead of passing in null? Maybe the squid-box dev could give us a hint? 😊

Edit:
This seems to be the open callback. Is it only used for passwords and UI stuff? What do you think? Documentation missing...
https://android.googlesource.com/platform/external/lzma/+/baa3858/CPP/7zip/UI/Common/ArchiveOpenCallback.cpp

@Pyroluk
Copy link

Pyroluk commented Apr 5, 2022

Hi! I found the reason and solution.

SevenZipExtractor\SevenZipInterface.cs:415

StreamWrapper.Seek():

public virtual void Seek(long offset, uint seekOrigin, IntPtr newPosition)
{
    long Position = (uint) this.BaseStream.Seek(offset, (SeekOrigin) seekOrigin);
    if (newPosition != IntPtr.Zero)
    {
        Marshal.WriteInt64(newPosition, Position);
    }
}

The cast to (uint) cripples everything larger than 2^32 aka 4GB. Remove the cast and everything works a treat!

andr_gin found and solved this bug 3 years ago in his comment on the original "C# (.NET) Interface for 7-Zip Archive DLLs" project on codeproject, which is the bases of this project.

Cheers!

@adoconnection
Copy link
Owner

what a stupid line of code 🙈
@Pyroluk thanks!

@adoconnection
Copy link
Owner

1.0.17 published!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants