From: Dragan Dosen Date: Wed, 1 Jul 2026 08:18:49 +0000 (+0000) Subject: MINOR: log: add app_log_raw() and send_log_raw() for binary-safe logging X-Git-Url: http://git.kaiwu.me/postgresql/log/contrib/postgres_fdw/static/control.html?a=commitdiff_plain;h=146015e58b142246b529390abd8886219460c344;p=haproxy.git MINOR: log: add app_log_raw() and send_log_raw() for binary-safe logging app_log() and send_log() build the message with vsnprintf(), which stops at the first NUL byte and therefore cannot emit an arbitrary binary payload. Add two variants that pass a pre-built of bytes straight to __send_log() without formatting it, so embedded NUL bytes are preserved: * app_log_raw() : takes an explicit list of loggers and a tag * send_log_raw() : derives both from a proxy The send path still strips trailing LF / NUL bytes (kept for the legacy text logs), so the message must be self-terminating by its own encoding and must not rely on a meaningful trailing '\n' or NUL. --- diff --git a/include/haproxy/log.h b/include/haproxy/log.h index f1610a297..061d61801 100644 --- a/include/haproxy/log.h +++ b/include/haproxy/log.h @@ -142,6 +142,8 @@ static inline void sess_log_embryonic(struct session *sess) void app_log(struct list *loggers, struct buffer *tag, int level, const char *format, ...) __attribute__ ((format(printf, 4, 5))); +void app_log_raw(struct list *loggers, struct buffer *tag, int level, char *msg, size_t len); + /* * add to the logformat linked list */ @@ -173,6 +175,8 @@ int parse_logger(char **args, struct list *loggers, int do_del, const char *file void send_log(struct proxy *p, int level, const char *format, ...) __attribute__ ((format(printf, 3, 4))); +void send_log_raw(struct proxy *p, int level, char *msg, size_t len); + /* * returns log format for or LOG_FORMAT_UNSPEC if not found. */ diff --git a/src/log.c b/src/log.c index 1acc1a0c4..68826f49c 100644 --- a/src/log.c +++ b/src/log.c @@ -3208,6 +3208,23 @@ void send_log(struct proxy *p, int level, const char *format, ...) logline, data_len, default_rfc5424_sd_log_format, 2); } +/* + * Same as send_log() but emits the pre-built message of bytes + * as-is (no vsnprintf), so embedded NUL bytes are preserved, which makes + * it usable for binary payloads. The send path still strips trailing '\n' + * / NUL bytes, so must be self-terminating by its own encoding and + * not carry a meaningful trailing '\n' or NUL. + */ +void send_log_raw(struct proxy *p, int level, char *msg, size_t len) +{ + if (level < 0 || msg == NULL) + return; + + __send_log(NULL, (p ? &p->loggers : NULL), + (p ? &p->log_tag : NULL), level, + msg, len, default_rfc5424_sd_log_format, 2); +} + /* * This function builds a log header according to settings. * @@ -5456,6 +5473,21 @@ void app_log(struct list *loggers, struct buffer *tag, int level, const char *fo __send_log(NULL, loggers, tag, level, logline, data_len, default_rfc5424_sd_log_format, 2); } +/* + * Same as app_log() but emits the pre-built message of bytes + * as-is (no vsnprintf), so embedded NUL bytes are preserved, which makes + * it usable for binary payloads. The send path still strips trailing '\n' + * / NUL bytes, so must be self-terminating by its own encoding and + * not carry a meaningful trailing '\n' or NUL. + */ +void app_log_raw(struct list *loggers, struct buffer *tag, int level, char *msg, size_t len) +{ + if (level < 0 || msg == NULL) + return; + + __send_log(NULL, loggers, tag, level, msg, len, default_rfc5424_sd_log_format, 2); +} + /* * This function sets up the initial state for a log message by preparing * the buffer, setting default values for the log level and facility, and