Remove unsafe code from SmtpReplyReaderFactory.ProcessRead#121297
Remove unsafe code from SmtpReplyReaderFactory.ProcessRead#121297
Conversation
SmtpReplyReaderFactory.cs in ProcessRead function, please file a PR to replace with just normal ReadOnlySpan memory access to make it memory safe.…plyReaderFactory Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
xtqqczze
left a comment
There was a problem hiding this comment.
Codegen with !char.IsAsciiDigit((char)b) should be equivalent: sharplab.io
src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpReplyReaderFactory.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpReplyReaderFactory.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpReplyReaderFactory.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: xtqqczze <45661989+xtqqczze@users.noreply.github.com>
There was a problem hiding this comment.
Pull Request Overview
This PR refactors the ProcessRead method in SmtpReplyReaderFactory to eliminate unsafe pointer-based code in favor of safe, index-based buffer access. The logic remains functionally equivalent while improving code safety and maintainability.
Key Changes:
- Replaced unsafe pointer arithmetic (
ptr++,*ptr, etc.) with safe array indexing using anicounter - Removed the
unsafeblock andfixedstatement that were previously required for pointer manipulation - Maintained the same state machine logic for parsing SMTP reply messages
src/libraries/System.Net.Mail/src/System/Net/Mail/SmtpReplyReaderFactory.cs
Show resolved
Hide resolved
|
@stephentoub @MihaZupan is it fine to remove the unsafe from System.Net.Mail Smtp without perf benchmark, it's unclear to me how nanoseconds saved on bounds check can have an impact on it + SmptClient is effectively deprecated
|
|
I recommend reviewing it with "Hide whitespaces" option |
|
Tagging subscribers to this area: @dotnet/ncl |
|
I think the perf is fine. But it still looks complicated to me. Basically it should be 3 digits + ASCII text. I would think there is better way than iterating though and keeping stated. (assuming we can handle the folding) |
rzikm
left a comment
There was a problem hiding this comment.
LGTM, I agree that the logic could be simplified (not only here, but across the entire implementation), but I already touched many parts during the refactor that I didn't want to add another possible breaking point.
|
/ba-g deadletter |

The
ProcessReadmethod used unnecessary unsafe pointer arithmetic despite accepting aReadOnlySpan<byte>parameter that already provides safe, efficient indexing.Changes
Replaced unsafe pointer arithmetic with ReadOnlySpan indexing
unsafeblock andfixedstatementbyte*pointers with integer index tracking*ptr++tobuffer[i++],(int)(ptr - start)toiFixed pre-existing validation bug (discovered during refactoring)
if (b < '0' && b > '9')toif (b < '0' || b > '9')in digit validationBefore/After
All existing tests pass. No API or behavior changes.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
1d7b368770e34adf874f9425defe0a54/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)2f1ac5ebdede409c885709296cd79caf/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)3e267405dc55499fbf89ba600b269486/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)4741d8119c5b46deb7b6a3247cf3e987/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)4777e169b2a54bef872d3013b91d119d/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)674cfdb34af049bc80dcbc8c430c56e8/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)83b38af9921845538f0d2b8e91bd4c93/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)8445b7f8594e4fa79d67a5f60e1917e1/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)9c17f6fe624d4688a482d039f62e9376/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)9caf23efb9b44deeaad1f5a4390857ed/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)ad5b1d9a0284470497198faf9964749f/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)dad9f17011b54a2883ca8f7489dde4e8/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)dc00558270b44330978820a282438ebc/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)f13d3b87148d4771ab29f5a3afc20964/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)f4e51707a3454d68a871b21a5edce6f6/home/REDACTED/work/runtime/runtime/artifacts/bin/testhost/net10.0-linux-Debug-x64/dotnet exec --runtimeconfig System.Net.Mail.Functional.Tests.runtimeconfig.json --depsfile System.Net.Mail.Functional.Tests.deps.json /home/REDACTED/.nuget/packages/microsoft.dotnet.xunitconsoleREDACTED/2.9.3-beta.25528.108/build/../tools/net/xunit.console.dll System.Net.Mail.Functional.Tests.dll -xml testResults.xml -nologo -notrait category=OuterLoop -notrait category=failing(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.