Adding adoc files & several conversion errors fixed
This commit is contained in:
parent
e836ecfd7c
commit
372438de0a
35 changed files with 5959 additions and 0 deletions
288
en-US/C-Libc.adoc
Normal file
288
en-US/C-Libc.adoc
Normal file
|
@ -0,0 +1,288 @@
|
|||
|
||||
:experimental:
|
||||
include::entities.adoc[]
|
||||
|
||||
[[sect-Defensive_Coding-C-Libc]]
|
||||
==== The C Standard Library
|
||||
|
||||
Parts of the C standard library (and the UNIX and GNU extensions)
|
||||
are difficult to use, so you should avoid them.
|
||||
|
||||
Please check the applicable documentation before using the
|
||||
recommended replacements. Many of these functions allocate
|
||||
buffers using `malloc` which your code must
|
||||
deallocate explicitly using `free`.
|
||||
|
||||
[[sect-Defensive_Coding-C-Absolutely-Banned]]
|
||||
===== Absolutely Banned Interfaces
|
||||
|
||||
The functions listed below must not be used because they are
|
||||
almost always unsafe. Use the indicated replacements instead.
|
||||
|
||||
* `gets`
|
||||
⟶ `fgets`
|
||||
|
||||
* `getwd`
|
||||
⟶ `getcwd`
|
||||
or `get_current_dir_name`
|
||||
|
||||
* `readdir_r` ⟶ `readdir`
|
||||
|
||||
* `realpath` (with a non-NULL second parameter)
|
||||
⟶ `realpath` with NULL as the second parameter,
|
||||
or `canonicalize_file_name`
|
||||
|
||||
The constants listed below must not be used, either. Instead,
|
||||
code must allocate memory dynamically and use interfaces with
|
||||
length checking.
|
||||
|
||||
* `NAME_MAX` (limit not actually enforced by
|
||||
the kernel)
|
||||
|
||||
* `PATH_MAX` (limit not actually enforced by
|
||||
the kernel)
|
||||
|
||||
* `_PC_NAME_MAX` (This limit, returned by the
|
||||
`pathconf` function, is not enforced by
|
||||
the kernel.)
|
||||
|
||||
* `_PC_PATH_MAX` (This limit, returned by the
|
||||
`pathconf` function, is not enforced by
|
||||
the kernel.)
|
||||
|
||||
The following structure members must not be used.
|
||||
|
||||
* `f_namemax` in `struct
|
||||
statvfs` (limit not actually enforced by the kernel,
|
||||
see `_PC_NAME_MAX` above)
|
||||
|
||||
[[sect-Defensive_Coding-C-Avoid]]
|
||||
===== Functions to Avoid
|
||||
|
||||
The following string manipulation functions can be used securely
|
||||
in principle, but their use should be avoided because they are
|
||||
difficult to use correctly. Calls to these functions can be
|
||||
replaced with `asprintf` or
|
||||
`vasprintf`. (For non-GNU targets, these
|
||||
functions are available from Gnulib.) In some cases, the
|
||||
`snprintf` function might be a suitable
|
||||
replacement, see <<sect-Defensive_Coding-C-String-Functions-Length>>.
|
||||
|
||||
* `sprintf`
|
||||
|
||||
* `strcat`
|
||||
|
||||
* `strcpy`
|
||||
|
||||
* `vsprintf`
|
||||
|
||||
Use the indicated replacements for the functions below.
|
||||
|
||||
* `alloca` ⟶
|
||||
`malloc` and `free`
|
||||
(see <<sect-Defensive_Coding-C-Allocators-alloca>>)
|
||||
|
||||
* `putenv` ⟶
|
||||
explicit `envp` argument in process creation
|
||||
(see <<sect-Defensive_Coding-Tasks-Processes-environ>>)
|
||||
|
||||
* `setenv` ⟶
|
||||
explicit `envp` argument in process creation
|
||||
(see <<sect-Defensive_Coding-Tasks-Processes-environ>>)
|
||||
|
||||
* `strdupa` ⟶
|
||||
`strdup` and `free`
|
||||
(see <<sect-Defensive_Coding-C-Allocators-alloca>>)
|
||||
|
||||
* `strndupa` ⟶
|
||||
`strndup` and `free`
|
||||
(see <<sect-Defensive_Coding-C-Allocators-alloca>>)
|
||||
|
||||
* `system` ⟶
|
||||
`posix_spawn`
|
||||
or `fork`pass:attributes[{blank}]/pass:attributes[{blank}]`execve`pass:attributes[{blank}]/
|
||||
(see <<sect-Defensive_Coding-Tasks-Processes-execve>>)
|
||||
|
||||
* `unsetenv` ⟶
|
||||
explicit `envp` argument in process creation
|
||||
(see <<sect-Defensive_Coding-Tasks-Processes-environ>>)
|
||||
|
||||
[[sect-Defensive_Coding-C-String-Functions-Length]]
|
||||
===== String Functions with Explicit Length Arguments
|
||||
|
||||
The C run-time library provides string manipulation functions
|
||||
which not just look for NUL characters for string termination,
|
||||
but also honor explicit lengths provided by the caller.
|
||||
However, these functions evolved over a long period of time, and
|
||||
the lengths mean different things depending on the function.
|
||||
|
||||
[[sect-Defensive_Coding-C-Libc-snprintf]]
|
||||
====== `snprintf`
|
||||
|
||||
The `snprintf` function provides a way to
|
||||
construct a string in a statically-sized buffer. (If the buffer
|
||||
size is allocated on the heap, consider use
|
||||
`asprintf` instead.)
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-snprintf.xml"
|
||||
|
||||
----
|
||||
|
||||
The second argument to the `snprintf` call
|
||||
should always be the size of the buffer in the first argument
|
||||
(which should be a character array). Elaborate pointer and
|
||||
length arithmetic can introduce errors and nullify the
|
||||
security benefits of `snprintf`.
|
||||
|
||||
In particular, `snprintf` is not well-suited
|
||||
to constructing a string iteratively, by appending to an
|
||||
existing buffer. `snprintf` returns one of
|
||||
two values, `-1` on errors, or the number of
|
||||
characters which *would have been written to the
|
||||
buffer if the buffer were large enough*. This means
|
||||
that adding the result of `snprintf` to the
|
||||
buffer pointer to skip over the characters just written is
|
||||
incorrect and risky. However, as long as the length argument
|
||||
is not zero, the buffer will remain null-terminated. <<ex-Defensive_Coding-C-String-Functions-snprintf-incremental>>
|
||||
works because `end -current > 0` is a loop
|
||||
invariant. After the loop, the result string is in the
|
||||
`buf` variable.
|
||||
|
||||
[[ex-Defensive_Coding-C-String-Functions-snprintf-incremental]]
|
||||
.Repeatedly writing to a buffer using `snprintf`
|
||||
====
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-snprintf-incremental.xml"
|
||||
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
If you want to avoid the call to `strlen`
|
||||
for performance reasons, you have to check for a negative
|
||||
return value from `snprintf` and also check
|
||||
if the return value is equal to the specified buffer length or
|
||||
larger. Only if neither condition applies, you may advance
|
||||
the pointer to the start of the write buffer by the number
|
||||
return by `snprintf`. However, this
|
||||
optimization is rarely worthwhile.
|
||||
|
||||
Note that it is not permitted to use the same buffer both as
|
||||
the destination and as a source argument.
|
||||
|
||||
[[sect-Defensive_Coding-C-Libc-vsnprintf]]
|
||||
====== `vsnprintf` and Format Strings
|
||||
|
||||
If you use `vsnprintf` (or
|
||||
`vasprintf` or even
|
||||
`snprintf`) with a format string which is
|
||||
not a constant, but a function argument, it is important to
|
||||
annotate the function with a `format`
|
||||
function attribute, so that GCC can warn about misuse of your
|
||||
function (see <<ex-Defensive_Coding-C-String-Functions-format-Attribute>>).
|
||||
|
||||
[[ex-Defensive_Coding-C-String-Functions-format-Attribute]]
|
||||
.The `format` function attribute
|
||||
====
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-format.xml"
|
||||
|
||||
----
|
||||
|
||||
====
|
||||
|
||||
[[sect-Defensive_Coding-C-Libc-strncpy]]
|
||||
====== `strncpy`
|
||||
|
||||
The `strncpy` function does not ensure that
|
||||
the target buffer is null-terminated. A common idiom for
|
||||
ensuring NUL termination is:
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-strncpy.xml"
|
||||
|
||||
----
|
||||
|
||||
Another approach uses the `strncat`
|
||||
function for this purpose:
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-strncat-as-strncpy.xml"
|
||||
|
||||
----
|
||||
|
||||
[[sect-Defensive_Coding-C-Libc-strncat]]
|
||||
====== `strncat`
|
||||
|
||||
The length argument of the `strncat`
|
||||
function specifies the maximum number of characters copied
|
||||
from the source buffer, excluding the terminating NUL
|
||||
character. This means that the required number of bytes in
|
||||
the destination buffer is the length of the original string,
|
||||
plus the length argument in the `strncat`
|
||||
call, plus one. Consequently, this function is rarely
|
||||
appropriate for performing a length-checked string operation,
|
||||
with the notable exception of the `strcpy`
|
||||
emulation described in <<sect-Defensive_Coding-C-Libc-strncpy>>.
|
||||
|
||||
To implement a length-checked string append, you can use an
|
||||
approach similar to <<ex-Defensive_Coding-C-String-Functions-snprintf-incremental>>:
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-strncat-emulation.xml"
|
||||
|
||||
----
|
||||
|
||||
In many cases, including this one, the string concatenation
|
||||
can be avoided by combining everything into a single format
|
||||
string:
|
||||
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ include "snippets/C-String-Functions-strncat-merged.xml"
|
||||
|
||||
----
|
||||
|
||||
But you should must not dynamically construct format strings
|
||||
to avoid concatenation because this would prevent GCC from
|
||||
type-checking the argument lists.
|
||||
|
||||
It is not possible to use format strings like
|
||||
`"%s%s"` to implement concatenation, unless
|
||||
you use separate buffers. `snprintf` does
|
||||
not support overlapping source and target strings.
|
||||
|
||||
====== `strlcpy` and
|
||||
`strlcat`
|
||||
|
||||
Some systems support `strlcpy` and
|
||||
`strlcat` functions which behave this way,
|
||||
but these functions are not part of GNU libc.
|
||||
`strlcpy` is often replaced with
|
||||
`snprintf` with a `"%s"`
|
||||
format string. See <<sect-Defensive_Coding-C-Libc-strncpy>> for a caveat
|
||||
related to the `snprintf` return value.
|
||||
|
||||
To emulate `strlcat`, use the approach
|
||||
described in <<sect-Defensive_Coding-C-Libc-strncat>>.
|
||||
|
||||
====== ISO C11 Annex K *pass:attributes[{blank}]`_s` functions
|
||||
|
||||
ISO C11 adds another set of length-checking functions, but GNU
|
||||
libc currently does not implement them.
|
||||
|
||||
====== Other `strn`pass:attributes[{blank}]* and
|
||||
`stpn`pass:attributes[{blank}]* functions
|
||||
|
||||
GNU libc contains additional functions with different variants
|
||||
of length checking. Consult the documentation before using
|
||||
them to find out what the length actually means.
|
Loading…
Add table
Add a link
Reference in a new issue