From: Aki Tuomi Date: Thu, 21 May 2026 08:00:56 +0000 (+0300) Subject: [PATCH 4/6] lib-var-expand: Change escape func signature to return int with error_r X-Git-Tag: archive/raspbian/1%2.4.1+dfsg1-6+rpi1+deb13u7^2~80 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=42f88afe333ea25df2a35cadba9a91a647b24b6e;p=dovecot.git [PATCH 4/6] lib-var-expand: Change escape func signature to return int with error_r 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 --- diff --git a/src/auth/auth-request-var-expand.c b/src/auth/auth-request-var-expand.c index e101c8d..410ec0b 100644 --- a/src/auth/auth-request-var-expand.c +++ b/src/auth/auth-request-var-expand.c @@ -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, }; diff --git a/src/auth/db-ldap.c b/src/auth/db-ldap.c index 8eda924..9bf7998 100644 --- a/src/auth/db-ldap.c +++ b/src/auth/db-ldap.c @@ -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 diff --git a/src/auth/db-ldap.h b/src/auth/db-ldap.h index a6aac02..3686ab8 100644 --- a/src/auth/db-ldap.h +++ b/src/auth/db-ldap.h @@ -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 * diff --git a/src/auth/passdb-sql.c b/src/auth/passdb-sql.c index ec160e3..3745942 100644 --- a/src/auth/passdb-sql.c +++ b/src/auth/passdb-sql.c @@ -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) diff --git a/src/auth/test-auth-request-var-expand.c b/src/auth/test-auth-request-var-expand.c index 851e365..75236bb 100644 --- a/src/auth/test-auth-request-var-expand.c +++ b/src/auth/test-auth-request-var-expand.c @@ -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, ¶ms, &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); diff --git a/src/auth/test-ldap.c b/src/auth/test-ldap.c index cd9904a..4557306 100644 --- a/src/auth/test-ldap.c +++ b/src/auth/test-ldap.c @@ -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(); } diff --git a/src/auth/userdb-sql.c b/src/auth/userdb-sql.c index 09bac48..39caf38 100644 --- a/src/auth/userdb-sql.c +++ b/src/auth/userdb-sql.c @@ -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, diff --git a/src/lib-dict-backend/dict-ldap.c b/src/lib-dict-backend/dict-ldap.c index 81eed29..c3420f8 100644 --- a/src/lib-dict-backend/dict-ldap.c +++ b/src/lib-dict-backend/dict-ldap.c @@ -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 diff --git a/src/lib-var-expand/expansion-program.c b/src/lib-var-expand/expansion-program.c index 6a05bc3..7fc591d 100644 --- a/src/lib-var-expand/expansion-program.c +++ b/src/lib-var-expand/expansion-program.c @@ -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 { diff --git a/src/lib-var-expand/test-var-expand.c b/src/lib-var-expand/test-var-expand.c index 3fa9c68..a66b3e8 100644 --- a/src/lib-var-expand/test-var-expand.c +++ b/src/lib-var-expand/test-var-expand.c @@ -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) diff --git a/src/lib-var-expand/var-expand.h b/src/lib-var-expand/var-expand.h index 58aea4e..1633025 100644 --- a/src/lib-var-expand/var-expand.h +++ b/src/lib-var-expand/var-expand.h @@ -11,9 +11,10 @@ */ 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;