Переполнение буфера в векторе - PullRequest
0 голосов
/ 23 марта 2020

Я пытаюсь создать программу, защищенную от переполнения буфера, и я подумывал об использовании вектора stl для этого, но я читал, что это все равно не будет выполнять проверку границ и все еще может быть взломано. В основном меня беспокоит переопределение возврата или вызова функции или другой переменной в моей программе. Будет ли вектор работать в этом случае?

1 Ответ

0 голосов
/ 23 марта 2020

Вы можете объявить вектор следующим образом:

std::vector<int> v;

Это пустой vector из int с именем v. Имеет 0 элементов. Попытка получить доступ к любому из его элементов - неопределенное поведение. Так что да, возможно создать переполнение буфера в std::vector, если вы плохо к нему относитесь.

v[0] = 1; // undefined because we're out of bounds
v[1] = 2; // as is this

Обычно при добавлении элементов к std::vector вы используете push_back или emplace_back, однако не прямой доступ к элементу

v.push_back(0);    // v is now 1 element long: { 0 }
v.emplace_back(1); // v is now 2 elements long: { 0 , 1 }

Использование оператора [] дает ссылку на базовый элемент, поэтому вы можете использовать его как для поиска, так и для назначения, если как вы уверены, что индекс действителен. Вы можете использовать функцию size(), чтобы определить соответствующий индекс максимального элемента (это size() - 1)

for (std::size_t i = 0; i < v.size(); ++i)
{
    v[i] = 10;
}
// v was size 2, we've replaced both elements at 0 and 1 with value 10

При использовании std::vector используйте предоставленный вам интерфейс. Используйте push_back или emplace_back или insert для добавления элементов. pop_back или erase для удаления элементов. A std::vector знает его begin и end, поэтому вы можете выполнить итерацию по нему следующим образом:

// prints the elements in the vector
for (auto it = v.begin(); it != v.end(); ++it)
   std::cout << *it << " ";
std::cout << "\n";

или на основе ранжирования для l oop, поскольку он обеспечивает begin() и end() функции

// prints the elements in the vector
for (const auto& elem : v)
    std::cout << elem << " ";
std::cout << "\n";

Возможно переполнение буфера std::vector, но очень маловероятно, если вы будете следовать правилам. std::vector лучше, чем массив, поэтому, если вы не возражаете против ваших элементов, существующих в бесплатном хранилище (которое является большинством не высокопроизводительных приложений), go для него. Простота использования и гибкость оправдывают дополнительные издержки.

Более того, поскольку данные в вашем std::vector НЕ существуют в стеке (в то время как локальный массив помещается в стек), вы очень вряд ли перезапишет ваш стек, если вы переполните свой std::vector. Если вам повезет, ваша программа обработает sh, но не полагайтесь на это.

В заключение, std::vector может иметь переполнение буфера, но его интерфейс делает его очень трудным для выполнения так. Если вы когда-нибудь переполните его буфер, вы перезаписываете данные в бесплатном хранилище, а не в стеке, поэтому вы не будете изменять свой обратный адрес. Несмотря на то, что второй элемент в бесплатном хранилище потенциально может быть перезаписан переполнением буфера vector, я считаю, что это не является детерминированным c. Хотя любой, у кого есть доступ к вашему исходному коду с массивом, может легко определить, какой ввод приведет к перезаписи стека, если таковой имеется.

См. https://en.cppreference.com/w/cpp/container/vector для получения дополнительной информации об интерфейсе std::vector .

...