I often criticize memory-insecure languages, mainly C and C ++, and how they provoke an extraordinary number of security vulnerabilities. My summary, based on examining evidence from numerous large C and C ++ programming projects, is that we need to migrate our industry to the default memory-safe languages (such as Rust and Swift). One of the answers that I often get is that the problem is not in C and C ++ themselves, the developers simply "prepare" them incorrectly. In particular, I often get an answer in defense of C ++ like: "C ++ is safe if you do not use functionality inherited from C" [1] or similar to it, that if you use the types and idioms of modern C ++, then you will be insured against vulnerabilities such as damage memories that other projects suffer from.
I would like to give credit to C ++ smart pointers because they help a lot. Unfortunately, my experience of working on large C ++ projects using modern idioms is that it is not even close enough to stop the influx of vulnerabilities. My goal for the remainder of this post is to highlight a number of completely modern C ++ idioms that introduce vulnerabilities.
Hidden link and use-after-free
#include <iostream>
#include <string>
#include <string_view>
int main() {
std::string s = "Hellooooooooooooooo ";
std::string_view sv = s + "World\n";
std::cout << sv;
}
, s + "World\n"
std::string
, std::string_view
. std::string , sv
, . sv
use-after-free . ! ++ , , sv
-, , . std::span
, ++.
++ :
#include <memory>
#include <iostream>
#include <functional>
std::function<int(void)> f(std::shared_ptr<int> x) {
return [&]() { return *x; };
}
int main() {
std::function<int(void)> y(nullptr);
{
std::shared_ptr<int> x(std::make_shared<int>(4));
y = f(x);
}
std::cout << y() << std::endl;
}
[&]
f
. main
, x
, . y
. , . , , std::shared_ptr&
, .
std::optional
std::optional
, , , (, -1
nullptr
). , value()
, T
, , , optional
. , operator*
operator->
. T
, , optional
.
, , :
#include <optional>
int f() {
std::optional<int> x(std::nullopt);
return *x;
}
std::optional
nullptr
, ! nullptr
segfault ( , ). , nullopt
, . T*
, , , nullptr
.
, . / :
#include <optional>
#include <memory>
std::unique_ptr<int> f() {
std::optional<std::unique_ptr<int>> x(std::nullopt);
return std::move(*x);
}
std::span
std::span
. , ; std::span
, std::vector, std::array<uint8_t, N>
. - , span
, , .
STL, span::operator[]
. , operator[]
. std::vector
std::array
, , , at()
, ( , , , std::vector::operator[]
). span at()
, , .
, Firefox, Chromium std::span
operator[]
, , , std::span
.
C++ , : , std::span
, , std::variant
union
. C++ :
use-after-free, optional
span
.
++ Rust- ( Rust-, unsafe
) , ++ , , Rust Swift ( Python Javascript, , - Python, C++).
C C++ - . , , , , . ++, , ++.
[1] , , --, malloc/free . , , , , , ++ , ++- "".