Introduce hardened xsprintf/xsnprintf macros

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.
This commit is contained in:
Eugene Syromyatnikov 2018-01-05 02:18:05 +01:00 committed by Dmitry V. Levin
parent 94264b790e
commit 0b92a3c933
2 changed files with 68 additions and 0 deletions

View File

@ -327,6 +327,7 @@ strace_SOURCES = \
xlat.h \
xmalloc.c \
xmalloc.h \
xstring.h \
# end of strace_SOURCES
if USE_LIBUNWIND

67
xstring.h Normal file
View File

@ -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 */