From 67994630d3e3d56895a9737a9996baf5ea84b609 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 16 Jan 2026 23:55:50 +0000 Subject: [PATCH 1/6] Initial plan From d87b1efa969a0a6b99e9802dc97853be24f46698 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 00:21:33 +0000 Subject: [PATCH 2/6] Fix ArgumentOutOfRangeException when Concat called after Skip that skips more elements than exist Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs | 5 +++++ src/libraries/System.Linq/tests/ConcatTests.cs | 11 +++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs index 944e0fa4cda70e..fa7e11d9714446 100644 --- a/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs +++ b/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs @@ -146,6 +146,11 @@ public void CopyTo(TSource[] array, int arrayIndex) => private static void Fill(IList source, Span destination, int sourceIndex) { + if (destination.Length == 0) + { + return; + } + if (source.TryGetSpan(out ReadOnlySpan sourceSpan)) { sourceSpan.Slice(sourceIndex, destination.Length).CopyTo(destination); diff --git a/src/libraries/System.Linq/tests/ConcatTests.cs b/src/libraries/System.Linq/tests/ConcatTests.cs index a32dbe217ac496..92a8118f46dcfe 100644 --- a/src/libraries/System.Linq/tests/ConcatTests.cs +++ b/src/libraries/System.Linq/tests/ConcatTests.cs @@ -571,5 +571,16 @@ public static IEnumerable GetToArrayDataSources() } ]; } + + [Fact] + public void ConcatAfterSkipMoreThanCount() + { + int[] source = [1]; + int[] items = [2, 3]; + + int[] result = source.Skip(2).Concat(items).ToArray(); + + Assert.Equal(items, result); + } } } From 290913b042b4861f66649118d597202074575c8d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 16:38:58 +0000 Subject: [PATCH 3/6] Move bounds check inside span path and check sourceIndex against sourceSpan.Length Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs b/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs index fa7e11d9714446..22f320d04e57bb 100644 --- a/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs +++ b/src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs @@ -146,14 +146,13 @@ public void CopyTo(TSource[] array, int arrayIndex) => private static void Fill(IList source, Span destination, int sourceIndex) { - if (destination.Length == 0) - { - return; - } - if (source.TryGetSpan(out ReadOnlySpan sourceSpan)) { - sourceSpan.Slice(sourceIndex, destination.Length).CopyTo(destination); + if (sourceIndex < sourceSpan.Length) + { + sourceSpan.Slice(sourceIndex, destination.Length).CopyTo(destination); + } + return; } From 8157525f4f585b4c07e379e77083f2b04faef6bc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 16:53:51 +0000 Subject: [PATCH 4/6] Move regression test to SkipTests.cs with multiple source types and operators Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- src/libraries/System.Linq/tests/ConcatTests.cs | 11 ----------- src/libraries/System.Linq/tests/SkipTests.cs | 16 ++++++++++++++++ 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/libraries/System.Linq/tests/ConcatTests.cs b/src/libraries/System.Linq/tests/ConcatTests.cs index 92a8118f46dcfe..a32dbe217ac496 100644 --- a/src/libraries/System.Linq/tests/ConcatTests.cs +++ b/src/libraries/System.Linq/tests/ConcatTests.cs @@ -571,16 +571,5 @@ public static IEnumerable GetToArrayDataSources() } ]; } - - [Fact] - public void ConcatAfterSkipMoreThanCount() - { - int[] source = [1]; - int[] items = [2, 3]; - - int[] result = source.Skip(2).Concat(items).ToArray(); - - Assert.Equal(items, result); - } } } diff --git a/src/libraries/System.Linq/tests/SkipTests.cs b/src/libraries/System.Linq/tests/SkipTests.cs index c05dc7c29f04b3..c360f3717bda78 100644 --- a/src/libraries/System.Linq/tests/SkipTests.cs +++ b/src/libraries/System.Linq/tests/SkipTests.cs @@ -388,5 +388,21 @@ public void DisposeSource(int sourceCount, int count) Assert.False(iterator.MoveNext()); Assert.Equal(-1, state); } + + [Fact] + public void SkipMoreThanCountFollowedByOperators() + { + int[] items = [2, 3]; + + foreach (IEnumerable source in CreateSources([1])) + { + Assert.Equal(items, source.Skip(2).Concat(items).ToArray()); + Assert.Equal(items, source.Skip(2).Concat(items).ToList()); + Assert.Equal(items, source.Skip(2).Append(2).Append(3).ToArray()); + Assert.Equal(items, source.Skip(2).Append(2).Append(3).ToList()); + Assert.Equal(items, items.Concat(source.Skip(2)).ToArray()); + Assert.Equal(items, items.Concat(source.Skip(2)).ToList()); + } + } } } From a9071616c010001c2db698bca440ed0d28448942 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 17 Jan 2026 21:51:07 +0000 Subject: [PATCH 5/6] Add tests for Skip followed by Select, Where, Take, Distinct, OrderBy operators Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- src/libraries/System.Linq/tests/SkipTests.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/libraries/System.Linq/tests/SkipTests.cs b/src/libraries/System.Linq/tests/SkipTests.cs index c360f3717bda78..ffdbd110bc4ac4 100644 --- a/src/libraries/System.Linq/tests/SkipTests.cs +++ b/src/libraries/System.Linq/tests/SkipTests.cs @@ -402,6 +402,18 @@ public void SkipMoreThanCountFollowedByOperators() Assert.Equal(items, source.Skip(2).Append(2).Append(3).ToList()); Assert.Equal(items, items.Concat(source.Skip(2)).ToArray()); Assert.Equal(items, items.Concat(source.Skip(2)).ToList()); + Assert.Empty(source.Skip(2).Select(x => x * 2).ToArray()); + Assert.Empty(source.Skip(2).Select(x => x * 2).ToList()); + Assert.Empty(source.Skip(2).Where(x => x > 0).ToArray()); + Assert.Empty(source.Skip(2).Where(x => x > 0).ToList()); + Assert.Empty(source.Skip(2).Take(10).ToArray()); + Assert.Empty(source.Skip(2).Take(10).ToList()); + Assert.Empty(source.Skip(2).Skip(1).ToArray()); + Assert.Empty(source.Skip(2).Skip(1).ToList()); + Assert.Empty(source.Skip(2).Distinct().ToArray()); + Assert.Empty(source.Skip(2).Distinct().ToList()); + Assert.Empty(source.Skip(2).OrderBy(x => x).ToArray()); + Assert.Empty(source.Skip(2).OrderBy(x => x).ToList()); } } } From 5d85ed87155775a9eba15c2a3ff1c56f2d9baa97 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 19 Jan 2026 16:04:23 +0000 Subject: [PATCH 6/6] Add Contains tests for Skip that skips more elements than exist Co-authored-by: eiriktsarpalis <2813363+eiriktsarpalis@users.noreply.github.com> --- src/libraries/System.Linq/tests/SkipTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libraries/System.Linq/tests/SkipTests.cs b/src/libraries/System.Linq/tests/SkipTests.cs index ffdbd110bc4ac4..bb6128403ff265 100644 --- a/src/libraries/System.Linq/tests/SkipTests.cs +++ b/src/libraries/System.Linq/tests/SkipTests.cs @@ -414,6 +414,8 @@ public void SkipMoreThanCountFollowedByOperators() Assert.Empty(source.Skip(2).Distinct().ToList()); Assert.Empty(source.Skip(2).OrderBy(x => x).ToArray()); Assert.Empty(source.Skip(2).OrderBy(x => x).ToList()); + Assert.False(source.Skip(2).Contains(1)); + Assert.False(source.Skip(2).Contains(2)); } } }