352 lines
14 KiB
XML
352 lines
14 KiB
XML
<?xml version='1.0' encoding='utf-8' ?>
|
|
<!DOCTYPE section PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
|
|
]>
|
|
<section id="sect-Defensive_Coding-C-Libc">
|
|
<title>The C standard library</title>
|
|
<para>
|
|
Parts of the C standard library (and the UNIX and GNU extensions)
|
|
are difficult to use, so you shoud avoid them.
|
|
</para>
|
|
<para>
|
|
Please check the applicable documentation before using the
|
|
recommended replacements. Many of these functions allocate
|
|
buffers using <function>malloc</function> which your code must
|
|
deallocate explicitly using <function>free</function>.
|
|
</para>
|
|
<section id="sect-Defensive_Coding-C-Absolutely-Banned">
|
|
<title>Absolutely banned interfaces</title>
|
|
<para>
|
|
The functions listed below must not be used because they are
|
|
almost always unsafe. Use the indicated replacements instead.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem><para><function>gets</function>
|
|
⟶ <function>fgets</function></para></listitem>
|
|
<listitem><para><function>getwd</function>
|
|
⟶ <function>getcwd</function>
|
|
or <function>get_current_dir_name</function></para></listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>readdir_r</function> ⟶ <function>readdir</function>
|
|
<!-- It is quite complicated to allocate a properly-sized
|
|
buffer for use with readdir_r, and readdir provides
|
|
sufficient thread safety guarantees. -->
|
|
<!-- ??? Add File_System cross-reference -->
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>realpath</function> (with a non-NULL second parameter)
|
|
⟶ <function>realpath</function> with NULL as the second parameter,
|
|
or <function>canonicalize_file_name</function>
|
|
<!-- It is complicated to allocate a properly-sized buffer
|
|
for use with realpath. -->
|
|
<!-- ??? Add File_System cross-reference -->
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
The constants listed below must not be used, either. Instead,
|
|
code must allocate memory dynamically and use interfaces with
|
|
length checking.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>NAME_MAX</literal> (limit not actually enforced by
|
|
the kernel)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>PATH_MAX</literal> (limit not actually enforced by
|
|
the kernel)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>_PC_NAME_MAX</literal> (This limit, returned by the
|
|
<function>pathconf</function> function, is not enforced by
|
|
the kernel.)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<literal>_PC_PATH_MAX</literal> (This limit, returned by the
|
|
<function>pathconf</function> function, is not enforced by
|
|
the kernel.)
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
The following structure members must not be used.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<literal>f_namemax</literal> in <literal>struct
|
|
statvfs</literal> (limit not actually enforced by the kernel,
|
|
see <literal>_PC_NAME_MAX</literal> above)
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section id="sect-Defensive_Coding-C-Avoid">
|
|
<title>Functions to avoid</title>
|
|
<para>
|
|
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 <function>asprintf</function> or
|
|
<function>vasprintf</function>. (For non-GNU targets, these
|
|
functions are available from Gnulib.) In some cases, the
|
|
<function>snprintf</function> function might be a suitable
|
|
replacement, see <xref
|
|
linkend="sect-Defensive_Coding-C-String-Functions-Length"/>.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem><para><function>sprintf</function></para></listitem>
|
|
<listitem><para><function>strcat</function></para></listitem>
|
|
<listitem><para><function>strcpy</function></para></listitem>
|
|
<listitem><para><function>vsprintf</function></para></listitem>
|
|
</itemizedlist>
|
|
<para>
|
|
Use the indicated replacements for the functions below.
|
|
</para>
|
|
<itemizedlist>
|
|
<listitem>
|
|
<para>
|
|
<function>alloca</function> ⟶
|
|
<function>malloc</function> and <function>free</function>
|
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>putenv</function> ⟶
|
|
explicit <varname>envp</varname> argument in process creation
|
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>setenv</function> ⟶
|
|
explicit <varname>envp</varname> argument in process creation
|
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>strdupa</function> ⟶
|
|
<function>strdup</function> and <function>free</function>
|
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>strndupa</function> ⟶
|
|
<function>strndup</function> and <function>free</function>
|
|
(see <xref linkend="sect-Defensive_Coding-C-Allocators-alloca"/>)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>system</function> ⟶
|
|
<function>posix_spawn</function>
|
|
or <function>fork</function>/<function>execve</function>/
|
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-execve"/>)
|
|
</para>
|
|
</listitem>
|
|
<listitem>
|
|
<para>
|
|
<function>unsetenv</function> ⟶
|
|
explicit <varname>envp</varname> argument in process creation
|
|
(see <xref linkend="sect-Defensive_Coding-Tasks-Processes-environ"/>)
|
|
</para>
|
|
</listitem>
|
|
</itemizedlist>
|
|
</section>
|
|
<section id="sect-Defensive_Coding-C-String-Functions-Length">
|
|
<title>String Functions With Explicit Length Arguments</title>
|
|
<para>
|
|
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.
|
|
</para>
|
|
<section id="sect-Defensive_Coding-C-Libc-snprintf">
|
|
<title><literal>snprintf</literal></title>
|
|
<para>
|
|
The <function>snprintf</function> function provides a way to
|
|
construct a string in a statically-sized buffer. (If the buffer
|
|
size is allocated on the heap, consider use
|
|
<function>asprintf</function> instead.)
|
|
</para>
|
|
<informalexample>
|
|
<xi:include href="snippets/C-String-Functions-snprintf.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</informalexample>
|
|
<para>
|
|
The second argument to the <function>snprintf</function> 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 <function>snprintf</function>.
|
|
</para>
|
|
<para>
|
|
In particular, <literal>snprintf</literal> is not well-suited
|
|
to constructing a string iteratively, by appending to an
|
|
existing buffer. <function>snprintf</function> returns one of
|
|
two values, <literal>-1</literal> on errors, or the number of
|
|
characters which <emphasis>would have been written to the
|
|
buffer if the buffer were large enough</emphasis>. This means
|
|
that adding the result of <function>snprintf</function> 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 NUL-terminated. <xref
|
|
linkend="ex-Defensive_Coding-C-String-Functions-snprintf-incremental"/>
|
|
works because <literal>end -current > 0</literal> is a loop
|
|
invariant. After the loop, the result string is in the
|
|
<varname>buf</varname> variable.
|
|
</para>
|
|
<example id="ex-Defensive_Coding-C-String-Functions-snprintf-incremental">
|
|
<title>Repeatedly writing to a buffer using <function>snprintf</function></title>
|
|
<xi:include href="snippets/C-String-Functions-snprintf-incremental.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</example>
|
|
<para>
|
|
If you want to avoid the call to <function>strlen</function>
|
|
for performance reasons, you have to check for a negative
|
|
return value from <function>snprintf</function> 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 <function>snprintf</function>. However, this
|
|
optimization is rarely worthwhile.
|
|
</para>
|
|
<para>
|
|
Note that it is not permitted to use the same buffer both as
|
|
the destination and as a source argument.
|
|
</para>
|
|
</section>
|
|
<section id="sect-Defensive_Coding-C-Libc-vsnprintf">
|
|
<title><literal>vsnprintf</literal> and format strings</title>
|
|
<para>
|
|
If you use <function>vsnprintf</function> (or
|
|
<function>vasprintf</function> or even
|
|
<function>snprintf</function>) with a format string which is
|
|
not a constant, but a function argument, it is important to
|
|
annotate the function with a <literal>format</literal>
|
|
function attribute, so that GCC can warn about misuse of your
|
|
function (see <xref
|
|
linkend="ex-Defensive_Coding-C-String-Functions-format-Attribute"/>).
|
|
</para>
|
|
<example id="ex-Defensive_Coding-C-String-Functions-format-Attribute">
|
|
<title>The <literal>format</literal> function attribute</title>
|
|
<xi:include href="snippets/C-String-Functions-format.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</example>
|
|
</section>
|
|
<section id="sect-Defensive_Coding-C-Libc-strncpy">
|
|
<title><function>strncpy</function></title>
|
|
<para>
|
|
The <function>strncpy</function> function does not ensure that
|
|
the target buffer is NUL-terminated. A common idiom for
|
|
ensuring NUL termination is:
|
|
</para>
|
|
<informalexample>
|
|
<xi:include href="snippets/C-String-Functions-strncpy.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</informalexample>
|
|
<para>
|
|
Another approach uses the <function>strncat</function>
|
|
function for this purpose:
|
|
</para>
|
|
<informalexample>
|
|
<xi:include href="snippets/C-String-Functions-strncat-as-strncpy.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</informalexample>
|
|
</section>
|
|
<section id="sect-Defensive_Coding-C-Libc-strncat">
|
|
<title><function>strncat</function></title>
|
|
<para>
|
|
The length argument of the <function>strncat</function>
|
|
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 <function>strncat</function>
|
|
call, plus one. Consequently, this function is rarely
|
|
appropriate for performing a length-checked string operation,
|
|
with the notable exception of the <function>strcpy</function>
|
|
emulation described in <xref
|
|
linkend="sect-Defensive_Coding-C-Libc-strncpy"/>.
|
|
</para>
|
|
<para>
|
|
To implement a length-checked string append, you can use an
|
|
approach similar to <xref
|
|
linkend="ex-Defensive_Coding-C-String-Functions-snprintf-incremental"/>:
|
|
</para>
|
|
<informalexample>
|
|
<xi:include href="snippets/C-String-Functions-strncat-emulation.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</informalexample>
|
|
<para>
|
|
In many cases, including this one, the string concatenation
|
|
can be avoided by combining everything into a single format
|
|
string:
|
|
</para>
|
|
<informalexample>
|
|
<xi:include href="snippets/C-String-Functions-strncat-merged.xml"
|
|
xmlns:xi="http://www.w3.org/2001/XInclude" />
|
|
</informalexample>
|
|
<para>
|
|
But you should must not dynamically construct format strings
|
|
to avoid concatenation because this would prevent GCC from
|
|
type-checking the argument lists.
|
|
</para>
|
|
<para>
|
|
It is not possible to use format strings like
|
|
<literal>"%s%s"</literal> to implement concatenation, unless
|
|
you use separate buffers. <function>snprintf</function> does
|
|
not support overlapping source and target strings.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title><function>strlcpy</function> and
|
|
<function>strlcat</function></title>
|
|
<para>
|
|
Some systems support <function>strlcpy</function> and
|
|
<function>strlcat</function> functions which behave this way,
|
|
but these functions are not part of GNU libc.
|
|
<function>strlcpy</function> is often replaced with
|
|
<function>snprintf</function> with a <literal>"%s"</literal>
|
|
format string. See <xref
|
|
linkend="sect-Defensive_Coding-C-Libc-strncpy"/> for a caveat
|
|
related to the <function>snprintf</function> return value.
|
|
</para>
|
|
<para>
|
|
To emulate <function>strlcat</function>, use the approach
|
|
described in <xref
|
|
linkend="sect-Defensive_Coding-C-Libc-strncat"/>.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>ISO C11 Annex K *<function>_s</function> functions</title>
|
|
<para>
|
|
ISO C11 adds another set of length-checking functions, but GNU
|
|
libc currently does not implement them.
|
|
</para>
|
|
</section>
|
|
<section>
|
|
<title>Other <function>strn</function>* and
|
|
<function>stpn</function>* functions</title>
|
|
<para>
|
|
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.
|
|
</para>
|
|
</section>
|
|
</section>
|
|
</section>
|