Why are methods that operate pointers insecure in . NET?

Asked

Viewed 230 times

8

Reading a bit of the . NET source code I realized that some methods have a peculiar modifier, the unsafe.

[System.Security.SecuritySafeCritical]  // auto-generated
[System.Runtime.CompilerServices.FriendAccessAllowed]
internal unsafe static Boolean TryStringToNumber(String str, NumberStyles options, ref NumberBuffer number, StringBuilder sb, NumberFormatInfo numfmt, Boolean parseDecimal) {   

    if (str == null) {
        return false;
    }
    Contract.Assert(numfmt != null, "");

    fixed (char* stringPointer = str) {
        char * p = stringPointer;
        if (!ParseNumber(ref p, options, ref number, sb, numfmt, parseDecimal) 
            || (p - stringPointer < str.Length && !TrailingZeros(str, (int)(p - stringPointer)))) {
            return false;
        }
    }

    return true;
}

Documentation is clear on the modifier:

The unsafe keyword denotes an unsafe context, which is required for any operation involving pointers. Source

  • What does this modifier do?
  • Why contexts involving pointer manipulation are considered unsafe in . NET?

3 answers

5


What does this modifier do?

The modifier only indicates to the compiler that you will use unsafe code and therefore it must allow this code to be considered valid.

To compile a code unsafe it is necessary to say this to the compiler with the flag /unsafe.

The language developers wanted to give the ease of manipulating data more freely than normal C# allows, but they didn’t want it to be done without being explicit, they didn’t want it to be abused. What could even facilitate some optimizations in other points.

Note that its use changes the security features of the application and may require use in a slightly different way than normal. You may not even be able to perform in certain scenarios. The code becomes unverifiable by CLR.

Why contexts involving pointer manipulation are considered unsafe in . NET?

The raw pointer is the main unsafe mechanism of the language, but it is useful for interoperability with other languages, mainly C and also to get more performance by accessing memory directly, in the same way that C does.

Not that it is completely free and memory is no longer managed when it does, but it can misinterpret parts of data and cause unexpected results that are not normal within what is normally accepted in C#.

Depending on how it is used it is possible to open a security breach and an external data interfere with access to memory and have the problems that normally a language like C or C++ has. Although a little more limited since you can’t access arbitrary memory positions, you have to take address from an existing object.

Pointers

The pointer does not have the same access controls as other forms have, forms that make the code slower. In general the access control of array is responsible for this. Note that the Jitter can eliminate this and the speed stay the same from the use of pointers. Yet the most common scenario where it is possible to eliminate this overhead has other costs.

There is some limitation of how you can use the pointer, it cannot point to any type, only types by value are accepted (the pointer is a type by value). There is a restriction for types that have reference types as one of their members (you can point to a char within a string, but cannot point to a string).

It includes the void * which is a pointer to an unknown type, but he can’t access anything if he wants to use it to access another type needs a cast for the type to make clear the intention, which in practice makes its use safer and less useful than in C (C3 has better mechanisms).

Pointers leave the normal C#type system, so they do not inherit from the Object and cannot be used normally.

Guys' security is relaxed, but not off.

With the advent of Span<T> the use of pointer becomes less necessary yet. It makes use of insecure mechanism internally, so you don’t need to use.

4

What does this modifier do?

Code blocks formed with unsafe allow the use of pointers within it, example:

using System;
class MyClass {
    public unsafe static void Main() {
        int numero = 10;
        int* pNumero = &numero;
        Console.WriteLine("numero é " + numero);
        Console.WriteLine("endereço é " + (int)pNumero );
    }
}

if you hadn’t been there unsafe, a build error would occur.

Why contexts involving pointer manipulation are considered unsafe in . NET?

I believe pointers are relatively "insecure" in any environment, not only . NET, because if used incorrectly, may result in unexpected behaviors, or Undefined Behaviors. In C#, what you would normally expect to trigger an exception, could simply have as output a strange or unexpected value due to the use of pointers.

The use of C#pointers is rarely useful, but there are some situations where it can be useful, such as some code snippet where it is necessary to have the highest possible performance

4

C# is a language with type security (type-Safety)

But what would be type security? The easiest way to explain this is to explain how contrary of this.

In languages such as C or C++ you can do things powerful on stage correct (and dangerous if not careful), how to treat a data type as another totally different type, without converting or caste this item for the specified type.

For example, you can pick up a pointer from a char and treat it like a pointer int. This is common and acceptable in these languages. The language really reads the bytes of the specified pointer value and interprets them wrong.

This is the definition of the opposite of what would be an operation with "type security" or "type-Safety".

In the C#, we have what we call type security (type-Safety), where the compiler ensures that that object really is of that kind, which prevents this kind of thing from being done, not allowing access to pointers, however, by adding the modifier unsafe, you get out of this zone of comfort and safety and can abuse pointers and types as own C/C++ (still with a little security).

Obviously, in C# you can try caste an object of one type to another type, but if the compiler detects that it really is impossible the conversion between these two types, it will accuse build error. Even if the compiler accepts the cast of types not compatible, the runtime will throw error on execution.

There is also the dynamic language in C#, which works more or less like the unsafe, but without access to pointers.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.