This is an automated email from the git hooks/post-receive script.
sparks pushed a commit to branch master
in repository defensive-coding-guide.
commit 587753aceba5a4b78a624e3a3f335656f33c51e1
Author: Florian Weimer <fweimer(a)redhat.com>
Date: Thu Apr 11 17:03:40 2013 +0200
C: Expand documentation of strncpy, strncat
Also fixes the description of strncat.
---
defensive-coding/en-US/C/Libc.xml | 99 +++++++++++++++++++---
.../String-Functions-strncat-as-strncpy.xml | 8 ++
.../String-Functions-strncat-emulation.xml | 9 ++
.../C/snippets/String-Functions-strncat-merged.xml | 7 ++
defensive-coding/src/C-String-Functions.c | 19 +++++
5 files changed, 131 insertions(+), 11 deletions(-)
diff --git a/defensive-coding/en-US/C/Libc.xml b/defensive-coding/en-US/C/Libc.xml
index 1f16fee..970f5bf 100644
--- a/defensive-coding/en-US/C/Libc.xml
+++ b/defensive-coding/en-US/C/Libc.xml
@@ -249,26 +249,103 @@
</example>
</section>
<section id="sect-Defensive_Coding-C-Libc-strncpy">
- <title><function>strncpy</function> and related
functions</title>
+ <title><function>strncpy</function></title>
<para>
- There are other functions which operator on NUL-terminated
- strings and take a length argument which affects the number of
- bytes written to the destination: <function>strncpy</function>,
- <function>strncat</function>, and <function>stpncpy</function>.
- These functions do not ensure that the result string is
- NUL-terminated. For <function>strncpy</function>,
- NUL termination can be added this way:
+ 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/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/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/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/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. Using
- <function>snprintf</function> with a suitable format string is a
- simple (albeit slightly slower) replacement.
+ 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>
diff --git a/defensive-coding/en-US/C/snippets/String-Functions-strncat-as-strncpy.xml
b/defensive-coding/en-US/C/snippets/String-Functions-strncat-as-strncpy.xml
new file mode 100644
index 0000000..0895eaf
--- /dev/null
+++ b/defensive-coding/en-US/C/snippets/String-Functions-strncat-as-strncpy.xml
@@ -0,0 +1,8 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+buf[0] = '\0';
+strncpy(buf, data, sizeof(buf) - 1);
+</programlisting>
diff --git a/defensive-coding/en-US/C/snippets/String-Functions-strncat-emulation.xml
b/defensive-coding/en-US/C/snippets/String-Functions-strncat-emulation.xml
new file mode 100644
index 0000000..12f5437
--- /dev/null
+++ b/defensive-coding/en-US/C/snippets/String-Functions-strncat-emulation.xml
@@ -0,0 +1,9 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+char buf[10];
+snprintf(buf, sizeof(buf), "%s", prefix);
+snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", data);
+</programlisting>
diff --git a/defensive-coding/en-US/C/snippets/String-Functions-strncat-merged.xml
b/defensive-coding/en-US/C/snippets/String-Functions-strncat-merged.xml
new file mode 100644
index 0000000..3deaa94
--- /dev/null
+++ b/defensive-coding/en-US/C/snippets/String-Functions-strncat-merged.xml
@@ -0,0 +1,7 @@
+<?xml version='1.0' encoding='utf-8' ?>
+<!DOCTYPE programlisting PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
+]>
+<!-- Automatically generated file. Do not edit. -->
+<programlisting language="C">
+snprintf(buf, sizeof(buf), "%s%s", prefix, data);
+</programlisting>
diff --git a/defensive-coding/src/C-String-Functions.c
b/defensive-coding/src/C-String-Functions.c
index 3522eaa..34d9c31 100644
--- a/defensive-coding/src/C-String-Functions.c
+++ b/defensive-coding/src/C-String-Functions.c
@@ -68,5 +68,24 @@ main(void)
//-
assert(strlen(buf) == 9);
assert(strncmp(buf, data, 9) == 0);
+ //+ C String-Functions-strncat-as-strncpy
+ buf[0] = '\0';
+ strncpy(buf, data, sizeof(buf) - 1);
+ //-
+ }
+ {
+ const char *const prefix = "prefix";
+ const char *const data = " suffix";
+
+ //+ C String-Functions-strncat-emulation
+ char buf[10];
+ snprintf(buf, sizeof(buf), "%s", prefix);
+ snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%s", data);
+ //-
+ puts(buf);
+ //+ C String-Functions-strncat-merged
+ snprintf(buf, sizeof(buf), "%s%s", prefix, data);
+ //-
+ puts(buf);
}
}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.