RSSAmplifier

Levicki's Tech Spot · May 29, 2026

Thoughts on Improving C# Memory Safety

0
Sign in to vote or save

Igor Levicki · levicki.net

Published on 2026/05/29 by Igor Levicki

Richard Lander, a product manager on .NET Team has recently posted a blog article titled Improving C# Memory Safety.

The blog post goes to great lengths to try to explain (read: rationalize) planned "improvements" to memory safety model and the unsafe keyword that are coming in C# 16.

Here is the summary of changes condensed from that 75 KB wall of text into 5 easy to understand points:

  1. Mandatory unsafe {} Blocks: Previously only pointer dereferences had to be wrapped, now even calls to methods marked unsafe must be explicitly wrapped in an unsafe { } block.
  2. Signature Propagation: Adding unsafe to a member signature now passes the safety obligations up to the next caller.
  3. Safety Docs: Unsafe members must use a /// <safety> comment block to document caller obligations, or analyzers will flag them.
  4. Signature Decoupling: Pointer types (byte*, void*) as well as nint, and IntPtr in a method signature no longer propagate unsafety automatically.
  5. Structural Restrictions: Classes, structs, static constructors, and finalizers can't be marked as unsafe.

While some of those changes make sense (#2, #4, #5), the rest of them (#1,#3) are, and I am being generous here, controversial at the minimum.

After reading the blog post I felt compelled to respond to it and I did so originally by writing a comment in which I tore into the overall tone of the article, the real motivation for making a change, divorce from reality, and a fake notion of safety provided by the above-mentioned points #1 and #3.

I am including the screenshot of my original comment here since it was deleted:

Deleted comment from Igor Levicki

Now I admit I put it over the top to make a point, and Richard Lander has the right to dislike the tone of my comment. However, deleting it in its entirety just shows he's incapable or unwilling (or both) to structurally answer the actual and factual criticism embedded in it.

Here are the technical points I made in the comment which went unanswered:

  • Instead of adding a method keyword such as boundary or using the existing safe keyword as mandatory on a method using unsafe code to force developers to actually implement correct safety boundaries it just tosses a live grenade up the stack for someone else to handle.
  • In its current state, it does ABSOLUTELY NOTHING to guarantee memory access safety — your NativeBuffer example shows that perfectly as the Dispose method isn't memory safe despite unsafe block and Safety comment claiming otherwise. You can't have full memory safety without thread safety, those are intertwined and this proposal falls short of addressing that part. Not doing it now is only going to make it harder once the infestation of nested unsafe blocks and walls of safety comments spreads through the codebases.
  • It feels like a knee-jerk reaction to June 24, 2025 CISA report titled Memory Safe Languages: Reducing Vulnerabilities in Modern Software Development except they totally ignored "use-after-free" and "data races" points and screamed "OMG we have to do something" and someone said "let's make unsafe more cumbersome to use, that will improve safety" and nobody objected.

TL;DR — There's no proper memory safety without thread safety, and forcing developers to add more boilerplate code and comments to make unsafe code more visible (instead of safer!) is a security theater which might result in even worse code safety going forward.

Read the original on levicki.net

Comments

Nothing yet. Say the first thing.

    Sign in to join the conversation.