Skip to content

Commit ec4cc0f

Browse files
Copilotpmaytak
andauthored
Fix IDX10816 decompression failure for large JWE payloads in DeflateCompressionProvider (#3286)
* Initial plan * Initial plan for fixing IDX10816 decompression issue Co-authored-by: pmaytak <[email protected]> * Fix IDX10816 decompression issue and add tests Co-authored-by: pmaytak <[email protected]> * Final verification and restore global.json Co-authored-by: pmaytak <[email protected]> * Change comparison to <= MaximumDeflateSize for clearer intent in loop condition Co-authored-by: pmaytak <[email protected]> * Addressing PR comments Co-authored-by: pmaytak <[email protected]> * Revert global.json to original state - only decompression changes needed Co-authored-by: pmaytak <[email protected]> * Update DeflateCompressionProviderTests to use Assert class instead of CompareContext/TestUtilities Co-authored-by: pmaytak <[email protected]> * Add test to reproduce issue #2516 scenario with large JWE payload decompression Co-authored-by: pmaytak <[email protected]> * Fix formatting, fix tests. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: pmaytak <[email protected]>
1 parent 35cc68b commit ec4cc0f

File tree

2 files changed

+62
-2
lines changed

2 files changed

+62
-2
lines changed

src/Microsoft.IdentityModel.Tokens/DeflateCompressionProvider.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,16 @@ public byte[] Decompress(byte[] value)
7777
{
7878
using (var reader = new StreamReader(deflateStream, Encoding.UTF8))
7979
{
80+
int totalCharsRead = 0;
81+
int charsRead;
82+
83+
// Read from the stream until all data is consumed or max size is reached
84+
while (totalCharsRead <= MaximumDeflateSize && (charsRead = reader.Read(chars, totalCharsRead, MaximumDeflateSize - totalCharsRead)) > 0)
85+
{
86+
totalCharsRead += charsRead;
87+
}
88+
8089
// if there is one more char to read, then the token is too large.
81-
int bytesRead = reader.Read(chars, 0, MaximumDeflateSize);
8290
if (reader.Peek() != -1)
8391
{
8492
throw LogHelper.LogExceptionMessage(
@@ -88,7 +96,7 @@ public byte[] Decompress(byte[] value)
8896
LogHelper.MarkAsNonPII(MaximumDeflateSize))));
8997
}
9098

91-
return Encoding.UTF8.GetBytes(chars, 0, bytesRead);
99+
return Encoding.UTF8.GetBytes(chars, 0, totalCharsRead);
92100
}
93101
}
94102
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
3+
4+
using System.Text;
5+
using Xunit;
6+
7+
namespace Microsoft.IdentityModel.Tokens.Tests
8+
{
9+
public class DeflateCompressionProviderTests
10+
{
11+
[Fact]
12+
public void DecompressLargePayload_ShouldSucceed()
13+
{
14+
var largeData = CreateLargeTestData(50000);
15+
16+
var provider = new DeflateCompressionProvider();
17+
provider.MaximumDeflateSize = 10000000;
18+
var compressedData = provider.Compress(Encoding.UTF8.GetBytes(largeData));
19+
var decompressedData = provider.Decompress(compressedData);
20+
var result = Encoding.UTF8.GetString(decompressedData);
21+
22+
Assert.Equal(largeData, result);
23+
}
24+
25+
[Fact]
26+
public void DecompressLargePayload_ExceedsMaximumSize_ShouldThrow()
27+
{
28+
var data = CreateLargeTestData(1000);
29+
30+
var provider = new DeflateCompressionProvider();
31+
provider.MaximumDeflateSize = 100; // Very small limit
32+
33+
var compressedData = provider.Compress(Encoding.UTF8.GetBytes(data));
34+
35+
var exception = Assert.Throws<SecurityTokenDecompressionFailedException>(() => provider.Decompress(compressedData));
36+
Assert.Contains("IDX10816", exception.Message);
37+
}
38+
39+
private string CreateLargeTestData(int itemCount)
40+
{
41+
var sb = new StringBuilder();
42+
sb.Append('[');
43+
for (int i = 0; i < itemCount; i++)
44+
{
45+
if (i > 0) sb.Append(',');
46+
sb.Append($"{{\"Prop1\":\"TestValue{i}\",\"Prop2\":{i},\"Prop3\":\"SomeAdditionalDataToMakeItLarger{i}\"}}");
47+
}
48+
sb.Append(']');
49+
return sb.ToString();
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)