Skip to content

Commit b6e2c0d

Browse files
Copilotericstj
authored andcommitted
Use Base64.DecodeFromUtf8 to avoid string intermediate during decoding
Co-authored-by: ericstj <[email protected]>
1 parent f3f6a70 commit b6e2c0d

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

src/ModelContextProtocol.Core/Protocol/BlobResourceContents.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Buffers.Text;
12
using System.Diagnostics;
23
using System.Runtime.InteropServices;
34
using System.Text.Json.Serialization;
@@ -60,7 +61,17 @@ public ReadOnlyMemory<byte> Data
6061
if (_decodedData is null)
6162
{
6263
#if NET
63-
_decodedData = Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(Blob.Span));
64+
// Decode directly from UTF-8 base64 bytes without string intermediate
65+
int maxLength = Base64.GetMaxDecodedFromUtf8Length(Blob.Length);
66+
byte[] buffer = new byte[maxLength];
67+
if (Base64.DecodeFromUtf8(Blob.Span, buffer, out _, out int bytesWritten) == System.Buffers.OperationStatus.Done)
68+
{
69+
_decodedData = bytesWritten == maxLength ? buffer : buffer.AsMemory(0, bytesWritten).ToArray();
70+
}
71+
else
72+
{
73+
throw new FormatException("Invalid base64 data");
74+
}
6475
#else
6576
byte[] array = MemoryMarshal.TryGetArray(Blob, out ArraySegment<byte> segment) && segment.Offset == 0 && segment.Count == segment.Array!.Length ? segment.Array : Blob.ToArray();
6677
_decodedData = Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(array));

src/ModelContextProtocol.Core/Protocol/ContentBlock.cs

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System.Buffers;
2+
using System.Buffers.Text;
23
using System.ComponentModel;
34
using System.Diagnostics;
45
using System.Diagnostics.CodeAnalysis;
@@ -426,7 +427,17 @@ public ReadOnlyMemory<byte> DecodedData
426427
if (_decodedData is null)
427428
{
428429
#if NET
429-
_decodedData = Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(Data.Span));
430+
// Decode directly from UTF-8 base64 bytes without string intermediate
431+
int maxLength = Base64.GetMaxDecodedFromUtf8Length(Data.Length);
432+
byte[] buffer = new byte[maxLength];
433+
if (Base64.DecodeFromUtf8(Data.Span, buffer, out _, out int bytesWritten) == System.Buffers.OperationStatus.Done)
434+
{
435+
_decodedData = bytesWritten == maxLength ? buffer : buffer.AsMemory(0, bytesWritten).ToArray();
436+
}
437+
else
438+
{
439+
throw new FormatException("Invalid base64 data");
440+
}
430441
#else
431442
byte[] array = MemoryMarshal.TryGetArray(Data, out ArraySegment<byte> segment) && segment.Offset == 0 && segment.Count == segment.Array!.Length ? segment.Array : Data.ToArray();
432443
_decodedData = Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(array));
@@ -491,7 +502,17 @@ public ReadOnlyMemory<byte> DecodedData
491502
if (_decodedData is null)
492503
{
493504
#if NET
494-
_decodedData = Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(Data.Span));
505+
// Decode directly from UTF-8 base64 bytes without string intermediate
506+
int maxLength = Base64.GetMaxDecodedFromUtf8Length(Data.Length);
507+
byte[] buffer = new byte[maxLength];
508+
if (Base64.DecodeFromUtf8(Data.Span, buffer, out _, out int bytesWritten) == System.Buffers.OperationStatus.Done)
509+
{
510+
_decodedData = bytesWritten == maxLength ? buffer : buffer.AsMemory(0, bytesWritten).ToArray();
511+
}
512+
else
513+
{
514+
throw new FormatException("Invalid base64 data");
515+
}
495516
#else
496517
byte[] array = MemoryMarshal.TryGetArray(Data, out ArraySegment<byte> segment) && segment.Offset == 0 && segment.Count == segment.Array!.Length ? segment.Array : Data.ToArray();
497518
_decodedData = Convert.FromBase64String(System.Text.Encoding.UTF8.GetString(array));

0 commit comments

Comments
 (0)