Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can unsafe code in C# cause memory corruption?

Tags:

c#

.net

Basically, memory corruption is caused by overwriting memory you're not supposed to overwrite. I am wondering if this is possible with unsafe code in C# (i.e. not by calling into external unmanaged code). I see two possible cases:

  • Accessing a null pointer -> Trapped by the CLR, throws a NullReferenceException
  • Accessing a pointer to an invalid random memory location -> Trapped by the CLR, throws an AccessViolationException

In both cases it seems the runtime detects and prevents the potential memory corruption from taking place. Therefore, is it possible to corrupt memory from C# using unsafe code? And as a corollary, is it safe to catch AccessViolationExceptions from unsafe code?

like image 957
Asik Avatar asked Aug 21 '13 19:08

Asik


People also ask

What is unsafe code in C?

What Does Unsafe Mean? Unsafe is a C programming language (C#) keyword used to denote a section of code that is not managed by the Common Language Runtime (CLR) of the . NET Framework, or unmanaged code. Unsafe is used in the declaration of a type or member or to specify block code.

What is an unsafe programming language?

Since memory safety bugs are often security issues, memory safe languages are more secure than languages that are not memory safe. Memory safe languages include Rust, Go, C#, Java, Swift, Python, and JavaScript. Languages that are not memory safe include C, C++, and assembly.

What makes a program unsafe?

In an unsafe programming language, errors are not trapped. Rather, after executing an erroneous operation the program keeps going, but in a silently faulty way that may have observable consequences later on.

Why is C not memory safe?

For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences. In contrast, C and C++ allow arbitrary pointer arithmetic with pointers implemented as direct memory addresses with no provision for bounds checking, and thus are potentially memory-unsafe.


1 Answers

You are missing the Big Bullet:

  • accessing memory and not getting an AccessViolationException.

Which is very common, there's always lots of writable memory around in a .NET program. Including writing the element beyond the end of an array, it rarely bombs. Memory protection is granular at memory page boundaries, 4096 bytes on Windows. The .NET GC bumps that up considerably, the generational heap segments are nice big hunks of VM. Catching AVEs is very unwise.

Some code to play with:

class Program {
    static unsafe void Main(string[] args) {
        var arr = new byte[1];
        for (int fill = 0; fill < 2 * 1024 - 64; ++fill) {
            byte[] dummy = new byte[1024];
        }
        fixed (byte* p = &arr[0]) {
            for (int ix = 1; ; ++ix)
                p[ix] = 42;
        }
    }
}

Overshoots by about 1.5 megabytes.

like image 118
Hans Passant Avatar answered Oct 13 '22 01:10

Hans Passant