diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-02-23 03:39:42 +0100 |
---|---|---|
committer | Yu Watanabe <watanabe.yu+github@gmail.com> | 2023-02-23 07:09:59 +0100 |
commit | 5648ebaf403dd2614a7cc72e892f4d29eaca46ef (patch) | |
tree | dce9d4d771e82db9d8cd842ebed7c87916af5f89 /src | |
parent | io-util: drop double evaluation in IOVEC_INIT_STRING() (diff) | |
download | systemd-5648ebaf403dd2614a7cc72e892f4d29eaca46ef.tar.xz systemd-5648ebaf403dd2614a7cc72e892f4d29eaca46ef.zip |
sd-journal: fix memleak and freeing invalid pointers
This also makes
- use GREEDY_REALLOC() or GREEDY_REALLOC0(),
- use CLEANUP_ARRAY() macro.
Diffstat (limited to 'src')
-rw-r--r-- | src/libsystemd/sd-journal/journal-send.c | 107 |
1 files changed, 38 insertions, 69 deletions
diff --git a/src/libsystemd/sd-journal/journal-send.c b/src/libsystemd/sd-journal/journal-send.c index 00c53f6d5b..c360d0e182 100644 --- a/src/libsystemd/sd-journal/journal-send.c +++ b/src/libsystemd/sd-journal/journal-send.c @@ -148,93 +148,64 @@ _public_ int sd_journal_printv(int priority, const char *format, va_list ap) { return sd_journal_sendv(iov, 2); } -_printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, int extra, struct iovec **_iov) { +_printf_(1, 0) static int fill_iovec_sprintf(const char *format, va_list ap, size_t extra, struct iovec **ret_iov, size_t *ret_n_iov) { PROTECT_ERRNO; - int r, n = 0, i = 0, j; struct iovec *iov = NULL; + size_t n = 0; - assert(_iov); + assert(ret_iov); + assert(ret_n_iov); if (extra > 0) { - n = MAX(extra * 2, extra + 4); - iov = malloc0(n * sizeof(struct iovec)); - if (!iov) { - r = -ENOMEM; - goto fail; - } + if (!GREEDY_REALLOC0(iov, extra)) + return -ENOMEM; - i = extra; + n = extra; } + CLEANUP_ARRAY(iov, n, iovec_array_free); + while (format) { - struct iovec *c; - char *buffer; + _cleanup_free_ char *buffer = NULL; va_list aq; - if (i >= n) { - n = MAX(i*2, 4); - c = reallocarray(iov, n, sizeof(struct iovec)); - if (!c) { - r = -ENOMEM; - goto fail; - } - - iov = c; - } - va_copy(aq, ap); if (vasprintf(&buffer, format, aq) < 0) { va_end(aq); - r = -ENOMEM; - goto fail; + return -ENOMEM; } va_end(aq); VA_FORMAT_ADVANCE(format, ap); - - (void) strstrip(buffer); /* strip trailing whitespace, keep prefixing whitespace */ - - iov[i++] = IOVEC_MAKE_STRING(buffer); - format = va_arg(ap, char *); - } - - *_iov = iov; - return i; + if (!GREEDY_REALLOC(iov, n + 1)) + return -ENOMEM; -fail: - for (j = 0; j < i; j++) - free(iov[j].iov_base); - - free(iov); + /* strip trailing whitespace, keep prefixing whitespace */ + iov[n++] = IOVEC_MAKE_STRING(delete_trailing_chars(TAKE_PTR(buffer), NULL)); + } - return r; + *ret_iov = TAKE_PTR(iov); + *ret_n_iov = n; + return 0; } _public_ int sd_journal_send(const char *format, ...) { - int r, i, j; - va_list ap; struct iovec *iov = NULL; + size_t n_iov = 0; + va_list ap; + int r; + + CLEANUP_ARRAY(iov, n_iov, iovec_array_free); va_start(ap, format); - i = fill_iovec_sprintf(format, ap, 0, &iov); + r = fill_iovec_sprintf(format, ap, 0, &iov, &n_iov); va_end(ap); + if (r < 0) + return r; - if (_unlikely_(i < 0)) { - r = i; - goto finish; - } - - r = sd_journal_sendv(iov, i); - -finish: - for (j = 0; j < i; j++) - free(iov[j].iov_base); - - free(iov); - - return r; + return sd_journal_sendv(iov, n_iov); } _public_ int sd_journal_sendv(const struct iovec *iov, int n) { @@ -529,19 +500,19 @@ _public_ int sd_journal_printv_with_location(int priority, const char *file, con } _public_ int sd_journal_send_with_location(const char *file, const char *line, const char *func, const char *format, ...) { - _cleanup_free_ struct iovec *iov = NULL; - int r, i, j; + struct iovec *iov = NULL; + size_t n_iov = 0; va_list ap; char *f; + int r; + + CLEANUP_ARRAY(iov, n_iov, iovec_array_free); va_start(ap, format); - i = fill_iovec_sprintf(format, ap, 3, &iov); + r = fill_iovec_sprintf(format, ap, 3, &iov, &n_iov); va_end(ap); - - if (_unlikely_(i < 0)) { - r = i; - goto finish; - } + if (r < 0) + return r; ALLOCA_CODE_FUNC(f, func); @@ -549,11 +520,9 @@ _public_ int sd_journal_send_with_location(const char *file, const char *line, c iov[1] = IOVEC_MAKE_STRING(line); iov[2] = IOVEC_MAKE_STRING(f); - r = sd_journal_sendv(iov, i); + r = sd_journal_sendv(iov, n_iov); -finish: - for (j = 3; j < i; j++) - free(iov[j].iov_base); + iov[0] = iov[1] = iov[2] = IOVEC_NULL; return r; } |