From 12c1127f060cd7dd129d4d1e395610f5402b8a92 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 3 Oct 2015 11:13:44 +0200 Subject: [PATCH] Check array bounds in expression indexer. --- .../Perspex.Markup/Binding/IndexerNode.cs | 27 ++++++++++++++++- .../ExpressionObserverTests_Indexer.cs | 30 +++++++++++++++++++ 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/src/Markup/Perspex.Markup/Binding/IndexerNode.cs b/src/Markup/Perspex.Markup/Binding/IndexerNode.cs index f29dcce741..5f1d840fbe 100644 --- a/src/Markup/Perspex.Markup/Binding/IndexerNode.cs +++ b/src/Markup/Perspex.Markup/Binding/IndexerNode.cs @@ -90,7 +90,12 @@ namespace Perspex.Markup.Binding if (typeInfo.IsArray && _intArgs != null) { - return ((Array)target).GetValue(_intArgs); + var array = (Array)target; + + if (InBounds(_intArgs, array)) + { + return array.GetValue(_intArgs); + } } else if (target is IList && _intArgs?.Length == 1) { @@ -102,5 +107,25 @@ namespace Perspex.Markup.Binding return PerspexProperty.UnsetValue; } + + private bool InBounds(int[] args, Array array) + { + if (args.Length == array.Rank) + { + for (var i = 0; i < args.Length; ++i) + { + if (args[i] >= array.GetLength(i)) + { + return false; + } + } + + return true; + } + else + { + return false; + } + } } } diff --git a/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests_Indexer.cs b/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests_Indexer.cs index 36bc2afbde..97d9bd1ccc 100644 --- a/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests_Indexer.cs +++ b/tests/Perspex.Markup.UnitTests/Binding/ExpressionObserverTests_Indexer.cs @@ -32,6 +32,36 @@ namespace Perspex.Markup.UnitTests.Binding Assert.Equal("qux", result); } + [Fact] + public async void Array_Out_Of_Bounds_Should_Return_UnsetValue() + { + var data = new { Foo = new[] { "foo", "bar" } }; + var target = new ExpressionObserver(data, "Foo[2]"); + var result = await target.Take(1); + + Assert.Equal(PerspexProperty.UnsetValue, result); + } + + [Fact] + public async void Array_With_Wrong_Dimensions_Should_Return_UnsetValue() + { + var data = new { Foo = new[] { "foo", "bar" } }; + var target = new ExpressionObserver(data, "Foo[1,2]"); + var result = await target.Take(1); + + Assert.Equal(PerspexProperty.UnsetValue, result); + } + + [Fact] + public async void List_Out_Of_Bounds_Should_Return_UnsetValue() + { + var data = new { Foo = new List { "foo", "bar" } }; + var target = new ExpressionObserver(data, "Foo[2]"); + var result = await target.Take(1); + + Assert.Equal(PerspexProperty.UnsetValue, result); + } + [Fact] public async void Should_Get_List_Value() {