2010-05-21 18 views
21

Digamos que quiero tener un tipo de valor de 7 bytes (o 3 o 777).¿Por qué un búfer de tamaño fijo (matrices) debe ser inseguro?

puedo definirlo así:

public struct Buffer71 
{ 
    public byte b0; 
    public byte b1; 
    public byte b2; 
    public byte b3; 
    public byte b4; 
    public byte b5; 
    public byte b6; 
} 

Una forma más sencilla de definir que utiliza una memoria intermedia fija

public struct Buffer72 
{ 
    public unsafe fixed byte bs[7]; 
} 

Por supuesto, la segunda definición es más simple. El problema radica en la palabra clave insegura que debe proporcionarse para los búferes fijos. Entiendo que esto se implementa usando punteros y por lo tanto inseguro.

Mi pregunta es por qué tiene que ser inseguro? ¿Por qué no puede C# proporcionar matrices de longitud constante arbitraria y mantenerlas como un tipo de valor en lugar de hacerlo una matriz de tipo de referencia C# o memorias intermedias inseguras?

Respuesta

13

Porque un "buffer fijo" no es una matriz real. Es un tipo de valor personalizado, sobre la única forma de generar uno en el lenguaje C# que conozco. No hay forma de que CLR verifique que la indexación de la matriz se realice de forma segura. El código tampoco es verificable. La demostración más gráfica de esto:

using System; 

class Program { 
    static unsafe void Main(string[] args) { 
     var buf = new Buffer72(); 
     Console.WriteLine(buf.bs[8]); 
     Console.ReadLine(); 
    } 
} 
public struct Buffer72 { 
    public unsafe fixed byte bs[7]; 
} 

Puede acceder arbitrariamente al marco de pila en este ejemplo. La técnica estándar de inyección de desbordamiento de búfer estaría disponible para el código malicioso para parchear la dirección de retorno de la función y obligar a su código a saltar a una ubicación arbitraria.

Sí, eso es bastante inseguro.

+11

¿El problema es simplemente que CIL no tiene ningún medio para realizar operaciones indexadas? No veo ninguna razón semántica por la cual CIL no pudo proporcionar esa característica. Algunas cosas, como las transformaciones gráficas, pueden estar un poco por encima del tamaño "ideal" de 16 bytes de una estructura, pero lógicamente deberían tener una semántica de valores mutables. La semántica inmutable hace que sea doloroso ajustar un valor dentro de una instancia, y la semántica de referencia mutable introduce ambigüedades en cuanto a cuándo, por ejemplo, una función que devuelve una instancia va a devolver una nueva instancia o una existente. – supercat

+0

No es tan simple, plantea un montón de problemas relacionados con las garantías de seguridad simultáneas. – user1496062

+1

Es una locura que no haya una forma * segura * de insertar una matriz de tamaño fijo en una estructura. Para las secciones de alto rendimiento del código, quiero usar prácticamente solo el 100% de estructuras blittables. Al menos tenemos devoluciones de ref y locales de referencia ahora. – JBeurer

Cuestiones relacionadas