Repository: microsoft/terminal
File: src/types/UiaTextRangeBase.cpp (C++)

Code before:
{
    std::wstring textData{};
    if (!IsDegenerate())
    {
        const auto& buffer = _pData->GetTextBuffer();
        const auto bufferSize = buffer.GetSize();

        // TODO GH#5406: create a different UIA parent object for each TextBuffer
        // nvaccess/nvda#11428: Ensure our endpoints are in bounds
        // otherwise, we'll FailFast catastrophically
        THROW_HR_IF(E_FAIL, !bufferSize.IsInBounds(_start) || !bufferSize.IsInBounds(_end));

        // convert _end to be inclusive
        auto inclusiveEnd = _end;
        bufferSize.DecrementInBounds(inclusiveEnd, true);

        const auto textRects = buffer.GetTextRects(_start, inclusiveEnd, _blockRange, true);
        const auto bufferData = buffer.GetText(true,
                                               false,
                                               textRects);

        const size_t textDataSize = bufferData.text.size() * bufferSize.Width();
        textData.reserve(textDataSize);
        for (const auto& text : bufferData.text)
        {
            if (textData.size() >= maxLength)
            {
                // early exit; we're already at/past max length
                break;
            }
            textData += text;
        }
    }

    // - size_t(-1) gets converted to 0xffff...
    // - if the maxLength is more than what we have,
    //     they probably just want the whole thing (so don't resize)
    if (const auto s = gsl::narrow_cast<size_t>(maxLength); s < textData.size())
    {
        textData.resize(s);
    }

    return textData;
}
#pragma warning(pop)

IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit,
                                      _In_ int count,
                                      _Out_ int* pRetVal) noexcept
try
{

Review comment (suggestion):
This is an unguarded comparison of a `size_t` against a signed value. You note it below, but I don't see how this compiles under Audit or for x86.

I would VERY much rather not rely on the narrowing behavior of a signed into an unsigned. Make it explicit.

Code after:
{
    std::wstring textData{};
    if (!IsDegenerate())
    {
        const auto& buffer = _pData->GetTextBuffer();
        const auto bufferSize = buffer.GetSize();

        // -1 is supposed to be interpreted as "no limit",
        // so leverage size_t(-1) being converted to 0xffff...
        const auto maxLengthAsSize = gsl::narrow_cast<size_t>(maxLength);

        // TODO GH#5406: create a different UIA parent object for each TextBuffer
        // nvaccess/nvda#11428: Ensure our endpoints are in bounds
        THROW_HR_IF(E_FAIL, !bufferSize.IsInBounds(_start) || !bufferSize.IsInBounds(_end));

        // convert _end to be inclusive
        auto inclusiveEnd = _end;
        bufferSize.DecrementInBounds(inclusiveEnd, true);

        // reserve size in accordance to extracted text
        const auto textRects = buffer.GetTextRects(_start, inclusiveEnd, _blockRange, true);
        const auto bufferData = buffer.GetText(true,
                                               false,
                                               textRects);
        const size_t textDataSize = bufferData.text.size() * bufferSize.Width();
        textData.reserve(textDataSize);
        for (const auto& text : bufferData.text)
        {
            if (textData.size() >= maxLengthAsSize)
            {
                // early exit; we're already at/past max length
                break;
            }
            textData += text;
        }

        // only use maxLength to resize down.
        // if maxLength > size, we don't want to resize and append unnecessary L'\0'.
        if (textData.size() > maxLengthAsSize)
        {
            textData.resize(maxLengthAsSize);
        }
    }

    return textData;
}
#pragma warning(pop)

IFACEMETHODIMP UiaTextRangeBase::Move(_In_ TextUnit unit,
                                      _In_ int count,
                                      _Out_ int* pRetVal) noexcept