Skip to content

Extra IDs larger than short.MaxValue not supported in ZipExtraData #657

Closed
@rougemeilland

Description

@rougemeilland

Steps to reproduce

  1. Define a class of extra field with tag ID 0xe57aby implementing TaggedData.
  2. Pass the implemented class instance to the ZipExtraData.AddEntry method.

Please refer to the source code of the program to reproduce this problem.

Expected behavior

The extra field is successfully added to the ZipExtraData object. Then I can refer to the extra field using something like the ZipExtraData.GetData method.

Actual behavior

In the ZipExtraData.AddEntry method, a System.ArgumentOutOfRangeException exception occurs.

Version of SharpZipLib

SharpZipLib 1.3.2

Obtained from (only keep the relevant lines)

  • Package installed using NuGet

Supplementary information

Some explanation is needed as to why this problem occurred.

What I originally wanted to do was parse an unfamiliar extra field with a tag ID of 0xe57a. I found the tag in the ZIP file I have.

The specification of the tag is unclear, but according to "https://gnqg.hatenablog.com/entry/2016/09/11/155033", it seems to explicitly specify the code page of the entry name. It seems to have been used in an application called "ALZip" in the past.

Anyway, I wrote the code to try to get 0xe57a extra field from that ZIP file. However, even though ZipEntry.ExtraData contains that extra field, for some reason the ZipExtraData.GetData method returns null.

I thought it was weird and tried to write a sample program to fix the problem, but in fact I got an exception in ZipExtraData.AddEntry which was executed before the ZipExtraData.GetData method.

I read the source code of SharpZipLib/src/ICSharpCode.SharpZipLib/Zip/ZipExtraData.cs.
As a result, it seemed that ZipExtraData.AddEntry would raise an exception if ITaggedData.TagID returned a value greater than or equal to 0x8000.
Also, the reason why the ZipExtraData.GetData method returned null is that the value of ITaggedData.TagID was expanded to int and treated as a negative value (0xffffe57a), and the ReadShortInternal method I think that the cause is that when reading the tag ID from the byte array, the operation is performed as an unsigned integer and the value (0x0000e57a) is returned as an int type.

And the next thing to think about is, "Is a 16-bit integer greater than or equal to 0x8000 valid as a tag ID?"
I think that "a 16-bit integer of 0x8000 or more is also valid as a tag ID" for the following reasons.

  • The list of well-known extra fields (proginfo/extrald.txt) contains 0xfb4a (SMS / QDOS).
  • Although it is specified that the tag ID is a 16-bit integer, there is no specification indicating whether it should be in the range of 0x0000 to 0x7fff or whether it should be treated as a signed integer. (Maybe I just don't know y well ...)

Source code of sample program

using ICSharpCode.SharpZipLib.Zip;
using System;
using System.Text;

namespace Experiment
{
    class Program
    {
        private class SampleExtraField
            : ITaggedData
        {
            public short TagID
            {
                get
                {
                    // Attempting to cast 0xe57a to short results in a compilation error "Compiler Error CS0221", so we are using the unchecked syntax here.
                    unchecked
                    {
                        return (short)0xe57a;
                    }
                }
            }

            public byte[] GetData()
            {
                return BitConverter.GetBytes(CodePage);
            }

            public void SetData(byte[] data, int offset, int count)
            {
                CodePage = BitConverter.ToInt32(data, offset);
            }

            public Int32 CodePage { get; set; }
        }

        static void Main(string[] args)
        {
            using (var extraData = new ZipExtraData(new byte[0]))
            {
                var now = DateTime.UtcNow;
                extraData.AddEntry(new NTTaggedData
                {
                    LastModificationTime = now,
                    LastAccessTime = now,
                    CreateTime = now,
                });

                if (extraData.GetData<NTTaggedData>() != null)
                    Console.WriteLine("OK (tag id = 0x000a)");
                else
                    Console.WriteLine("NG (tag id = 0x000a)");


                extraData.AddEntry(new SampleExtraField // <= I got an exception here
                {
                    CodePage = Encoding.Default.CodePage
                });
                if (extraData.GetData<SampleExtraField>() != null)
                    Console.WriteLine("OK (tag id = 0xe57a)");
                else
                    Console.WriteLine("NG (tag id = 0xe57a)");

            }
            Console.ReadLine();
        }
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzipRelated to ZIP file format

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions