From 6e159f11fd8c005e1c17d1b0fb9d2617c1fa4680 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Thu, 5 Sep 2024 14:26:04 -0600 Subject: [PATCH 1/3] fixing 0 length issue with constructor --- .../System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs | 2 +- .../src/System/Numerics/Tensors/netcore/TensorSpan.cs | 2 +- .../src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs | 3 ++- .../System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs | 5 +++++ .../System.Numerics.Tensors/tests/TensorSpanTests.cs | 5 +++++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs index 8abba1dfeb998..aca81d20971bc 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs @@ -129,7 +129,7 @@ public ReadOnlyTensorSpan(ReadOnlySpan span, scoped ReadOnlySpan length strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths, linearLength) : strides; TensorSpanHelpers.ValidateStrides(strides, lengths); nint maxElements = TensorSpanHelpers.ComputeMaxLinearIndex(strides, lengths); - if (maxElements >= span.Length && span.Length != 0) + if ((maxElements >= span.Length && span.Length != 0) || (span.Length == 0 && maxElements > 0)) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); _shape = new TensorShape(span.Length, lengths, strides); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs index 16361d689dbcf..28739b4a7cf3e 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs @@ -132,7 +132,7 @@ public TensorSpan(Span span, scoped ReadOnlySpan lengths, scoped ReadOn TensorSpanHelpers.ValidateStrides(strides, lengths); nint maxElements = TensorSpanHelpers.ComputeMaxLinearIndex(strides, lengths); - if (maxElements >= span.Length && span.Length != 0) + if ((maxElements >= span.Length && span.Length != 0) || (span.Length == 0 && maxElements > 0)) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); _shape = new TensorShape(span.Length, lengths, strides); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs index d84b1130c96c3..080891e96a20f 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpanHelpers.cs @@ -193,7 +193,8 @@ public static nint ComputeLinearIndex(ReadOnlySpan indexes, ReadOnlySpan public static void ValidateStrides(ReadOnlySpan strides, ReadOnlySpan lengths) { - Debug.Assert(strides.Length == lengths.Length); + if (strides.Length != lengths.Length) + ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); if (strides.Length == 0) return; diff --git a/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs index e5e4a8c60bdc7..f55d7f1fa0c67 100644 --- a/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/ReadOnlyTensorSpanTests.cs @@ -224,6 +224,11 @@ public static void ReadOnlyTensorSpanSystemArrayConstructorTests() [Fact] public static void ReadOnlyTensorSpanArrayConstructorTests() { + // Make sure exception is thrown if lengths and strides would let you go past the end of the array + Assert.Throws(() => new TensorSpan(new double[0], lengths: new IntPtr[] { 2 }, strides: new IntPtr[] { 1 })); + Assert.Throws(() => new TensorSpan(new double[1], lengths: new IntPtr[] { 2 }, strides: new IntPtr[] { 1 })); + Assert.Throws(() => new TensorSpan(new double[2], lengths: new IntPtr[] { 2 }, strides: new IntPtr[] { 2 })); + // Make sure basic T[] constructor works int[] a = { 91, 92, -93, 94 }; scoped ReadOnlyTensorSpan spanInt = new ReadOnlyTensorSpan(a); diff --git a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs index f03f682f94f70..558355bfc2567 100644 --- a/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs +++ b/src/libraries/System.Numerics.Tensors/tests/TensorSpanTests.cs @@ -765,6 +765,11 @@ public static void TensorSpanSystemArrayConstructorTests() [Fact] public static void TensorSpanArrayConstructorTests() { + // Make sure exception is thrown if lengths and strides would let you go past the end of the array + Assert.Throws(() => new TensorSpan(new double[0], lengths: new IntPtr[] { 2 }, strides: new IntPtr[] { 1 })); + Assert.Throws(() => new TensorSpan(new double[1], lengths: new IntPtr[] { 2 }, strides: new IntPtr[] { 1 })); + Assert.Throws(() => new TensorSpan(new double[2], lengths: new IntPtr[] { 2 }, strides: new IntPtr[] { 2 })); + // Make sure basic T[] constructor works int[] a = { 91, 92, -93, 94 }; scoped TensorSpan spanInt = new TensorSpan(a); From 04684290c66287a645d05a957fb347d71cbd84b5 Mon Sep 17 00:00:00 2001 From: Michael Sharp <51342856+michaelgsharp@users.noreply.github.com> Date: Mon, 9 Sep 2024 13:18:54 -0600 Subject: [PATCH 2/3] Update src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs Co-authored-by: Stephen Toub --- .../src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs index aca81d20971bc..0df6376accfdc 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs @@ -129,7 +129,7 @@ public ReadOnlyTensorSpan(ReadOnlySpan span, scoped ReadOnlySpan length strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths, linearLength) : strides; TensorSpanHelpers.ValidateStrides(strides, lengths); nint maxElements = TensorSpanHelpers.ComputeMaxLinearIndex(strides, lengths); - if ((maxElements >= span.Length && span.Length != 0) || (span.Length == 0 && maxElements > 0)) + if (span.IsEmpty ? maxElements > 0 : maxElements >= span.Length) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); _shape = new TensorShape(span.Length, lengths, strides); From 0cf1787aed685600aca2ae7873367e3d27b74df3 Mon Sep 17 00:00:00 2001 From: Michael Sharp Date: Mon, 16 Sep 2024 10:44:43 -0600 Subject: [PATCH 3/3] comments from PR --- .../src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs | 2 +- .../src/System/Numerics/Tensors/netcore/TensorSpan.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs index 0df6376accfdc..d1a7be1c928c6 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/ReadOnlyTensorSpan.cs @@ -129,7 +129,7 @@ public ReadOnlyTensorSpan(ReadOnlySpan span, scoped ReadOnlySpan length strides = strides.IsEmpty ? (ReadOnlySpan)TensorSpanHelpers.CalculateStrides(lengths, linearLength) : strides; TensorSpanHelpers.ValidateStrides(strides, lengths); nint maxElements = TensorSpanHelpers.ComputeMaxLinearIndex(strides, lengths); - if (span.IsEmpty ? maxElements > 0 : maxElements >= span.Length) + if (span.IsEmpty ? maxElements != 0 : maxElements >= span.Length) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); _shape = new TensorShape(span.Length, lengths, strides); diff --git a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs index 28739b4a7cf3e..dfb1ae16b87ae 100644 --- a/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs +++ b/src/libraries/System.Numerics.Tensors/src/System/Numerics/Tensors/netcore/TensorSpan.cs @@ -132,7 +132,7 @@ public TensorSpan(Span span, scoped ReadOnlySpan lengths, scoped ReadOn TensorSpanHelpers.ValidateStrides(strides, lengths); nint maxElements = TensorSpanHelpers.ComputeMaxLinearIndex(strides, lengths); - if ((maxElements >= span.Length && span.Length != 0) || (span.Length == 0 && maxElements > 0)) + if (span.IsEmpty ? maxElements != 0 : maxElements >= span.Length) ThrowHelper.ThrowArgument_InvalidStridesAndLengths(); _shape = new TensorShape(span.Length, lengths, strides);