log: fix repeated invocation of vsnprintf()/vaprintf() in log_struct()
https://bugs.freedesktop.org/show_bug.cgi?id=55213
This commit is contained in:
parent
1920e37ef9
commit
963ddb917d
|
@ -1307,6 +1307,12 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
if (arg_user) {
|
if (arg_user) {
|
||||||
|
|
||||||
|
/* Note that this resolves user names
|
||||||
|
* inside the container, and hence
|
||||||
|
* accesses the NSS modules from the
|
||||||
|
* container and not the host. This is
|
||||||
|
* a bit weird... */
|
||||||
|
|
||||||
if (get_user_creds((const char**)&arg_user, &uid, &gid, &home, NULL) < 0) {
|
if (get_user_creds((const char**)&arg_user, &uid, &gid, &home, NULL) < 0) {
|
||||||
log_error("get_user_creds() failed: %m");
|
log_error("get_user_creds() failed: %m");
|
||||||
goto child_fail;
|
goto child_fail;
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <printf.h>
|
||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
@ -705,11 +706,23 @@ int log_struct_internal(
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
while (format && n + 1 < ELEMENTSOF(iovec)) {
|
while (format && n + 1 < ELEMENTSOF(iovec)) {
|
||||||
char *buf;
|
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;
|
r = -ENOMEM;
|
||||||
goto finish;
|
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);
|
IOVEC_SET_STRING(iovec[n++], buf);
|
||||||
|
|
||||||
|
@ -742,8 +755,11 @@ int log_struct_internal(
|
||||||
|
|
||||||
va_start(ap, format);
|
va_start(ap, format);
|
||||||
while (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);
|
char_array_0(buf);
|
||||||
|
|
||||||
if (startswith(buf, "MESSAGE=")) {
|
if (startswith(buf, "MESSAGE=")) {
|
||||||
|
@ -751,6 +767,8 @@ int log_struct_internal(
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VA_FORMAT_ADVANCE(format, ap);
|
||||||
|
|
||||||
format = va_arg(ap, char *);
|
format = va_arg(ap, char *);
|
||||||
}
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
|
@ -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_closedir_ __attribute__((cleanup(closedirp)))
|
||||||
#define _cleanup_umask_ __attribute__((cleanup(umaskp)))
|
#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"
|
#include "log.h"
|
||||||
|
|
|
@ -42,5 +42,12 @@ int main(int argc, char* argv[]) {
|
||||||
"SERVICE=foobar",
|
"SERVICE=foobar",
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
log_struct(LOG_INFO,
|
||||||
|
"MESSAGE=Foobar PID=%lu", (unsigned long) getpid(),
|
||||||
|
"FORMAT_STR_TEST=1=%i A=%c 2=%hi 3=%li 4=%lli 1=%p foo=%s 2.5=%g 3.5=%g 4.5=%Lg",
|
||||||
|
(int) 1, 'A', (short) 2, (long int) 3, (long long int) 4, (void*) 1, "foo", (float) 2.5f, (double) 3.5, (long double) 4.5,
|
||||||
|
"SUFFIX=GOT IT",
|
||||||
|
NULL);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue