2010-05-21 14 views
21

Nehmen wir an, ich möchte einen Werttyp von 7 Bytes (oder 3 oder 777) haben.Warum müssen Puffer mit fester Größe (Arrays) nicht sicher sein?

Ich kann es so definieren:

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

Eine einfachere Art und Weise zu definieren, wird einen festen Puffer

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

Natürlich ist die zweite Definition ist einfacher. Das Problem liegt bei dem unsafe-Schlüsselwort, das für feste Puffer bereitgestellt werden muss. Ich verstehe, dass dies mit Zeigern implementiert und daher unsicher ist.

Meine Frage ist, warum muss es unsicher sein? Warum kann C# keine Arrays beliebiger Konstantenlänge bereitstellen und sie als Wertetyp beibehalten, anstatt sie als C# -Referenzarray oder unsichere Puffer zu definieren?

Antwort

13

Weil ein "fester Puffer" kein echtes Array ist. Es ist ein benutzerdefinierter Werttyp, der einzige Weg, um einen in der C# -Sprache zu generieren, den ich kenne. Die CLR kann nicht überprüfen, ob die Indexierung des Arrays auf sichere Weise erfolgt. Der Code ist auch nicht verifizierbar. Die am meisten grafische Demonstration davon:

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]; 
} 

Sie können willkürlich auf den Stapelrahmen in diesem Beispiel zugreifen. Die standardmäßige Pufferüberlauf-Injektionstechnik wäre für bösartigen Code verfügbar, um die Funktionsrückgabeadresse zu patchen und Ihren Code zu zwingen, zu einem beliebigen Ort zu springen.

Ja, das ist ziemlich unsicher.

+11

Also ist das Problem einfach, dass CIL keine Mittel zur Durchführung beschränkter indizierter Operationen hat? Ich sehe keinen semantischen Grund, warum CIL solch ein Feature nicht bieten konnte. Einige Dinge wie Grafiktransformationen können ein wenig über der "idealen" 16-Byte-Größe einer Struktur liegen, aber sie sollten logisch eine Semantik mit änderbarem Wert haben. Unveränderliche Semantiken machen es schwierig, einen Wert innerhalb einer Instanz zu optimieren, und änderbare Referenzsemantiken führen zu Mehrdeutigkeiten, wenn z. Eine Funktion, die eine Instanz zurückgibt, gibt eine neue oder eine vorhandene Instanz zurück. – supercat

+0

Es ist nicht so einfach, es wirft eine ganze Reihe von Problemen auf, die mit gleichzeitigen Sicherheitsgarantien zu tun haben. – user1496062

+1

Es ist verrückt, dass es keine * sichere * Möglichkeit gibt, ein Array fester Größe in eine Struktur einzubetten. Für leistungsstarke Abschnitte des Codes möchte ich nur sehr wenige 100% blitbare Strukturen verwenden. Wenigstens haben wir jetzt ref returns und ref locals. – JBeurer

Verwandte Themen