Commit 30648c03 authored by Marc-André Lureau's avatar Marc-André Lureau

util: add slirp_fmt() helpers

Various calls to snprintf() in libslirp assume that snprintf() returns
"only" the number of bytes written (excluding terminating NUL).

https://pubs.opengroup.org/onlinepubs/9699919799/functions/snprintf.html#tag_16_159_04

"Upon successful completion, the snprintf() function shall return the
number of bytes that would be written to s had n been sufficiently
large excluding the terminating null byte."

Introduce slirp_fmt() that handles several pathological cases the
way libslirp usually expect:

- treat error as fatal (instead of silently returning -1)

- fmt0() will always \0 end

- return the number of bytes actually written (instead of what would
have been written, which would usually result in OOB later), including
the ending \0 for fmt0()

- warn if truncation happened (instead of ignoring)

Other less common cases can still be handled with strcpy/snprintf() etc.
Signed-off-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Reviewed-by: Samuel Thibault's avatarSamuel Thibault <samuel.thibault@ens-lyon.org>
Message-Id: <20200127092414.169796-2-marcandre.lureau@redhat.com>
parent de70cfa2
......@@ -364,3 +364,65 @@ void slirp_pstrcpy(char *buf, int buf_size, const char *str)
}
*q = '\0';
}
static int slirp_vsnprintf(char *str, size_t size,
const char *format, va_list args)
{
int rv = vsnprintf(str, size, format, args);
if (rv < 0) {
g_error("vsnprintf() failed: %s", g_strerror(errno));
}
return rv;
}
/*
* A snprintf()-like function that:
* - returns the number of bytes written (excluding optional \0-ending)
* - dies on error
* - warn on truncation
*/
int slirp_fmt(char *str, size_t size, const char *format, ...)
{
va_list args;
int rv;
va_start(args, format);
rv = slirp_vsnprintf(str, size, format, args);
va_end(args);
if (rv > size) {
g_critical("vsnprintf() truncation");
}
return MIN(rv, size);
}
/*
* A snprintf()-like function that:
* - always \0-end (unless size == 0)
* - returns the number of bytes actually written, including \0 ending
* - dies on error
* - warn on truncation
*/
int slirp_fmt0(char *str, size_t size, const char *format, ...)
{
va_list args;
int rv;
va_start(args, format);
rv = slirp_vsnprintf(str, size, format, args);
va_end(args);
if (rv >= size) {
g_critical("vsnprintf() truncation");
if (size > 0)
str[size - 1] = '\0';
rv = size;
} else {
rv += 1; /* include \0 */
}
return rv;
}
......@@ -181,4 +181,7 @@ static inline int slirp_socket_set_fast_reuse(int fd)
void slirp_pstrcpy(char *buf, int buf_size, const char *str);
int slirp_fmt(char *str, size_t size, const char *format, ...);
int slirp_fmt0(char *str, size_t size, const char *format, ...);
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment