summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorYu Watanabe <watanabe.yu+github@gmail.com>2023-02-23 03:39:42 +0100
committerYu Watanabe <watanabe.yu+github@gmail.com>2023-02-23 07:09:59 +0100
commit5648ebaf403dd2614a7cc72e892f4d29eaca46ef (patch)
treedce9d4d771e82db9d8cd842ebed7c87916af5f89 /src
parentio-util: drop double evaluation in IOVEC_INIT_STRING() (diff)
downloadsystemd-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.c107
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;
}