Merge pull request #15052 from jaankit/journal-send

journal-send: Fix the limitation of LINE_MAX
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2020-05-15 10:42:25 +02:00 committed by GitHub
commit 214ffe64fc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 59 additions and 14 deletions

View File

@ -15,6 +15,7 @@
#include "errno-util.h"
#include "fd-util.h"
#include "io-util.h"
#include "fileio.h"
#include "memfd-util.h"
#include "socket-util.h"
#include "stdio-util.h"
@ -73,12 +74,12 @@ _public_ int sd_journal_print(int priority, const char *format, ...) {
}
_public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
/* FIXME: Instead of limiting things to LINE_MAX we could do a
C99 variable-length array on the stack here in a loop. */
char buffer[8 + LINE_MAX], p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
char p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
char sbuf[LINE_MAX + 8] = "MESSAGE=";
struct iovec iov[2];
int len;
va_list aq;
char *buffer = sbuf;
assert_return(priority >= 0, -EINVAL);
assert_return(priority <= 7, -EINVAL);
@ -86,14 +87,27 @@ _public_ int sd_journal_printv(int priority, const char *format, va_list ap) {
xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
memcpy(buffer, "MESSAGE=", 8);
vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
va_copy(aq, ap);
len = vsnprintf(buffer + 8, LINE_MAX, format, aq);
va_end(aq);
if (len >= (int)LONG_LINE_MAX - 8)
return -ENOBUFS;
/* Allocate large buffer to accomodate big message */
if (len >= LINE_MAX) {
int rlen;
buffer = alloca(len + 9);
memcpy(buffer, "MESSAGE=", 8);
rlen = vsnprintf(buffer + 8, len + 1, format, ap);
assert(len == rlen);
}
/* Strip trailing whitespace, keep prefix whitespace. */
(void) strstrip(buffer);
/* Suppress empty lines */
if (isempty(buffer+8))
if (isempty(buffer + 8))
return 0;
iov[0] = IOVEC_MAKE_STRING(buffer);
@ -437,9 +451,13 @@ _public_ int sd_journal_print_with_location(int priority, const char *file, cons
}
_public_ int sd_journal_printv_with_location(int priority, const char *file, const char *line, const char *func, const char *format, va_list ap) {
char buffer[8 + LINE_MAX], p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
char p[STRLEN("PRIORITY=") + DECIMAL_STR_MAX(int) + 1];
char sbuf[LINE_MAX + 8] = "MESSAGE=";
struct iovec iov[5];
char *f;
int len;
char *buffer = sbuf;
va_list aq;
assert_return(priority >= 0, -EINVAL);
assert_return(priority <= 7, -EINVAL);
@ -447,14 +465,27 @@ _public_ int sd_journal_printv_with_location(int priority, const char *file, con
xsprintf(p, "PRIORITY=%i", priority & LOG_PRIMASK);
memcpy(buffer, "MESSAGE=", 8);
vsnprintf(buffer+8, sizeof(buffer) - 8, format, ap);
va_copy(aq, ap);
len = vsnprintf(buffer + 8, LINE_MAX, format, aq);
va_end(aq);
if (len >= (int)LONG_LINE_MAX - 8)
return -ENOBUFS;
/* Allocate large buffer to accomodate big message */
if (len >= LINE_MAX) {
int rlen;
buffer = alloca(len + 9);
memcpy(buffer, "MESSAGE=", 8);
rlen = vsnprintf(buffer + 8, len + 1, format, ap);
assert(len == rlen);
}
/* Strip trailing whitespace, keep prefixing whitespace */
(void) strstrip(buffer);
/* Suppress empty lines */
if (isempty(buffer+8))
if (isempty(buffer + 8))
return 0;
/* func is initialized from __func__ which is not a macro, but

View File

@ -5,11 +5,19 @@
#include <unistd.h>
#include "sd-journal.h"
#include "fileio.h"
#include "macro.h"
#include "memory-util.h"
int main(int argc, char *argv[]) {
static void test_journal_print(void) {
assert_se(sd_journal_print(LOG_INFO, "XXX") == 0);
assert_se(sd_journal_print(LOG_INFO, "%s", "YYY") == 0);
assert_se(sd_journal_print(LOG_INFO, "X%4094sY", "ZZZ") == 0);
assert_se(sd_journal_print(LOG_INFO, "X%*sY", LONG_LINE_MAX - 8 - 3, "ZZZ") == 0);
assert_se(sd_journal_print(LOG_INFO, "X%*sY", LONG_LINE_MAX - 8 - 2, "ZZZ") == -ENOBUFS);
}
static void test_journal_send(void) {
_cleanup_free_ char *huge = NULL;
#define HUGE_SIZE (4096*1024)
@ -82,7 +90,13 @@ int main(int argc, char *argv[]) {
assert_se(sd_journal_sendv(graph2, 1) == 0);
assert_se(sd_journal_sendv(message1, 1) == 0);
assert_se(sd_journal_sendv(message2, 1) == 0);
}
int main(int argc, char *argv[]) {
test_journal_print();
test_journal_send();
/* Sleep a bit to make it easy for journald to collect metadata. */
sleep(1);
return 0;