]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: log: always reserve room for trailing 0 when using CBOR encoding helpers
authorAurelien DARRAGON <adarragon@haproxy.com>
Thu, 6 Aug 2026 19:15:36 +0000 (21:15 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 7 Aug 2026 08:32:55 +0000 (10:32 +0200)
Logging helpers leveraged by sess_build_logline_orig() can be split in
two different groups. Although they all look similar in their construction
as they take pretty much the same parameters and return the address where
following bytes can be appended, some will always try to append the
terminating NULL byte and return the address of the terminating NULL
byte, while others (which are not specifically text oriented) will simply
use all available space (they don't reserve space for the terminating NULL
byte) and return the address of the byte following the last byte written.
But since they don't try to write the \0 themselves, they will in practise
output one extra byte compared to other helpers. If no precaution is taken
and they are used as drop-in replacement to text oriented ones, this can
cause invalid writes later in the code because sess_build_logline_orig()
will always append the terminating NULL byte (even if it is already set),
thus it is mandatory that the output pointer never reaches the stopmark.

Fortunately, most pitfalls were already avoided in log generation path,
but recent commit c614fd3b ("MINOR: log: add +cbor encoding option")
made use of several encoding helpers which were not text oriented as
text oriented ones. Let's fix that by always securing 1 byte for the
terminating NULL byte when calling them (even if it not used by the
endpoint X format, sess_build_logline_orig() will append it not matter
what, so we have to live with that).

Reported-by: Claude (ANT-2026-QQ17FDX1)
It should be backported up to 3.0.

src/log.c

index c48e0a7c5c58e30a52d05d9c8d95e86b2ab90220..c21c2192664295b619a1eba98985e371f2ea93ef 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -2314,7 +2314,9 @@ static char *_lf_encode_bytes(char *start, char *stop,
        }
 
        if (start < stop) {
-               stop--; /* reserve one byte for the final '\0' */
+               stop--; /* reserve one byte for the final '\0' as encoding functions
+                        * will try to use all available space
+                        */
 
                if ((ctx->options & LOG_OPT_ENCODE_CBOR) && !ctx->in_text) {
                        /* start indefinite-length cbor byte string or text */
@@ -2430,7 +2432,10 @@ static inline char *_lf_text_len(char *dst, const char *src,
                         */
                        len = strnlen2(src, len);
 
-                       ret = cbor_encode_text(&ctx->encode.cbor, dst, dst + size, src, len);
+                       /* cbor_encode_text() doesn't append terminating NULL
+                        * byte, we must reserve 1 byte for that.
+                        */
+                       ret = cbor_encode_text(&ctx->encode.cbor, dst, dst + size - 1, src, len);
                        if (ret == NULL)
                                return NULL;
                        len = ret - dst;
@@ -3546,7 +3551,7 @@ const char sess_set_cookie[] = "NPDIRU67";        /* No set-cookie, Set-cookie found an
 #define LOG_CBOR_BYTE(x) do {                                          \
                        ret = _lf_cbor_encode_byte(&ctx->encode.cbor,  \
                                                   tmplog,             \
-                                                  dst + maxsize,      \
+                                                  dst + maxsize - 1,  \
                                                   (x));               \
                        if (ret == NULL)                               \
                                goto out;                              \
@@ -3567,7 +3572,7 @@ const char sess_set_cookie[] = "NPDIRU67";        /* No set-cookie, Set-cookie found an
                                _x[0] = (x);                                   \
                                ret = cbor_encode_text(&ctx->encode.cbor,      \
                                                       tmplog,                 \
-                                                      dst + maxsize,          \
+                                                      dst + maxsize - 1,      \
                                                       _x, sizeof(_x));        \
                                if (ret == NULL)                               \
                                        goto out;                              \
@@ -4139,7 +4144,7 @@ size_t sess_build_logline_orig(struct session *sess, struct stream *s,
                        }
                        else if (ctx->options & LOG_OPT_ENCODE_CBOR) {
                                ret = cbor_encode_text(&ctx->encode.cbor, tmplog,
-                                                      dst + maxsize, tmp->name,
+                                                      dst + maxsize - 1, tmp->name,
                                                       strlen(tmp->name));
                                if (ret == NULL)
                                        goto out;