Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does this code work without the unsafe keyword?

Tags:

c#

.net

unsafe

In an answer to his own controversial question, Mash has illustrated that you don't need the "unsafe" keyword to read and write directly to the bytes of any .NET object instance. You can declare the following types:

   [StructLayout(LayoutKind.Explicit)]
   struct MemoryAccess
   {

      [FieldOffset(0)]
      public object Object;

      [FieldOffset(0)]
      public TopBytes Bytes;
   }

   class TopBytes
   {
      public byte b0;
      public byte b1;
      public byte b2;
      public byte b3;
      public byte b4;
      public byte b5;
      public byte b6;
      public byte b7;
      public byte b8;
      public byte b9;
      public byte b10;
      public byte b11;
      public byte b12;
      public byte b13;
      public byte b14;
      public byte b15;
   }

And then you can do things like change an "immutable" string. The following code prints "bar" on my machine:

 string foo = "foo";
 MemoryAccess mem = new MemoryAccess();
 mem.Object = foo;
 mem.Bytes.b8 = (byte)'b';
 mem.Bytes.b10 = (byte)'a';
 mem.Bytes.b12 = (byte)'r';
 Console.WriteLine(foo);

You can also trigger an AccessViolationException by corrupting object references with the same technique.

Question: I thought that (in pure managed C# code) the unsafe keyword was necessary to do things like this. Why is it not necessary here? Does this mean that pure managed "safe" code is not really safe at all?

like image 477
Wim Coenen Avatar asked Apr 27 '09 08:04

Wim Coenen


People also ask

What does it mean for code to be unsafe?

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.

Why do we need unsafe in C#?

C# supports an unsafe context, in which you may write unverifiable code. In an unsafe context, code may use pointers, allocate and free blocks of memory, and call methods using function pointers. Unsafe code in C# isn't necessarily dangerous; it's just code whose safety cannot be verified.

What is the difference between unsafe code and unmanaged code?

This is responsible for things like memory management and garbage collection. So unmanaged simply runs outside of the context of the CLR. unsafe is kind of "in between" managed and unmanaged. unsafe still runs under the CLR, but it will let you access memory directly through pointers.

Is Unsafe code faster?

Unsafe code typically runs faster than a corresponding safe implementation, which in this case would have required a nested loop with array indexing and bounds checking.


1 Answers

OK, that is nasty... the dangers of using a union. That may work, but isn't a very good idea - I guess I'd compare it to reflection (where you can do most things). I'd be interested to see if this works in a constrained access environment - if so, it may represent a bigger problem...


I've just tested it without the "Full Trust" flag, and the runtime rejects it:

Could not load type 'MemoryAccess' from assembly 'ConsoleApplication4, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' because objects overlapped at offset 0 and the assembly must be verifiable.

And to have this flag, you already need high trust - so you can already do more nasty things. Strings are a slightly different case, because they aren't normal .NET objects - but there are other examples of ways to mutate them - the "union" approach is an interesting one, though. For another hacky way (with enough trust):

string orig = "abc   ", copy = orig;
typeof(string).GetMethod("AppendInPlace",
    BindingFlags.NonPublic | BindingFlags.Instance,
    null, new Type[] { typeof(string), typeof(int) }, null)
    .Invoke(orig, new object[] { "def", 3 });
Console.WriteLine(copy); // note we didn't touch "copy", so we have
                         // mutated the same reference
like image 170
Marc Gravell Avatar answered Oct 26 '22 03:10

Marc Gravell