]> dgit.raspbian.org Git - dovecot.git/commitdiff
[PATCH 4/6] lib-var-expand: Change escape func signature to return int with error_r
authorAki Tuomi <aki.tuomi@open-xchange.com>
Thu, 21 May 2026 08:00:56 +0000 (11:00 +0300)
committerNoah Meyerhans <noahm@debian.org>
Wed, 16 Sep 2026 19:06:35 +0000 (15:06 -0400)
Wire error propagation in var_expand_program_execute_one_real() so a
failing escape function causes the expansion to return -1.

Update all implementations (passdb-sql, userdb-sql, db-ldap, dict-ldap,
auth-request-var-expand) and replace the unsafe auth_request_escape_func_t
cast in auth-request-var-expand.c with a proper bridge wrapper.

Gbp-Pq: Name 0004-lib-var-expand-Change-escape-func-signature-to-retur.patch

src/auth/auth-request-var-expand.c
src/auth/db-ldap.c
src/auth/db-ldap.h
src/auth/passdb-sql.c
src/auth/test-auth-request-var-expand.c
src/auth/test-ldap.c
src/auth/userdb-sql.c
src/lib-dict-backend/dict-ldap.c
src/lib-var-expand/expansion-program.c
src/lib-var-expand/test-var-expand.c
src/lib-var-expand/var-expand.h

index e101c8d1b211b5f0550686cb1401c80130e7edc7..410ec0b1181c411eb6bcf291e73779fb4f8bb243 100644 (file)
@@ -55,6 +55,15 @@ escape_none(const char *string,
        return string;
 }
 
+static int
+auth_request_escape_wrapper(const char *input, const char **output_r,
+                           void *context, const char **error_r ATTR_UNUSED)
+{
+       const struct auth_request_var_expand_ctx *ctx = context;
+       *output_r = ctx->escape_func(input, ctx->auth_request);
+       return 0;
+}
+
 const char *
 auth_request_str_escape(const char *string,
                        const struct auth_request *request ATTR_UNUSED)
@@ -242,9 +251,9 @@ int auth_request_var_expand_with_table(string_t *dest, const char *str,
        const struct var_expand_params params = {
                .table = table,
                .providers = auth_request_var_expand_providers,
-               .escape_func = (var_expand_escape_func_t *)ctx.escape_func,
+               .escape_func = auth_request_escape_wrapper,
                .context = &ctx,
-               .escape_context = (void *)auth_request,
+               .escape_context = &ctx,
                .event = auth_request->event,
        };
 
index 8eda9245654450ff67b61addb5203cc032d4686c..9bf7998b7ec271554dff11307486ac7568eaba5e 100644 (file)
@@ -1138,7 +1138,8 @@ void db_ldap_get_attribute_names(pool_t pool,
                *sensitive_r = array_front(&sensitive_attr_names);
 }
 
-const char *ldap_escape(const char *input, void *context ATTR_UNUSED)
+int ldap_escape(const char *input, const char **output_r,
+               void *context ATTR_UNUSED, const char **error_r ATTR_UNUSED)
 {
        /* This function escapes both LDAP filters and LDAP DNs. This works,
           because both allow using the method of escaping any characters.
@@ -1195,8 +1196,10 @@ const char *ldap_escape(const char *input, void *context ATTR_UNUSED)
                           (required by DN) */
                        if (pos > 0 && input[pos - 1] == ' ')
                                pos--;
-                       else
-                               return input;
+                       else {
+                               *output_r = input;
+                               return 0;
+                       }
                }
        }
 
@@ -1211,7 +1214,8 @@ const char *ldap_escape(const char *input, void *context ATTR_UNUSED)
                        pos--;
        } while (pos < input_len);
        str_append_data(str, input, pos);
-       return str_c(str);
+       *output_r = str_c(str);
+       return 0;
 }
 
 static bool
index a6aac02a72b6ba27cd67e6eec678becf522ad563..3686ab8b7cdc1e268ad8f4c83d09a81f276c826e 100644 (file)
@@ -169,8 +169,8 @@ void db_ldap_connect_delayed(struct ldap_connection *conn);
 
 void db_ldap_enable_input(struct ldap_connection *conn, bool enable);
 
-const char *ldap_dn_escape(const char *str, void *context);
-const char *ldap_escape(const char *str, void *context);
+int ldap_dn_escape(const char *str, const char **output_r, void *context, const char **error_r);
+int ldap_escape(const char *str, const char **output_r, void *context, const char **error_r);
 const char *ldap_get_error(struct ldap_connection *conn);
 
 struct db_ldap_result_iterate_context *
index ec160e3d7582c61466024523c98c0d8589e3ad8a..3745942056e3246079ce4f8558f3043d54370c20 100644 (file)
@@ -167,10 +167,12 @@ static void sql_query_callback(struct sql_result *result,
        auth_request_unref(&auth_request);
 }
 
-static const char *passdb_sql_escape(const char *str, void *context)
+static int passdb_sql_escape(const char *str, const char **output_r,
+                            void *context, const char **error_r ATTR_UNUSED)
 {
        struct sql_db *db = context;
-       return sql_escape_string(db, str);
+       *output_r = sql_escape_string(db, str);
+       return 0;
 }
 
 static void sql_lookup_pass(struct passdb_sql_request *sql_request)
index 851e365e294fcd4eb400b70174b998e695cb7a0d..75236bb6c556292d0e3e741506dfeded23acb8bd 100644 (file)
@@ -70,6 +70,14 @@ test_escape(const char *string, const struct auth_request *request)
        return dest;
 }
 
+static int
+test_escape_varexpand(const char *string, const char **output_r,
+                     void *context, const char **error_r ATTR_UNUSED)
+{
+       *output_r = test_escape(string, context);
+       return 0;
+}
+
 static bool test_empty_request(string_t *str, const char *input)
 {
        const struct var_expand_params params = {
@@ -102,7 +110,7 @@ static void test_auth_request_var_expand_keys(void)
 
        const struct var_expand_params params = {
                .table = auth_request_get_var_expand_table(&test_request),
-               .escape_func = (var_expand_escape_func_t *)test_escape,
+               .escape_func = test_escape_varexpand,
                .escape_context = &test_request,
        };
 
@@ -129,7 +137,7 @@ static void test_auth_request_var_expand_flags(void)
 
        struct var_expand_params params = {
                .table = auth_request_get_var_expand_table(&test_request),
-               .escape_func = (var_expand_escape_func_t *)test_escape,
+               .escape_func = test_escape_varexpand,
                .escape_context = &test_request
        };
        test_assert(var_expand(str, test_input, &params, &error) == 0);
@@ -169,7 +177,7 @@ static void test_auth_request_var_expand_long(void)
 
        const struct var_expand_params params = {
                .table = auth_request_get_var_expand_table(&test_request),
-               .escape_func = (var_expand_escape_func_t *)test_escape,
+               .escape_func = test_escape_varexpand,
                .escape_context = &test_request,
        };
 
@@ -200,7 +208,7 @@ static void test_auth_request_var_expand_usernames(void)
                test_request.fields.user = t_strdup_noconst(tests[i].username);
                const struct var_expand_params params = {
                        .table = auth_request_get_var_expand_table(&test_request),
-                       .escape_func = (var_expand_escape_func_t *)test_escape,
+                       .escape_func = test_escape_varexpand,
                        .escape_context = &test_request,
                };
                str_truncate(str, 0);
index cd9904a7ee8ebbf8c78225aabe26d593b6a8fa7b..4557306afda809074c1454e97b8e642da5b4556e 100644 (file)
@@ -25,8 +25,9 @@ static void test_ldap_escape(void)
        };
        test_begin("ldap_escape()");
        for (unsigned int i = 0; i < N_ELEMENTS(tests); i++) {
-               test_assert_strcmp_idx(ldap_escape(tests[i].input, NULL),
-                                      tests[i].output, i);
+               const char *output, *error;
+               test_assert(ldap_escape(tests[i].input, &output, NULL, &error) == 0);
+               test_assert_strcmp_idx(output, tests[i].output, i);
        }
        test_end();
 }
index 09bac486508d3a25fe2f6180dad5e3044b4893bd..39caf3862e597e2632879fa8c08b6f644f70b5de 100644 (file)
@@ -112,10 +112,12 @@ static void sql_query_callback(struct sql_result *sql_result,
        i_free(sql_request);
 }
 
-static const char *userdb_sql_escape(const char *str, void *context)
+static int userdb_sql_escape(const char *str, const char **output_r,
+                            void *context, const char **error_r ATTR_UNUSED)
 {
        struct sql_db *db = context;
-       return sql_escape_string(db, str);
+       *output_r = sql_escape_string(db, str);
+       return 0;
 }
 
 static void userdb_sql_lookup(struct auth_request *auth_request,
index 81eed292cec91f824a596139d4571c7cd0252066..c3420f8ee5609b4c5b0f248c8eafec30d2519502 100644 (file)
@@ -139,7 +139,8 @@ int dict_ldap_connect(struct ldap_dict *dict, const char **error_r)
 #define IS_LDAP_ESCAPED_CHAR(c) \
        ((((unsigned char)(c)) & 0x80) != 0 || strchr(LDAP_ESCAPE_CHARS, (c)) != NULL)
 
-static const char *ldap_escape(const char *str, void *context ATTR_UNUSED)
+static int ldap_escape(const char *str, const char **output_r,
+                      void *context ATTR_UNUSED, const char **error_r ATTR_UNUSED)
 {
        string_t *ret = NULL;
 
@@ -154,7 +155,8 @@ static const char *ldap_escape(const char *str, void *context ATTR_UNUSED)
                        str_append_c(ret, *p);
        }
 
-       return ret == NULL ? str : str_c(ret);
+       *output_r = ret == NULL ? str : str_c(ret);
+       return 0;
 }
 
 static
index 6a05bc386f03b8aee638d2d83c11554bace1117e..7fc591d181fb72c80fd876e99d9b204f43dc071d 100644 (file)
@@ -142,9 +142,11 @@ int var_expand_program_execute(string_t *dest, const struct var_expand_program *
                if (state.transfer_set) {
                        if (!program->only_literal && !state.transfer_safe &&
                            params->escape_func != NULL) {
-                               str_append(state.result,
-                                          params->escape_func(str_c(state.transfer),
-                                                              params->escape_context));
+                               const char *escaped;
+                               if (params->escape_func(str_c(state.transfer), &escaped,
+                                                       params->escape_context, error_r) < 0)
+                                       return -1;
+                               str_append(state.result, escaped);
                        } else
                                str_append_str(state.result, state.transfer);
                } else {
index 3fa9c6869f8e822ce939057619f53df0fb2f138e..a66b3e8935764c0a53f7e45dc8dc631718efef60 100644 (file)
@@ -586,7 +586,8 @@ static void test_var_expand_tables_arr(void)
        test_end();
 }
 
-static const char *test_escape(const char *str, void *context)
+static int test_escape(const char *str, const char **output_r,
+                      void *context, const char **error_r ATTR_UNUSED)
 {
        const char *escape_chars = context;
        string_t *dest = t_str_new(strlen(str) + 2);
@@ -601,7 +602,8 @@ static const char *test_escape(const char *str, void *context)
                }
        }
        str_append_c(dest, '\'');
-       return str_c(dest);
+       *output_r = str_c(dest);
+       return 0;
 }
 
 static void test_var_expand_escape(void)
index 58aea4ef032bea00408400ca7552027e1fd67faa..16330251d8e9becfcc617d27b1602f7815027609 100644 (file)
 */
 typedef int value_provider_func_t(const char *key, const char **value_r,
                                  void *context, const char **error_r);
-/* Used for escaping values, gets given string to escape and context,
-   must return escaped string. */
-typedef const char *var_expand_escape_func_t(const char *str, void *context);
+/* Used for escaping values. On success sets output_r and returns 0.
+   On failure sets error_r and returns -1. */
+typedef int var_expand_escape_func_t(const char *input, const char **output_r,
+                                    void *context, const char **error_r);
 
 struct var_expand_parser_state;
 struct var_expand_program;