void ValidateTrailer()

in Agents/Xamarin.Interactive/Collections/PropertyList.cs [340:403]


        void ValidateTrailer ()
        {
            // Don't overflow on number of objects or offset of the table
            if (trailer.NumObjects >= Int64.MaxValue)
                Fatal ("trailer.NumObjects >= Int64.MaxValue");
            else if (trailer.OffsetTableOffset >= Int64.MaxValue)
                Fatal ("trailer.OffsetTableOffset >= Int64.MaxValue)");

            // Must be a minimum of one object
            if (trailer.NumObjects < 1)
                Fatal ("trailer.NumObjects < 1");

            // Ensure the top object is in range
            if (trailer.NumObjects <= trailer.TopObject)
                Fatal ("trailer.NumObjects <= trailer.TopObject");

            // The offset table must be at least 9 bytes into the file
            // ('bplist??' + 1 byte of object table data)
            if (trailer.OffsetTableOffset < 9)
                Fatal ("trailer.OffsetTableOffset < 9");

            // The trailer must point to a value before itself in the file
            if ((uint)(stream.Length - TRAILER_SIZE) <= trailer.OffsetTableOffset)
                Fatal ("stream.Length - TRAILER_SIZE <= trailer.OffsetTableOffset");

            // Minimum of 1 byte for the size of integers and refs in the file
            if (trailer.OffsetIntSize < 1)
                Fatal ("trailer.OffsetIntSize < 1");
            else if (trailer.ObjectRefSize < 1)
                Fatal ("trailer.ObjectRefSize < 1");

            // Total size of offset table must not overflow
            var offsetTableSize = checked (trailer.NumObjects * trailer.OffsetIntSize);

            // Offset table must have at least one entry
            if (offsetTableSize < 1)
                Fatal ("trailer offsetTableSize < 1");

            // Ensure the size of the offset table and data sections do not overflow
            var objectDataSize = trailer.OffsetTableOffset - 8;
            var tmp = checked (objectDataSize + 8);
            tmp = checked (tmp + offsetTableSize);
            tmp = checked (tmp + TRAILER_SIZE);

            // The total size of the file should be equal to offsetTableOffset + TRAILER_SIZE
            if ((ulong)stream.Length != tmp)
                Fatal ("stream.Length != trailer.OffsetTableOffset + TRAILER_SIZE");

            // The object refs must be the right size to point into the offset table.
            // That is, if the count of objects is 260, but only 1 byte is used to
            // store references (max value 255), something is wrong.
            if (trailer.ObjectRefSize < 8 && (1UL << (8 * trailer.ObjectRefSize)) <= trailer.NumObjects)
                Fatal ("trailer.ObjectRefSize invalid");

            // The integers used for pointers in the offset table must be able to
            // reach as far as the start of the offset table.
            if (trailer.OffsetIntSize < 8 && (1UL << (8 * trailer.OffsetIntSize)) <= trailer.OffsetTableOffset)
                Fatal ("trailer.OffsetIntSize invalid");

            Seek (trailer.OffsetTableOffset + trailer.TopObject * trailer.OffsetIntSize);
            var ofs = ReadSizedInt (trailer.OffsetIntSize);
            if (ofs < 8 || trailer.OffsetTableOffset <= ofs)
                Fatal ("offset ({0}) < 8 || trailer.OffsetTableOffset <= offset ({0})", ofs);
        }