Example #1
0
        public MetadataBuilder(
            int userStringHeapStartOffset = 0,
            int stringHeapStartOffset     = 0,
            int blobHeapStartOffset       = 0,
            int guidHeapStartOffset       = 0)
        {
            // -1 for the 0 we always write at the beginning of the heap:
            if (userStringHeapStartOffset >= UserStringHeapSizeLimit - 1)
            {
                throw ImageFormatLimitationException.HeapSizeLimitExceeded(HeapIndex.UserString);
            }

            // Add zero-th entry to all heaps, even in EnC delta.
            // We don't want generation-relative handles to ever be IsNil.
            // In both full and delta metadata all nil heap handles should have zero value.
            // There should be no blob handle that references the 0 byte added at the
            // beginning of the delta blob.
            _userStringBuilder.WriteByte(0);

            _blobs.Add(ImmutableArray <byte> .Empty, default(BlobHandle));
            _blobHeapSize = 1;

            // When EnC delta is applied #US, #String and #Blob heaps are appended.
            // Thus indices of strings and blobs added to this generation are offset
            // by the sum of respective heap sizes of all previous generations.
            _userStringHeapStartOffset = userStringHeapStartOffset;
            _stringHeapStartOffset     = stringHeapStartOffset;
            _blobHeapStartOffset       = blobHeapStartOffset;

            // Unlike other heaps, #Guid heap in EnC delta is zero-padded.
            _guidBuilder.WriteBytes(0, guidHeapStartOffset);
        }
        private int GetNewUserStringHeapOffset(int stringLength)
        {
            int startPosition = _userStringWriter.Position;
            int offset        = startPosition + _userStringHeapStartOffset;

            // Native metadata emitter allows strings to exceed the heap size limit as long
            // as the index is within the limits (see https://github.com/dotnet/roslyn/issues/9852)
            if (offset > UserStringHeapSizeLimit)
            {
                ImageFormatLimitationException.ThrowHeapSizeLimitExceeded(HeapIndex.UserString);
            }

            return(offset);
        }
Example #3
0
        /// <exception cref="ImageFormatLimitationException">The remaining space on the heap is too small to fit the string.</exception>
        public UserStringHandle GetOrAddUserString(string str)
        {
            int index;

            if (!_userStrings.TryGetValue(str, out index))
            {
                Debug.Assert(!_streamsAreComplete);

                int startPosition = _userStringBuilder.Count;
                int encodedLength = str.Length * 2 + 1;
                index = startPosition + _userStringHeapStartOffset;

                // Native metadata emitter allows strings to exceed the heap size limit as long
                // as the index is within the limits (see https://github.com/dotnet/roslyn/issues/9852)
                if (index >= UserStringHeapSizeLimit)
                {
                    throw ImageFormatLimitationException.HeapSizeLimitExceeded(HeapIndex.UserString);
                }

                _userStrings.Add(str, index);
                _userStringBuilder.WriteCompressedInteger(encodedLength);
                _userStringBuilder.WriteUTF16(str);

                // Write out a trailing byte indicating if the string is really quite simple
                byte stringKind = 0;
                foreach (char ch in str)
                {
                    if (ch >= 0x7F)
                    {
                        stringKind = 1;
                    }
                    else
                    {
                        switch ((int)ch)
                        {
                        case 0x1:
                        case 0x2:
                        case 0x3:
                        case 0x4:
                        case 0x5:
                        case 0x6:
                        case 0x7:
                        case 0x8:
                        case 0xE:
                        case 0xF:
                        case 0x10:
                        case 0x11:
                        case 0x12:
                        case 0x13:
                        case 0x14:
                        case 0x15:
                        case 0x16:
                        case 0x17:
                        case 0x18:
                        case 0x19:
                        case 0x1A:
                        case 0x1B:
                        case 0x1C:
                        case 0x1D:
                        case 0x1E:
                        case 0x1F:
                        case 0x27:
                        case 0x2D:
                            stringKind = 1;
                            break;

                        default:
                            continue;
                        }
                    }

                    break;
                }

                _userStringBuilder.WriteByte(stringKind);
            }

            return(MetadataTokens.UserStringHandle(index));
        }