Skip to content

Commit d963ce4

Browse files
Copilotdanmoseley
andauthored
Fix SetCookieHeaderValue.TryParse throwing ArgumentOutOfRangeException for Max-Age overflow (#63323)
* Initial plan * Fix TimeSpan overflow in SetCookieHeaderValue.TryParse for Max-Age Co-authored-by: danmoseley <[email protected]> * Simplify overflow handling using exception handling instead of manual validation Co-authored-by: danmoseley <[email protected]> * Revert to manual validation approach instead of try-catch for TimeSpan overflow handling Co-authored-by: danmoseley <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: danmoseley <[email protected]>
1 parent d520252 commit d963ce4

File tree

2 files changed

+36
-0
lines changed

2 files changed

+36
-0
lines changed

src/Http/Headers/src/SetCookieHeaderValue.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,16 @@ private static int GetSetCookieLength(StringSegment input, int startIndex, out S
587587
maxAge = -maxAge;
588588
}
589589

590+
// Check if maxAge would cause TimeSpan.FromSeconds to overflow
591+
// TimeSpan.MaxValue.TotalSeconds is approximately 922337203685.4775
592+
const long MaxTimeSpanSeconds = 922337203685L;
593+
const long MinTimeSpanSeconds = -922337203685L;
594+
if (maxAge is > MaxTimeSpanSeconds or < MinTimeSpanSeconds)
595+
{
596+
// MaxAge value would overflow TimeSpan, abort
597+
return 0;
598+
}
599+
590600
result.MaxAge = TimeSpan.FromSeconds(maxAge);
591601
offset += itemLength;
592602
}

src/Http/Headers/test/SetCookieHeaderValueTest.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,4 +486,30 @@ public void SetCookieHeaderValue_TryParseStrictList_FailsForAnyInvalidValues(
486486
Assert.Null(results);
487487
Assert.False(result);
488488
}
489+
490+
[Theory]
491+
[InlineData("name=value; max-age=922337203686")] // One more than TimeSpan.MaxValue.TotalSeconds
492+
[InlineData("name=value; max-age=999999999999999999999")] // Much larger value
493+
[InlineData("name=value; max-age=-922337203686")] // Negative overflow
494+
public void SetCookieHeaderValue_TryParse_MaxAgeOverflow_ReturnsFalse(string value)
495+
{
496+
// Should return false instead of throwing ArgumentOutOfRangeException
497+
bool result = SetCookieHeaderValue.TryParse(value, out var parsedValue);
498+
Assert.False(result);
499+
Assert.Null(parsedValue);
500+
}
501+
502+
[Theory]
503+
[InlineData("name=value; max-age=922337203685")] // Max valid value
504+
[InlineData("name=value; max-age=-922337203685")] // Min valid value
505+
[InlineData("name=value; max-age=0")] // Zero
506+
[InlineData("name=value; max-age=86400")] // One day in seconds
507+
public void SetCookieHeaderValue_TryParse_MaxAgeValid_ReturnsTrue(string value)
508+
{
509+
// Should successfully parse valid max-age values
510+
bool result = SetCookieHeaderValue.TryParse(value, out var parsedValue);
511+
Assert.True(result);
512+
Assert.NotNull(parsedValue);
513+
Assert.NotNull(parsedValue!.MaxAge);
514+
}
489515
}

0 commit comments

Comments
 (0)