Why methods that operate pointers are insecure in .NET?

8

Reading a little of the .NET source code I noticed 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;
}

The documentation is clear about the modifier:

  

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

  • What does this modifier do?
  • Why contexts involving pointer manipulation are considered unsafe in .NET?
asked by anonymous 09.10.2017 / 21:15

3 answers

5
  

What does this modifier do?

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

To compile a unsafe code, you have to say this to the compiler with flag /unsafe .

Language developers wanted to give the facility of manipulating data more freely than the norm C # allows, but they did not want this done without being explicit, they did not want them to abuse it. What could even facilitate some optimizations at other points.

Note that its use changes the security features of the application and may require the use of a slightly different form than normal. You may not even be able to execute 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 insecure mechanism of the language, but it is useful for interoperability with other languages, especially C and also for more performance accessing memory directly, in the same way that C does.

Not that it is completely free and that memory can no longer be managed when it does, but it can wrongly access pieces of data and cause unexpected results that are not normal within what is usually accepted in C #.

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

Pointers

The pointer does not have the same access controls as other shapes, which makes the code slower. In general, access control of array is responsible for this. Note that JITter can eliminate this and the speed remains the same as using pointers. Although the most common scenario where you can eliminate this overhead has other costs.

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

Include the void * that is a pointer to an unknown type, but it can not access anything if you want to use it to access another type needs a cast for type to make clear the intention, which in practice makes its use more secure and less useful than in C.

Pointers come out of the normal C # type system, so they do not inherit from Object and can not be used normally.

Type security is relaxed, but not turned off.

With the advent of Span<T> the use of pointer becomes less needed yet.

    
09.10.2017 / 21:32
4

What does this modifier do?

Code blocks formed with unsafe allow the use of pointers inside it, eg:

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 it did not have unsafe , then a compile error would happen.

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

I believe pointers are relatively "insecure" in any environment, not just .NET, because if used incorrectly, they can result in unexpected behaviors, or undefined behaviors . In C #, what you would normally expect to trigger an exception might simply output a strange or unexpected value due to the use of pointers.

It is rarely useful to use pointers in C #, but there are some situations where it might be useful, like some code snippet where performance is required as high as possible

    
09.10.2017 / 21:31
4

C # is a type-safe language

In languages such as C or C++ you can do powerful things in the correct scenario (and dangerous ) if you are not careful ), how to treat a data type as another totally different type, without converting or casting this element to the specified type.

For example, you can get a pointer from a char and treat it as if it were a pointer of type int . This is common and acceptable in these languages. The language actually reads the bytes of the value of the specified pointer and interprets them the wrong way .

This is the opposite definition of what would be a "type-safety" or "type-safety" operation.

In C# , we have what we call type-safety, in which the compiler ensures that that object really is of that type, the that prevents this type of thing from being made, not allowing access to pointers, however, by adding the unsafe modifier, you get out of this zone of comfort and security and may abuse pointers and types like the actual C/C++ (still with a bit of security).

Obviously in C # you can try casting an object of one type to another type, but if the compiler detects that it is really impossible to convert between these two types, it will accuse compilation error. Even if the compiler accepts cast of noncompatible types, runtime will throw execution error.

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

    
09.10.2017 / 21:36