[A11y] Initialize and copy _blockRange in UIA Clone (#10544)

## Summary of the Pull Request
#7960 was caused by `UiaTextRangeBase::_blockRange` not being initialized, thus pointing to random memory. In most cases, we initialize it properly in `RuntimeClassInitialize`, however, the copying version of `RuntimeClassInitialize` doesn't actually copy it over, resulting in it still containing random memory.

NVDA (and other screen readers) occasionally use `Clone` (really just the copy initializer), resulting in this bug occurring randomly.

## PR Checklist
* [X] Closes #7960 
* [X] Tests added/passed

## Validation Steps Performed
Test failed before the change, but passes after the change.
This commit is contained in:
Carlos Zamora 2021-07-06 13:54:51 -07:00 committed by GitHub
parent d3b9a780d3
commit 79a18f0825
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 1 deletions

View file

@ -1346,4 +1346,27 @@ class UiaTextRangeTests
VERIFY_SUCCEEDED(utr->ScrollIntoView(alignToTop));
}
}
TEST_METHOD(BlockRange)
{
// This test replicates GH#7960.
// It was caused by _blockRange being uninitialized, resulting in it occasionally being set to true.
// Additionally, all of the ctors _except_ the copy ctor initialized it. So this would be more apparent
// when calling Clone.
Microsoft::WRL::ComPtr<UiaTextRange> utr;
THROW_IF_FAILED(Microsoft::WRL::MakeAndInitialize<UiaTextRange>(&utr, _pUiaData, &_dummyProvider));
VERIFY_IS_FALSE(utr->_blockRange);
Microsoft::WRL::ComPtr<ITextRangeProvider> clone1;
THROW_IF_FAILED(utr->Clone(&clone1));
UiaTextRange* cloneUtr1 = static_cast<UiaTextRange*>(clone1.Get());
VERIFY_IS_FALSE(cloneUtr1->_blockRange);
cloneUtr1->_blockRange = true;
Microsoft::WRL::ComPtr<ITextRangeProvider> clone2;
cloneUtr1->Clone(&clone2);
UiaTextRange* cloneUtr2 = static_cast<UiaTextRange*>(clone2.Get());
VERIFY_IS_TRUE(cloneUtr2->_blockRange);
}
};

View file

@ -117,6 +117,7 @@ try
_end = a._end;
_pData = a._pData;
_wordDelimiters = a._wordDelimiters;
_blockRange = a._blockRange;
UiaTracing::TextRange::Constructor(*this);
return S_OK;

View file

@ -137,7 +137,7 @@ namespace Microsoft::Console::Types
// NOTE: _start is inclusive, but _end is exclusive
COORD _start{};
COORD _end{};
bool _blockRange;
bool _blockRange{};
// This is used by tracing to extract the text value
// that the UiaTextRange currently encompasses.