]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: tools: have parse_line's error pointer point to unknown variable names
authorWilly Tarreau <w@1wt.eu>
Tue, 24 Jun 2025 15:20:33 +0000 (17:20 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 24 Jun 2025 16:29:41 +0000 (18:29 +0200)
When an argument is empty, parse_line() currently returns a pointer to
the empty string itself. This is convenient, but it's only actionable by
the user who will see for example "${HAPROXY_LOCALPEER}" and figure what
is wrong. Here we slightly change the reported pointer so that if an empty
argument results from the evaluation of an empty variable (meaning that
all variables in string are empty and no other char is present), then
instead of pointing to the opening quote, we'll return a pointer to the
first character of the variable's name. This will allow to make a
difference between an empty variable and an unknown variable, and for
the caller to take action based on this.

I.e. before we would get:

    log "${LOG_SERVER_IP}" local0
        ^

if LOG_SERVER_IP is not set, and now instead we'll get this:

    log "${LOG_SERVER_IP}" local0
           ^

src/tools.c

index 29a8a7845ea65cfd61c9d9f17194d86d3cb25b3b..0f9476fe649a7d6437351858548e4c1cafd4e14e 100644 (file)
@@ -6184,6 +6184,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
        const char *curr_in = in; // <in> at the beginning of the loop
        const char *begin_new_arg = NULL; // <in> at transition to new arg
        const char *empty_arg_ptr = NULL; // pos of first empty arg if any (wrt in)
+       const char *unknown_var_name = NULL; // relative to in
        int squote = 0;
        int dquote = 0;
        int arg = 0;
@@ -6403,6 +6404,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
                                        if (!*in)
                                                goto no_brace;
                                        *in = 0; // terminate the default value
+                                       unknown_var_name = NULL;
                                }
                                else if (*in != '}') {
                                no_brace:
@@ -6419,6 +6421,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
                        }
 
                        if (value) {
+                               unknown_var_name = NULL;
                                while (*value) {
                                        /* expand as individual parameters on a space character */
                                        if (word_expand && isspace((unsigned char)*value)) {
@@ -6451,6 +6454,9 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
                        else {
                                /* An unmatched environment variable was parsed. */
                                in_arg = 1;
+
+                               if (!unknown_var_name)
+                                       unknown_var_name = var_name;
                        }
                        word_expand = NULL;
                }
@@ -6470,7 +6476,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
 
                if (prev_in_arg && !in_arg) {
                        if (!empty_arg_ptr && outpos == arg_start)
-                               empty_arg_ptr = begin_new_arg;
+                               empty_arg_ptr = unknown_var_name ? unknown_var_name : begin_new_arg;
                        EMIT_CHAR(0);
                        arg++;
                        arg_start = outpos;
@@ -6480,7 +6486,7 @@ uint32_t parse_line(char *in, char *out, size_t *outlen, char **args, int *nbarg
        /* end of output string */
        if (in_arg) {
                if (!empty_arg_ptr && outpos == arg_start)
-                       empty_arg_ptr = begin_new_arg;
+                       empty_arg_ptr = unknown_var_name ? unknown_var_name : begin_new_arg;
                EMIT_CHAR(0);
                arg++;
                arg_start = outpos;