133 lines
5.2 KiB
Text
133 lines
5.2 KiB
Text
|
|
:experimental:
|
|
|
|
[[sect-Defensive_Coding-CXX-Language]]
|
|
== The Core Language
|
|
|
|
C++ includes a large subset of the C language. As far as the C
|
|
subset is used, the recommendations in xref:../programming-languages/C.adoc#chap-Defensive_Coding-C[Defensive Coding in C] apply.
|
|
|
|
=== Array Allocation with `operator new[]`
|
|
|
|
For very large values of `n`, an expression
|
|
like `new T[n]` can return a pointer to a heap
|
|
region which is too small. In other words, not all array
|
|
elements are actually backed with heap memory reserved to the
|
|
array. Current GCC versions generate code that performs a
|
|
computation of the form `sizeof(T) * size_t(n) +
|
|
cookie_size`, where `cookie_size` is
|
|
currently at most 8. This computation can overflow, and GCC
|
|
versions prior to 4.8 generated code which did not detect this.
|
|
(Fedora 18 was the first release which fixed this in GCC.)
|
|
|
|
The `std::vector` template can be used instead
|
|
an explicit array allocation. (The GCC implementation detects
|
|
overflow internally.)
|
|
|
|
If there is no alternative to `operator new[]`
|
|
and the sources will be compiled with older GCC versions, code
|
|
which allocates arrays with a variable length must check for
|
|
overflow manually. For the `new T[n]` example,
|
|
the size check could be `n || (n > 0 && n >
|
|
(size_t(-1) - 8) / sizeof(T))`. (See xref:../programming-languages/C-Language.adoc#sect-Defensive_Coding-C-Arithmetic[Recommendations for Integer Arithmetic]) If there are
|
|
additional dimensions (which must be constants according to the
|
|
{cpp} standard), these should be included as factors in the
|
|
divisor.
|
|
|
|
These countermeasures prevent out-of-bounds writes and potential
|
|
code execution. Very large memory allocations can still lead to
|
|
a denial of service. xref:../tasks/Tasks-Serialization.adoc#sect-Defensive_Coding-Tasks-Serialization-Decoders[Recommendations for Manually-written Decoders]
|
|
contains suggestions for mitigating this problem when processing
|
|
untrusted data.
|
|
|
|
See xref:../tasks/programming-languages/C-Allocators.adoc#sect-Defensive_Coding-C-Allocators-Arrays[Array Allocation]
|
|
for array allocation advice for C-style memory allocation.
|
|
|
|
=== Overloading
|
|
|
|
Do not overload functions with versions that have different
|
|
security characteristics. For instance, do not implement a
|
|
function `strcat` which works on
|
|
`std::string` arguments. Similarly, do not name
|
|
methods after such functions.
|
|
|
|
=== ABI compatibility and preparing for security updates
|
|
|
|
A stable binary interface (ABI) is vastly preferred for security
|
|
updates. Without a stable ABI, all reverse dependencies need
|
|
recompiling, which can be a lot of work and could even be
|
|
impossible in some cases. Ideally, a security update only
|
|
updates a single dynamic shared object, and is picked up
|
|
automatically after restarting affected processes.
|
|
|
|
Outside of extremely performance-critical code, you should
|
|
ensure that a wide range of changes is possible without breaking
|
|
ABI. Some very basic guidelines are:
|
|
|
|
* Avoid inline functions.
|
|
|
|
* Use the pointer-to-implementation idiom.
|
|
|
|
* Try to avoid templates. Use them if the increased type
|
|
safety provides a benefit to the programmer.
|
|
|
|
* Move security-critical code out of templated code, so that
|
|
it can be patched in a central place if necessary.
|
|
|
|
The KDE project publishes a document with more extensive
|
|
guidelines on ABI-preserving changes to {cpp} code, link:++https://community.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B++[Policies/Binary
|
|
Compatibility Issues With {cpp}]
|
|
(*d-pointer* refers to the
|
|
pointer-to-implementation idiom).
|
|
|
|
[[sect-Defensive_Coding-CXX-Language-CXX11]]
|
|
=== {cpp}0X and {cpp}11 Support
|
|
|
|
GCC offers different language compatibility modes:
|
|
|
|
* [option]`-std=c++98` for the original 1998 {cpp}
|
|
standard
|
|
|
|
* [option]`-std=c++03` for the 1998 standard with the
|
|
changes from the TR1 technical report
|
|
|
|
* [option]`-std=c++11` for the 2011 {cpp} standard. This
|
|
option should not be used.
|
|
|
|
* [option]`-std=c++0x` for several different versions
|
|
of {cpp}11 support in development, depending on the GCC
|
|
version. This option should not be used.
|
|
|
|
For each of these flags, there are variants which also enable
|
|
GNU extensions (mostly language features also found in C99 or
|
|
C11):
|
|
|
|
* [option]`-std=gnu++98`
|
|
* [option]`-std=gnu++03`
|
|
* [option]`-std=gnu++11`
|
|
|
|
Again, [option]`-std=gnu++11` should not be used.
|
|
|
|
If you enable {cpp}11 support, the ABI of the standard {cpp} library
|
|
`libstdc++` will change in subtle ways.
|
|
Currently, no {cpp} libraries are compiled in {cpp}11 mode, so if
|
|
you compile your code in {cpp}11 mode, it will be incompatible
|
|
with the rest of the system. Unfortunately, this is also the
|
|
case if you do not use any {cpp}11 features. Currently, there is
|
|
no safe way to enable {cpp}11 mode (except for freestanding
|
|
applications).
|
|
|
|
The meaning of {cpp}0X mode changed from GCC release to GCC
|
|
release. Earlier versions were still ABI-compatible with {cpp}98
|
|
mode, but in the most recent versions, switching to {cpp}0X mode
|
|
activates {cpp}11 support, with its compatibility problems.
|
|
|
|
Some {cpp}11 features (or approximations thereof) are available
|
|
with TR1 support, that is, with [option]`-std=c++03` or
|
|
[option]`-std=gnu++03` and in the
|
|
`<tr1/*>` header files. This includes
|
|
`std::tr1::shared_ptr` (from
|
|
`<tr1/memory>`) and
|
|
`std::tr1::function` (from
|
|
`<tr1/functional>`). For other {cpp}11
|
|
features, the Boost {cpp} library contains replacements.
|