Почему фиксированный размер буферов (массивов) должен быть небезопасным? - PullRequest
22 голосов
/ 21 мая 2010

Допустим, я хочу иметь тип значения 7 байтов (или 3 или 777).

Я могу определить это так:

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

Более простой способ определить это - использовать фиксированный буфер

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

Конечно, второе определение проще. Проблема заключается в небезопасном ключевом слове, которое должно быть предоставлено для фиксированных буферов. Я понимаю, что это реализовано с помощью указателей и, следовательно, небезопасно.

Мой вопрос: почему это должно быть небезопасно? Почему C # не может предоставлять произвольные массивы постоянной длины и сохранять их как тип значения вместо того, чтобы делать это массивом ссылочных типов C # или небезопасными буферами?

1 Ответ

12 голосов
/ 21 мая 2010

Потому что «фиксированный буфер» не является реальным массивом. Это пользовательский тип значения, единственный способ сгенерировать его на языке C #, который я знаю. У CLR нет способа проверить, что индексация массива выполнена безопасным способом. Код также не поддается проверке. Наиболее наглядная демонстрация этого:

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

В этом примере вы можете получить произвольный доступ к фрейму стека. Стандартный метод внедрения переполнения буфера будет доступен вредоносному коду для исправления адреса возврата функции и принудительного перехода вашего кода в произвольное место.

Да, это довольно небезопасно.

...