]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: log: write raw strings using lf_rawtext()
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 27 Mar 2024 09:28:59 +0000 (10:28 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Fri, 26 Apr 2024 16:39:31 +0000 (18:39 +0200)
Make use of the previous commit to print strings that should not be
modified.

For instance, when +X option is provided, we have to print numerical
values in ASCII HEX form. For that, we used snprintf() to output the
result to the log output buffer directly, but now we build the string in
a temporary buffer of fixed-size and then print it using lf_rawtext()
which will take care of encoding options.

Because of this patch, we add a little overhead because we first generate
the text into a temporary variable and then use lf_rawtext() to print it.
Thus we have a double-copy, and this could have some performance
implications that were not yet evaluated. Due to the small number of bytes
that can end up being copied twice, we could be lucky and have no visible
performance impact, but if we happen to see a significant impact, it could
be useful to add a passthrough mechanism (to keep historical behavior)
when no encoding is involved.

src/log.c

index 2ac3128a6672005760df19ea4a208e8a59eccf5e..dc0e0766fd7caaeb99a1a0decfa5f6530494ec0e 100644 (file)
--- a/src/log.c
+++ b/src/log.c
@@ -3335,16 +3335,18 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
                                unsigned long value = logs->accept_date.tv_sec;
 
                                if (tmp->options & LOG_OPT_HEXA) {
-                                       iret = snprintf(tmplog, dst + maxsize - tmplog, "%04X", (unsigned int)value);
+                                       char hex[9]; // enough to hold 32bit hex representation + NULL byte
+
+                                       iret = snprintf(hex, sizeof(hex), "%04X", (unsigned int)value);
                                        if (iret < 0 || iret >= dst + maxsize - tmplog)
                                                goto out;
-                                       tmplog += iret;
+                                       ret = lf_rawtext(tmplog, hex, dst + maxsize - tmplog, tmp);
                                } else {
                                        ret = lf_int(tmplog, dst + maxsize - tmplog, value, tmp, LF_INT_LTOA);
-                                       if (ret == NULL)
-                                               goto out;
-                                       tmplog = ret;
                                }
+                               if (ret == NULL)
+                                       goto out;
+                               tmplog = ret;
                                break;
                        }
 
@@ -3353,17 +3355,19 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
                                unsigned int value = (unsigned int)logs->accept_date.tv_usec/1000;
 
                                if (tmp->options & LOG_OPT_HEXA) {
-                                       iret = snprintf(tmplog, dst + maxsize - tmplog, "%02X", value);
+                                       char hex[9]; // enough to hold 32bit hex representation + NULL byte
+
+                                       iret = snprintf(hex, sizeof(hex), "%02X", value);
                                        if (iret < 0 || iret >= dst + maxsize - tmplog)
                                                goto out;
-                                       tmplog += iret;
+                                       ret = lf_rawtext(tmplog, hex, dst + maxsize - tmplog, tmp);
                                } else {
                                        ret = lf_int(tmplog, dst + maxsize - tmplog, value,
                                                     tmp, LF_INT_UTOA_PAD_4);
-                                       if (ret == NULL)
-                                               goto out;
-                                       tmplog = ret;
                                }
+                               if (ret == NULL)
+                                       goto out;
+                               tmplog = ret;
                                break;
                        }
 
@@ -3378,10 +3382,10 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
                        case LOG_FMT_FRONTEND_XPRT: // %ft
                                src = fe->id;
                                LOGQUOTE_START();
-                               iret = strlcpy2(tmplog, src, dst + maxsize - tmplog);
-                               if (iret == 0)
+                               ret = lf_rawtext(tmplog, src, dst + maxsize - tmplog, tmp);
+                               if (ret == NULL)
                                        goto out;
-                               tmplog += iret;
+                               tmplog ret;
 
                                /* sess->listener may be undefined if the session's owner is a health-check */
                                if (sess->listener && sess->listener->bind_conf->xprt->get_ssl_sock_ctx)
@@ -4003,31 +4007,35 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
 
                        case LOG_FMT_COUNTER: // %rt
                                if (tmp->options & LOG_OPT_HEXA) {
-                                       iret = snprintf(tmplog, dst + maxsize - tmplog, "%04X", uniq_id);
+                                       char hex[9]; // enough to hold 32bit hex representation + NULL byte
+
+                                       iret = snprintf(hex, sizeof(hex), "%04X", uniq_id);
                                        if (iret < 0 || iret >= dst + maxsize - tmplog)
                                                goto out;
-                                       tmplog += iret;
+                                       ret = lf_rawtext(tmplog, hex, dst + maxsize - tmplog, tmp);
                                } else {
                                        ret = lf_int(tmplog, dst + maxsize - tmplog, uniq_id, tmp, LF_INT_LTOA);
-                                       if (ret == NULL)
-                                               goto out;
-                                       tmplog = ret;
                                }
+                               if (ret == NULL)
+                                       goto out;
+                               tmplog = ret;
                                break;
 
                        case LOG_FMT_LOGCNT: // %lc
                                if (tmp->options & LOG_OPT_HEXA) {
-                                       iret = snprintf(tmplog, dst + maxsize - tmplog, "%04X", fe->log_count);
+                                       char hex[9]; // enough to hold 32bit hex representation + NULL byte
+
+                                       iret = snprintf(hex, sizeof(hex), "%04X", fe->log_count);
                                        if (iret < 0 || iret >= dst + maxsize - tmplog)
                                                goto out;
-                                       tmplog += iret;
+                                       ret = lf_rawtext(tmplog, hex, dst + maxsize - tmplog, tmp);
                                } else {
                                        ret = lf_int(tmplog, dst + maxsize - tmplog, fe->log_count,
                                                     tmp, LF_INT_ULTOA);
-                                       if (ret == NULL)
-                                               goto out;
-                                       tmplog = ret;
                                }
+                               if (ret == NULL)
+                                       goto out;
+                               tmplog = ret;
                                break;
 
                        case LOG_FMT_HOSTNAME: // %H
@@ -4040,16 +4048,18 @@ int sess_build_logline(struct session *sess, struct stream *s, char *dst, size_t
 
                        case LOG_FMT_PID: // %pid
                                if (tmp->options & LOG_OPT_HEXA) {
-                                       iret = snprintf(tmplog, dst + maxsize - tmplog, "%04X", pid);
+                                       char hex[9]; // enough to hold 32bit hex representation + NULL byte
+
+                                       iret = snprintf(hex, sizeof(hex), "%04X", pid);
                                        if (iret < 0 || iret >= dst + maxsize - tmplog)
                                                goto out;
-                                       tmplog += iret;
+                                       ret = lf_rawtext(tmplog, hex, dst + maxsize - tmplog, tmp);
                                } else {
                                        ret = lf_int(tmplog, dst + maxsize - tmplog, pid, tmp, LF_INT_LTOA);
-                                       if (ret == NULL)
-                                               goto out;
-                                       tmplog = ret;
                                }
+                               if (ret == NULL)
+                                       goto out;
+                               tmplog = ret;
                                break;
 
                        case LOG_FMT_UNIQUEID: // %ID