From a35662c8e07ffc1542c74d90bed2bf612c1ae97b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 18 Aug 2025 23:48:46 +0000 Subject: [PATCH 1/5] Initial plan From 767fe8e7ec3cb79fc48eff72f1f6058895c2fc7e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 Aug 2025 00:01:43 +0000 Subject: [PATCH 2/5] Fix TimeSpan overflow in SetCookieHeaderValue.TryParse for Max-Age Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> --- src/Http/Headers/src/SetCookieHeaderValue.cs | 10 +++++++ .../Headers/test/SetCookieHeaderValueTest.cs | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/src/Http/Headers/src/SetCookieHeaderValue.cs b/src/Http/Headers/src/SetCookieHeaderValue.cs index 359e6014dae2..55cccf068b5f 100644 --- a/src/Http/Headers/src/SetCookieHeaderValue.cs +++ b/src/Http/Headers/src/SetCookieHeaderValue.cs @@ -587,6 +587,16 @@ private static int GetSetCookieLength(StringSegment input, int startIndex, out S maxAge = -maxAge; } + // Check if maxAge would cause TimeSpan.FromSeconds to overflow + // TimeSpan.MaxValue.TotalSeconds is approximately 922337203685.4775 + const long MaxTimeSpanSeconds = 922337203685L; + const long MinTimeSpanSeconds = -922337203685L; + if (maxAge > MaxTimeSpanSeconds || maxAge < MinTimeSpanSeconds) + { + // MaxAge value would overflow TimeSpan, abort + return 0; + } + result.MaxAge = TimeSpan.FromSeconds(maxAge); offset += itemLength; } diff --git a/src/Http/Headers/test/SetCookieHeaderValueTest.cs b/src/Http/Headers/test/SetCookieHeaderValueTest.cs index eff008809559..0d14851896b5 100644 --- a/src/Http/Headers/test/SetCookieHeaderValueTest.cs +++ b/src/Http/Headers/test/SetCookieHeaderValueTest.cs @@ -486,4 +486,30 @@ public void SetCookieHeaderValue_TryParseStrictList_FailsForAnyInvalidValues( Assert.Null(results); Assert.False(result); } + + [Theory] + [InlineData("name=value; max-age=922337203686")] // One more than TimeSpan.MaxValue.TotalSeconds + [InlineData("name=value; max-age=999999999999999999999")] // Much larger value + [InlineData("name=value; max-age=-922337203686")] // Negative overflow + public void SetCookieHeaderValue_TryParse_MaxAgeOverflow_ReturnsFalse(string value) + { + // Should return false instead of throwing ArgumentOutOfRangeException + bool result = SetCookieHeaderValue.TryParse(value, out var parsedValue); + Assert.False(result); + Assert.Null(parsedValue); + } + + [Theory] + [InlineData("name=value; max-age=922337203685")] // Max valid value + [InlineData("name=value; max-age=-922337203685")] // Min valid value + [InlineData("name=value; max-age=0")] // Zero + [InlineData("name=value; max-age=86400")] // One day in seconds + public void SetCookieHeaderValue_TryParse_MaxAgeValid_ReturnsTrue(string value) + { + // Should successfully parse valid max-age values + bool result = SetCookieHeaderValue.TryParse(value, out var parsedValue); + Assert.True(result); + Assert.NotNull(parsedValue); + Assert.NotNull(parsedValue!.MaxAge); + } } From f10d3645f3b153a1475061553b5ceb865f73135a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 Aug 2025 00:22:34 +0000 Subject: [PATCH 3/5] Simplify overflow handling using exception handling instead of manual validation Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> --- src/Http/Headers/src/SetCookieHeaderValue.cs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/Http/Headers/src/SetCookieHeaderValue.cs b/src/Http/Headers/src/SetCookieHeaderValue.cs index 55cccf068b5f..72bc59957029 100644 --- a/src/Http/Headers/src/SetCookieHeaderValue.cs +++ b/src/Http/Headers/src/SetCookieHeaderValue.cs @@ -587,17 +587,15 @@ private static int GetSetCookieLength(StringSegment input, int startIndex, out S maxAge = -maxAge; } - // Check if maxAge would cause TimeSpan.FromSeconds to overflow - // TimeSpan.MaxValue.TotalSeconds is approximately 922337203685.4775 - const long MaxTimeSpanSeconds = 922337203685L; - const long MinTimeSpanSeconds = -922337203685L; - if (maxAge > MaxTimeSpanSeconds || maxAge < MinTimeSpanSeconds) + try + { + result.MaxAge = TimeSpan.FromSeconds(maxAge); + } + catch (ArgumentOutOfRangeException) { // MaxAge value would overflow TimeSpan, abort return 0; } - - result.MaxAge = TimeSpan.FromSeconds(maxAge); offset += itemLength; } // domain-av = "Domain=" domain-value From 3d23d0a8432ec108581ab1dee4c5d4687eba5485 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 19 Aug 2025 21:12:28 +0000 Subject: [PATCH 4/5] Revert to manual validation approach instead of try-catch for TimeSpan overflow handling Co-authored-by: danmoseley <6385855+danmoseley@users.noreply.github.com> --- src/Http/Headers/src/SetCookieHeaderValue.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Http/Headers/src/SetCookieHeaderValue.cs b/src/Http/Headers/src/SetCookieHeaderValue.cs index 72bc59957029..55cccf068b5f 100644 --- a/src/Http/Headers/src/SetCookieHeaderValue.cs +++ b/src/Http/Headers/src/SetCookieHeaderValue.cs @@ -587,15 +587,17 @@ private static int GetSetCookieLength(StringSegment input, int startIndex, out S maxAge = -maxAge; } - try - { - result.MaxAge = TimeSpan.FromSeconds(maxAge); - } - catch (ArgumentOutOfRangeException) + // Check if maxAge would cause TimeSpan.FromSeconds to overflow + // TimeSpan.MaxValue.TotalSeconds is approximately 922337203685.4775 + const long MaxTimeSpanSeconds = 922337203685L; + const long MinTimeSpanSeconds = -922337203685L; + if (maxAge > MaxTimeSpanSeconds || maxAge < MinTimeSpanSeconds) { // MaxAge value would overflow TimeSpan, abort return 0; } + + result.MaxAge = TimeSpan.FromSeconds(maxAge); offset += itemLength; } // domain-av = "Domain=" domain-value From ecd95675248fd63c88451cb2fc0a00c802d6b60e Mon Sep 17 00:00:00 2001 From: Dan Moseley Date: Wed, 20 Aug 2025 15:29:11 -0600 Subject: [PATCH 5/5] Update src/Http/Headers/src/SetCookieHeaderValue.cs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Günther Foidl --- src/Http/Headers/src/SetCookieHeaderValue.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Http/Headers/src/SetCookieHeaderValue.cs b/src/Http/Headers/src/SetCookieHeaderValue.cs index 55cccf068b5f..967d959d0016 100644 --- a/src/Http/Headers/src/SetCookieHeaderValue.cs +++ b/src/Http/Headers/src/SetCookieHeaderValue.cs @@ -591,7 +591,7 @@ private static int GetSetCookieLength(StringSegment input, int startIndex, out S // TimeSpan.MaxValue.TotalSeconds is approximately 922337203685.4775 const long MaxTimeSpanSeconds = 922337203685L; const long MinTimeSpanSeconds = -922337203685L; - if (maxAge > MaxTimeSpanSeconds || maxAge < MinTimeSpanSeconds) + if (maxAge is > MaxTimeSpanSeconds or < MinTimeSpanSeconds) { // MaxAge value would overflow TimeSpan, abort return 0;