Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DependencyObjectCollection.Indexer throws ArgumentOutOfRangeException #19253

Closed
Xiaoy312 opened this issue Jan 17, 2025 · 1 comment · Fixed by #19252
Closed

DependencyObjectCollection.Indexer throws ArgumentOutOfRangeException #19253

Xiaoy312 opened this issue Jan 17, 2025 · 1 comment · Fixed by #19252
Labels
difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification

Comments

@Xiaoy312
Copy link
Contributor

Xiaoy312 commented Jan 17, 2025

Current behavior

On Uno, new DependencyObjectCollection()[2] throws:

System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection. (Parameter 'index')

Expected behavior

On WinUI, new DependencyObjectCollection()[2] returns null.

How to reproduce it (as minimally and precisely as possible)

n/a

Workaround

n/a

Works on UWP/WinUI

Yes

Environment

Uno.WinUI / Uno.WinUI.WebAssembly / Uno.WinUI.Skia

NuGet package version(s)

No response

Affected platforms

Skia (GTK), Skia (Linux Framebuffer), Skia (macOS), Skia (Linux X11), Skia (WPF), Mac Catalyst, iOS, Android, WebAssembly

IDE

No response

IDE version

No response

Relevant plugins

No response

Anything else we need to know?

edit: the next part is from static analysis, it is not actually correct...
see comment below, for the actual callstack with native debugging

https://github.com/microsoft/microsoft-ui-xaml/blob/winui3/release/1.6.4/src/dxaml/xcp/components/DependencyObject/DependencyObjectCollection.cpp#L30-L33

CDependencyObject* const& CDOCollection::operator[](_In_ size_t index) const
{
    return m_items[index];
}

https://github.com/microsoft/microsoft-ui-xaml/blob/main/src/dxaml/xcp/components/Collection/Inc/docollection.h

class CDOCollection
    : public CCollection
{
public:
    typedef std::vector<CDependencyObject*> storage_type;

private:
    storage_type m_items;
}

https://en.cppreference.com/w/cpp/container/vector/operator_at

std::vector<T,Allocator>::operator[]
Returns a reference to the element at specified location pos. No bounds checking is performed.
Notes: [...] Accessing a nonexistent element through this operator is undefined behavior.

@Xiaoy312 Xiaoy312 added difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification labels Jan 17, 2025
@Xiaoy312
Copy link
Contributor Author

Xiaoy312 commented Jan 17, 2025

callstack:

Microsoft.ui.xaml.dll!CDOCollection::GetItemImpl(unsigned int nIndex) Line 1222 C++
Microsoft.ui.xaml.dll!CDOCollection::GetItemWithAddRef(unsigned int nIndex) Line 773 C++
[Inline Frame] Microsoft.ui.xaml.dll!CCollection::GetItem(CDependencyObject *) Line 295 C++
Microsoft.ui.xaml.dll!CoreImports::Collection_GetItem(CCollection * pCollection, unsigned int nIndex, CValue * pItem) Line 1329 C++
>Microsoft.ui.xaml.dll!DirectUI::ObservablePresentationFrameworkCollection<ABI::Microsoft::UI::Xaml::DependencyObject *>::GetAt(unsigned int index, ABI::Microsoft::UI::Xaml::IDependencyObject * * item) Line 1016  C++
[Managed to Native Transition]
Microsoft.WinUI.dll!WinRT.GenericTypeInstantiations.Windows_Foundation_Collections_IVector_1_Microsoft_UI_Xaml_DependencyObject.GetAt(WinRT.IObjectReference _obj, uint index) Line 25  C#
WinRT.Runtime.dll!ABI.System.Collections.Generic.IVectorMethods<Microsoft.UI.Xaml.DependencyObject>.GetAt(WinRT.IObjectReference obj, uint index) Line 58 C#
WinRT.Runtime.dll!ABI.System.Collections.Generic.IListMethods<Microsoft.UI.Xaml.DependencyObject>.GetAtHelper(WinRT.IObjectReference obj, uint index) Line 167 C#
WinRT.Runtime.dll!ABI.System.Collections.Generic.IListMethods<Microsoft.UI.Xaml.DependencyObject>.Indexer_Get(WinRT.IObjectReference obj, int index) Line 120 C#
Microsoft.WinUI.dll!Microsoft.UI.Xaml.DependencyObjectCollection.this[int].get(int index) Line 107 C#
UnoApp117.dll!UnoApp117.MainPage.MainPage() Line 12 C#

https://github.com/microsoft/microsoft-ui-xaml/blob/winui3/release/1.6.3/src/dxaml/xcp/components/Collection/DOCollection.cpp#L1220

_Check_return_ CDependencyObject* CDOCollection::GetItemImpl(_In_ XUINT32 nIndex)
{
    if (nIndex >= m_items.size() || m_fIsProcessingNeat)
    {
        return nullptr;
    }
    return m_items[nIndex];
}

so, returning nullptr is actually an expected behavior.

public static T IListMethods::Indexer_Get(IObjectReference obj, int index)
{
	if (index < 0)
	{
		throw new ArgumentOutOfRangeException("index");
	}
	return GetAtHelper(obj, (uint)index);
}

^ exception on negative index is also well defined behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
difficulty/tbd Categorizes an issue for which the difficulty level needs to be defined. kind/bug Something isn't working triage/untriaged Indicates an issue requires triaging or verification
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant