Typography icon indicating copy to clipboard operation
Typography copied to clipboard

woff2 read header error did not specify the use of big-endian

Open emako opened this issue 11 months ago • 0 comments

See https://www.w3.org/TR/2024/REC-WOFF2-20240808/

3.1. Data types

Data Types
UInt8 8-bit unsigned integer.
Int16 16-bit signed integer in 2's complement format, stored big-endian.
UInt16 16-bit unsigned integer, stored big-endian.
UInt32 32-bit unsigned integer, stored big-endian.
255UInt16 Variable-length encoding of a 16-bit unsigned integer for optimized intermediate font data storage.
UIntBase128 Variable-length encoding of 32-bit unsigned integers.

But the method in Woff2Header ReadHeader(BinaryReader reader) did not specify the use of big-endian

The fixed code should be like it:


        Woff2Header ReadHeader(BinaryReader reader)
        {
            //WOFF2 Header
            //UInt32  signature             0x774F4632 'wOF2'
            //UInt32  flavor                The "sfnt version" of the input font.
            //UInt32  length                Total size of the WOFF file.
            //UInt16  numTables             Number of entries in directory of font tables.
            //UInt16  reserved              Reserved; set to 0.
            //UInt32  totalSfntSize         Total size needed for the uncompressed font data, including the sfnt header,
            //                              directory, and font tables(including padding).
            //UInt32  totalCompressedSize   Total length of the compressed data block.
            //UInt16  majorVersion          Major version of the WOFF file.
            //UInt16  minorVersion          Minor version of the WOFF file.
            //UInt32  metaOffset            Offset to metadata block, from beginning of WOFF file.
            //UInt32  metaLength            Length of compressed metadata block.
            //UInt32  metaOrigLength        Uncompressed size of metadata block.
            //UInt32  privOffset            Offset to private data block, from beginning of WOFF file.
            //UInt32  privLength            Length of private data block.

            Woff2Header header = new Woff2Header();
            byte b0 = reader.ReadByte();
            byte b1 = reader.ReadByte();
            byte b2 = reader.ReadByte();
            byte b3 = reader.ReadByte();
            if (!(b0 == 0x77 && b1 == 0x4f && b2 == 0x46 && b3 == 0x32))
            {
                return null;
            }

            header.flavor = reader.ReadUInt32BE(); // sfnt version
            string flavorName = Utils.TagToString(header.flavor);

            header.length = reader.ReadUInt32BE();
            header.numTables = reader.ReadUInt16BE();
            ushort reserved = reader.ReadUInt16BE();
            header.totalSfntSize = reader.ReadUInt32BE();
            header.totalCompressedSize = reader.ReadUInt32BE();

            header.majorVersion = reader.ReadUInt16BE();
            header.minorVersion = reader.ReadUInt16BE();

            header.metaOffset = reader.ReadUInt32BE();
            header.metaLength = reader.ReadUInt32BE();
            header.metaOriginalLength = reader.ReadUInt32BE();

            header.privOffset = reader.ReadUInt32BE();
            header.privLength = reader.ReadUInt32BE();

            return header;
        }


internal static class BinaryReaderExtensions
{
    public static ushort ReadUInt16BE(this BinaryReader reader)
    {
        byte[] bytes = reader.ReadBytes(2);
        return (ushort)((bytes[0] << 8) | bytes[1]);
    }

    public static uint ReadUInt32BE(this BinaryReader reader)
    {
        byte[] bytes = reader.ReadBytes(4);
        return (uint)((bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]);
    }
}

emako avatar Dec 30 '24 06:12 emako