Archives.ArchiveFactory.Open returns a ZipArchive but ZipArchive.IsZipFile is false
#r "nuget: SharpCompress, 0.34.1"
open SharpCompress
let filePath = "./example.zip"
let isZipFile = Archives.Zip.ZipArchive.IsZipFile(filePath)
printfn $"isZipFile? %b{isZipFile}"
let archive = Archives.ArchiveFactory.Open(filePath)
printfn $"Archive type: %s{archive.GetType().FullName}"
printfn "Entries:"
for x in archive.Entries do
printfn "%s" x.Key
Output:
isZipFile? false
Archive type: SharpCompress.Archives.Zip.ZipArchive
Entries:
Foo/
Foo/Bar.txt
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at SharpCompress.Archives.Zip.ZipArchive.LoadEntries(IEnumerable`1 volumes)+MoveNext()
at SharpCompress.LazyReadOnlyCollection`1.LazyLoader.MoveNext()
at <StartupCode$FSI_0002>.$FSI_0002.main@() in /home/runner/Scratch.fsx:line 13
at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor)
at System.Reflection.MethodInvoker.Invoke(Object obj, IntPtr* args, BindingFlags invokeAttr)
Stopped due to error
This suggests a bug in ArchiveFactory.Open to me - it shouldn't return a ZipArchive for a file where ZipArchive.IsZipFile is false.
I cannot share the zip file, unfortunately.
@njlr do you have any way to share the .zip in question for reproducing this?
The fact it can extract any entries at all implies it has at least some zip headers in it, even if IsZipFile returns false. This seems too specific to the zip file to be able to debug without it. I'm afraid you'll need to step through the headers in the file manually in something like HxD. The Wikipedia Zip file format article is a good reference. You need to try to figure out where things go off track.
IsZipFile just checks if there is a valid header. This should probably change to use the magic bytes for the format. However, it can be a valid zip without the magic bytes