2011-06-24 13 views
8

Estoy aprendiendo sobre el código administrado y no administrado en CLR. Así que escribió este ejemplo con los punteros de tipo C en C#:¿Qué es inseguro en este código?

unsafe static void Main(string[] args) 
{ 
    int x; 
    int* y; 
    y = &x; 
    *y = 50; 
    Console.WriteLine(*y); 
    Console.WriteLine(((int)y).ToString()); 
} 

Así que me pregunto lo que realmente no es seguro en el código IL que me dieron en el código anterior?

.assembly extern mscorlib 
{} 
.assembly UnsafePointers 
{} 
.module UnsafePointers.exe 
.class private auto ansi beforefieldinit UnsafePointers.Program 
extends [mscorlib]System.Object 
{ 
    .method private hidebysig static void Main(string[] args) cil managed 
    { 
     .entrypoint 
     // Code size  34 (0x22) 
     .locals init (int32 x, 
     int32* y) 
     IL_0001: ldloca  x 
     IL_0003: conv.u 
     IL_0004: stloc  y 
     IL_0005: ldloc y 
     IL_0006: ldc.i4 50 
     IL_0008: stind.i4 
     IL_0009: ldloc  y 
     IL_000a: ldind.i4 
     IL_000b: call  void [mscorlib]System.Console::WriteLine(int32) 
     IL_0010: nop 
     IL_0011: ldloca  y 
     IL_0012: conv.i4 
     IL_0016: call  instance string [mscorlib]System.Int32::ToString() 
     IL_001b: call  void [mscorlib]System.Console::WriteLine(string) 
     IL_0021: ret 
    } 
}  

¿CLR gestiona este código? ¿Y qué puede salir mal con un código de arriba?

+0

Además de lo que otros dijeron, este código sigue siendo 100% administrado. Es solo que no es verificable que tenga memoria correcta, como la herramienta peverify puede decirte. – John

Respuesta

6

Lo que hace que este código no sea seguro es el uso de la instrucción 'ldind.i4'. Esto carga un entero de 4 bytes firmado desde una dirección de memoria. Se puede dar cualquier dirección de memoria, lo que le permite leer desde cualquier dirección de memoria en el proceso actual. Esto se considera inseguro y no verificable. Por ejemplo, puede usar esto para mirar dentro de otros appdomains, lo cual no está permitido.

+0

¡Gracias por tu respuesta! Creo que esta explicación es lo que estaba buscando. Ahora me parece tan obvio, pero no lo vi hasta ahora. – vldmrrdjcc

+1

Peverify ya falla en el 'conv.u', lo que significa que se niega a llamarlo seguro para volver a interpretar la dirección cargada como un entero. – John

6

Se llama inseguro, en parte porque no se gestiona.

Usted puede crear fácilmente C++ pérdidas de memoria estilo, no hay verificación de límites y otros problemas ...

Un buen artículo sobre el código inseguro, también enumera algunos riesgos:

Using Unsafe Code in C#

+0

Todavía es código administrado, simplemente no se puede verificar. – John

3

En general, la palabra clave unsafe le permite acceder directamente a la memoria y, por lo tanto, pasa por alto todas las comprobaciones y controles de seguridad de la CLR.

He aquí un buen artículo sobre el uso e impacto de unsafe código: http://blogs.msdn.com/b/sebby1234/archive/2006/04/05/565090.aspx

+0

Este es un artículo muy bueno, creo que esto es lo que estaba buscando. ¡Gracias! Solo una pregunta más: ¿cómo CLR sabe que algún código IL es inseguro?¿Mira los tipos declarados, y si ve, por ejemplo, el tipo de puntero, decide que el código no es seguro? – vldmrrdjcc

4

inseguro no puede significar peligroso, pero hay una cosa que es importante en código no seguro: es imposible de verificar . Esto puede significar varias cosas, como no verificar los límites de una matriz. En tu simple ejemplo. no hay mucho peligroso o aterrador al respecto. Es bastante sencillo.

En puede ser inseguro porque también se mueve alrededor de la mayoría de los mecanismos de seguridad en .NET Framework; que es por lo que el código inseguro requiere plena confianza de todos modos.

Unsafe! = Sin gestionar. Inseguro solo significa que puede manipular punteros.

0

De forma predeterminada, los compiladores C# y Visual Basic.NET de Microsoft producen código "seguro". El código de seguridad es un código que es verificablemente seguro. Sin embargo, al utilizar la palabra clave insegura de C# o el uso de otros lenguajes (como C++ con extensiones administradas o el lenguaje IL Assembly), puede generar código que no puede verificarse de forma segura. Es decir, el código podría, de hecho, estar seguro, pero la verificación no puede probarlo.

un administrador puede optar por desactivar la verificación (utilizando el "Administrador de .NET" Microsoft complemento de la consola de administración). Con la verificación desactivada, el compilador JIT compilará IL no verificable en instrucciones nativas de la CPU; sin embargo, el administrador asume la total responsabilidad del comportamiento del código.