Abstract

In .NET, unsafe code really means potentially unsafe code, which is code or memory that exists outside the normal boundary. This article digs into the details of legacy C programming pointer implementation in the .NET framework. However, we will seldom need to use pointer types. Unsafe code can access unmanaged memory resources, which are outside the realm of CLR. You can access unmanaged memory with raw pointers, which are available only to unsafe code. Finally, using pointers is very risky and prone to breaches because we have to manually manage the subtle memory-related tasks.

Unsafe Coding

In unsafe coding, developers can access raw legacy pointers in the .NET framework environment. You can use pointer operators, such as & and *. As per the semantics of perfect programming practice, pointers should be avoided to make your code safer because they interrupt the normal operation of Garbage Collector and they point to a fixed location in unmanaged memory, while reference types point to a movable location in managed memory. But the question arises: If pointers are so dangerous, then why we are practicing unsafe coding? Why does the .NET framework allow pointers? However, using unsafe coding or pointer is sometimes necessary: for example, porting C/C++ algorithms, which rely heavily on pointers, is very beneficial. There are certain circumstances in which unsafe coding is recommended; e.g.:

  • Calling an unmanaged function that requires a function pointer as a parameter.
  • Unmanaged pointers no doubt improve performance and efficiency.
  • Pointers might be easier and more convenient when working with binary and memory-resident data structure.

Safe Coding

Improper pointer management causes many common problems, including memory leaks, accessing invalid memory, and deleting bad pointers. Safe coding is limited to accessing the managed heap. The managed heap is managed by Garbage Collector, which is an essential component of the common language runtime. Code restricted to the managed heap is intrinsically safer than code that accesses unmanaged memory. The CLR automatically releases unused objects, conducts type verification, and performs other checks on managed memory. All this is not done automatically for unmanaged code; rather, the developer is responsible for these tasks. With managed coding, the developer can only focus on core application development instead of various administrative tasks, such as memory management.

Note: Code in an unmanaged section is considered unsafe and not accessible to the CLR. Therefore, no code verification or stack tracing is performed on the unmanaged code.

Pointers Implementation

Managed applications that include unsafe code must be compiled with the unsafe option. The C# compiler option is simply /unsafe. In VS 2010 IDE, this option is found under solution properties in the build tab. You just have to check this option in order to compile the unsafe code that is leveraged with pointers.

Note: Unsafe coding and pointer implementation require some background of C++ pointer manipulation.


The unsafe Keyword

The unsafe keyword specifies the location of unsafe code. When this keyword is applied to a type, all the members of that type are also considered unsafe because code inside the target is considered unsafe. When you wish to work with pointers in C#, you must specifically declare a block of unsafe code using the unsafe keyword.The following code segment depicts the overview of an unsafe code block:

classProgram
{
staticvoid Main(string[] args)
{
//// pointers won't work here
unsafe
{
// pointer manipulation (&, *)
}
}
}

We can also mark classes, methods, structure, variables, and parameters with unsafe keyword like this:

publicunsafeclasstest
{
unsafeint x = 10;

unsafevoidmyMethod(int* x)
{
}
}

The following sample does some math calculation by using a pointer and eventually produces a square root:

using System;

namespaceunsafePro
{
classProgram
{
staticvoid Main(string[] args)
{
unsafe
{
double x = 10;
sqrt(&x);
}

Console.ReadKey();
}

unsafestaticvoidsqrt(double* i)
{
Console.WriteLine("Square Root is={0}",Math.Sqrt(*i));
}
}
}

The important point to remember here is that an unsafe method must be called from the unsafe block, otherwise compile will issue an error. The following implementation produces a compile-time error because we are calling the sqrt method from outside the unsafe block:

staticvoid Main(string[] args)
{
unsafe
{
double x = 10;
sqrt(&x);
}

int y = 5;

sqrt(&y); //compile time error
}

We can avoid the hassle of an unsafe block by putting the unsafe keyword prefix over than main method:

unsafestaticvoid Main(string[] args)
{
double x = 10;
sqrt(&x);
}

Pointer Declaration and Syntax

C# does not expose the pointer automatically. Exposing a pointer requires an unsafe context. Pointers normally are abstract, using references in C#. The reference abstracts a pointer to memory on the managed heap. The reference and related memory are managed by the GC. Here is the syntax for declaring a pointer:

unmanagedtype* identifier;

int* x,y;

int *x, *y; // Wrong Syntax error

Here the asterisk symbol has two purposes. The first is to declare a new pointer variable and the second is to dereference a pointer.

The (->) Operator

Want to learn more?? The InfoSec Institute Advanced Computer Forensics Training trains you on critical forensic skills that are difficult to master outside of a lab enviornment. Already know how to acquire forensically sound images? Perform file carving? Take your existing forensic knowledge further and sharpen your skills with this Advanced Computer Forensics Boot Camp from InfoSec Institute. Upon the completion of our Advanced Computer Forensics Boot Camp, students will know how to:
  • Perform Volume Shadow Copy (VSC) analysis
  • Advanced level file and data structure analysis for XP, Windows 7 and Server 2008/2012 systems
  • Timeline Analysis & Windows Application Analysis
  • iPhone Forensics

Arrow notation (->) dereference members of a pointer type found at a memory location. For instance, you can access members of a structure type using arrow notation and a pointer like this:

namespaceunsafePro
{
publicstructxyz
{
publicint x;
publicint y;
}
classProgram
{
staticvoid Main(string[] args)
{
unsafe
{
xyzobj = newxyz();
xyz* aa = &obj;
aa->x = 200;
aa->y = 400;
Console.WriteLine("X is={0}", aa->x);
Console.WriteLine("Y is={0}", aa->y);
}

Console.ReadKey();
}
}
}

The sizeof Keyword

As in C++, the sizeof keyword is used to obtain the size in bytes of a value type and it may only be used in an unsafe context.

staticvoid Main(string[] args)
{
unsafe
{
Console.WriteLine("Int size is={0}", sizeof(int));
Console.WriteLine("Int16 size is={0}", sizeof(Int16));
Console.WriteLine("Int32 size is={0}", sizeof(Int32));
Console.WriteLine("Int64 size is={0}", sizeof(Int64));
}

}

After compiling this program, it produces the size of each integer type as follows:


The stackalloc Keyword

In the unsafe context, we can declare a local variable that allocates memory directly from the call stack. To do so, C# provides the stackalloc keyword, which is the C# equivalent of the allocate function of the C runtime library.

unsafestaticstring data()
{
char* buffer = stackallocchar[5];
for (int i = 0; i < 5; i++)
{
buffer[i] = 'a';
}
returnnewstring(buffer);
}

Synopsis

The purpose of this article was to investigate one of the advance concept pointer implementations under the CLR context. We got a deep understanding of unsafe and safe programming and we learned how to implement pointers using C #.net. Finally, we spent some time examining small sets of pointer-related keywords such as unsafe, sizeof, and stackalloc.