]> granicus.if.org Git - strace/commitdiff
Introduce hardened xsprintf/xsnprintf macros
authorEugene Syromyatnikov <evgsyr@gmail.com>
Fri, 5 Jan 2018 01:18:05 +0000 (02:18 +0100)
committerDmitry V. Levin <ldv@altlinux.org>
Fri, 5 Jan 2018 12:26:47 +0000 (12:26 +0000)
Let's try to future/fool-proof code a bit by introducing variants
of sprintf/snprintf that die if an overflow (or an error) occurs.
They are deemed to be the default choice for printing to some local
string buffer where no sensible error handling is implemented.

* xstring.h: New file.
* Makefile.am (strace_SOURCES): Add it.

Makefile.am
xstring.h [new file with mode: 0644]

index 34da3372c675ef1974ad6ba22684f3b68eaac509..670046a5b651f7410f22ec4f4b4e8009c836e669 100644 (file)
@@ -327,6 +327,7 @@ strace_SOURCES =    \
        xlat.h          \
        xmalloc.c       \
        xmalloc.h       \
+       xstring.h       \
        # end of strace_SOURCES
 
 if USE_LIBUNWIND
diff --git a/xstring.h b/xstring.h
new file mode 100644 (file)
index 0000000..11f9f00
--- /dev/null
+++ b/xstring.h
@@ -0,0 +1,67 @@
+#ifndef STRACE_XSTRING_H
+#define STRACE_XSTRING_H
+
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "error_prints.h"
+#include "gcc_compat.h"
+
+/**
+ * Print to static buffer and die on (really unexpected) errors and overflows.
+ * Shouldn't be used directly; please refer to helper macros xsnprintf and
+ * xsprint instead.
+ *
+ * @param str    String buffer to print into.
+ * @param size   Size of the string buffer in bytes.
+ * @param func   Function name from which this function is called.
+ * @param argstr Stringified arguments (including format argument).
+ * @param format Format string.
+ * @param ...    Format arguments.
+ * @return       Number of characters printed, excluding terminating null byte
+ *               (the same as s(n)printf).
+ */
+static inline int ATTRIBUTE_FORMAT((printf, 5, 6))
+xsnprintf_(char *str, size_t size, const char *func, const char *argstr,
+          const char *format, ...)
+{
+       int ret;
+       va_list ap;
+
+       va_start(ap, format);
+       ret = vsnprintf(str, size, format, ap);
+       va_end(ap);
+
+       if (ret < 0 || (unsigned int) ret >= size)
+               error_msg_and_die("%s: got unexpected return value %d for "
+                                 "snprintf(buf, %zu, %s)",
+                                 func, ret, size, argstr);
+
+       return ret;
+}
+
+/**
+ * snprintf that dies on (really unexpected) errors and overflows.
+ *
+ * @param str_  String buffer to print into.
+ * @param size_ Size of the string buffer in bytes.
+ * @param fmt_  Format string.
+ * @param ...   Format arguments.
+ */
+#define xsnprintf(str_, size_, fmt_, ...) \
+       xsnprintf_((str_), (size_), __func__, #fmt_ ", " #__VA_ARGS__, \
+                  (fmt_), __VA_ARGS__)
+
+/**
+ * Print to a character array buffer and die on (really unexpected) errors and
+ * overflows.  Buffer size is obtained with sizeof().
+ *
+ * @param str_  Character array buffer to print into.
+ * @param fmt_  Format string.
+ * @param ...   Format arguments.
+ */
+#define xsprintf(str_, fmt_, ...) \
+       xsnprintf((str_), sizeof(str_) + MUST_BE_ARRAY(str_), (fmt_), \
+                 __VA_ARGS__)
+
+#endif /* !STRACE_XSTRING_H */