log: fix repeated invocation of vsnprintf()/vaprintf() in log_struct()

https://bugs.freedesktop.org/show_bug.cgi?id=55213
This commit is contained in:
Lennart Poettering
2012-09-24 23:26:46 +02:00
parent 1920e37ef9
commit 963ddb917d
4 changed files with 76 additions and 2 deletions
+20 -2
View File
@@ -27,6 +27,7 @@
#include <sys/socket.h>
#include <sys/un.h>
#include <stddef.h>
#include <printf.h>
#include "log.h"
#include "util.h"
@@ -705,11 +706,23 @@ int log_struct_internal(
va_start(ap, format);
while (format && n + 1 < ELEMENTSOF(iovec)) {
char *buf;
va_list aq;
if (vasprintf(&buf, format, ap) < 0) {
/* We need to copy the va_list structure,
* since vasprintf() leaves it afterwards at
* an undefined location */
va_copy(aq, ap);
if (vasprintf(&buf, format, aq) < 0) {
va_end(aq);
r = -ENOMEM;
goto finish;
}
va_end(aq);
/* Now, jump enough ahead, so that we point to
* the next format string */
VA_FORMAT_ADVANCE(format, ap);
IOVEC_SET_STRING(iovec[n++], buf);
@@ -742,8 +755,11 @@ int log_struct_internal(
va_start(ap, format);
while (format) {
va_list aq;
vsnprintf(buf, sizeof(buf), format, ap);
va_copy(aq, ap);
vsnprintf(buf, sizeof(buf), format, aq);
va_end(aq);
char_array_0(buf);
if (startswith(buf, "MESSAGE=")) {
@@ -751,6 +767,8 @@ int log_struct_internal(
break;
}
VA_FORMAT_ADVANCE(format, ap);
format = va_arg(ap, char *);
}
va_end(ap);
+43
View File
@@ -193,4 +193,47 @@ static inline size_t IOVEC_INCREMENT(struct iovec *i, unsigned n, size_t k) {
#define _cleanup_closedir_ __attribute__((cleanup(closedirp)))
#define _cleanup_umask_ __attribute__((cleanup(umaskp)))
#define VA_FORMAT_ADVANCE(format, ap) do { \
int _argtypes[64]; \
size_t _i, _k; \
_k = parse_printf_format((format), ELEMENTSOF(_argtypes), _argtypes); \
for (_i = 0; _i < _k; _i++) { \
if (_argtypes[_i] & PA_FLAG_PTR) { \
(void) va_arg(ap, void*); \
continue; \
} \
\
switch (_argtypes[_i]) { \
case PA_INT: \
case PA_INT|PA_FLAG_SHORT: \
case PA_CHAR: \
(void) va_arg(ap, int); \
break; \
case PA_INT|PA_FLAG_LONG: \
(void) va_arg(ap, long int); \
break; \
case PA_INT|PA_FLAG_LONG_LONG: \
(void) va_arg(ap, long long int); \
break; \
case PA_WCHAR: \
(void) va_arg(ap, wchar_t); \
break; \
case PA_WSTRING: \
case PA_STRING: \
case PA_POINTER: \
(void) va_arg(ap, void*); \
break; \
case PA_FLOAT: \
case PA_DOUBLE: \
(void) va_arg(ap, double); \
break; \
case PA_DOUBLE|PA_FLAG_LONG_DOUBLE: \
(void) va_arg(ap, long double); \
break; \
default: \
assert_not_reached("Unknown format string argument."); \
} \
} \
} while(false)
#include "log.h"