Skip to content

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

@emako

Description

@emako

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]);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions