]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
Store TLS opts in lua stack, no strdup/free 5626/head
authorJustin Dossey <jbd@justindossey.com>
Thu, 25 Sep 2025 16:52:45 +0000 (09:52 -0700)
committerJustin Dossey <jbd@justindossey.com>
Thu, 25 Sep 2025 16:52:45 +0000 (09:52 -0700)
- Removed g_strdup/g_free of TLS paths in src/lua/lua_redis.c.
- Now we:
  - Keep TLS values (booleans + strings) on the Lua stack temporarily.
  - Use an absolute table index (so gettable calls aren’t confused by
    the growing stack).
  - Call rspamd_redis_pool_connect_ext while those values are on the
    stack.
  - Pop all postponed values and then the table in one go immediately
    after the connect call.
- The C++ pool still copies into std::string on element creation; we
  only ensure Lua strings live through the call without extra
  allocations.

src/lua/lua_redis.c

index d1eb471da8332884cf4f657d704e720ff159c7e0..02dccce2c24411adbe053e4bfaea37e0e9722c31 100644 (file)
@@ -889,10 +889,10 @@ rspamd_lua_redis_prepare_connection(lua_State *L, int *pcbref, gboolean is_async
        const char *host = NULL;
        const char *username = NULL, *password = NULL, *dbname = NULL, *log_tag = NULL;
        struct rspamd_redis_tls_opts tls_opts;
-       /* Duplicated TLS strings to ensure lifetime beyond Lua stack */
-       char *dup_ca_file = NULL, *dup_ca_dir = NULL, *dup_cert_file = NULL,
-                *dup_key_file = NULL, *dup_sni = NULL;
        int cbref = -1;
+       /* Track postponed TLS values on Lua stack and table index */
+       int tls_items = 0;
+       int tls_tbl_idx = 0;
        struct rspamd_config *cfg = NULL;
        struct rspamd_async_session *session = NULL;
        struct ev_loop *ev_base = NULL;
@@ -1016,70 +1016,64 @@ rspamd_lua_redis_prepare_connection(lua_State *L, int *pcbref, gboolean is_async
                }
                lua_pop(L, 1);
 
-               /* TLS options (optional) */
+               /* TLS options (optional). Postpone pops to keep values alive */
+               tls_tbl_idx = lua_gettop(L);
+
                lua_pushstring(L, "ssl");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (!!lua_toboolean(L, -1)) {
                        tls_opts.use_tls = true;
                }
-               lua_pop(L, 1);
+               tls_items++;
 
                lua_pushstring(L, "no_ssl_verify");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (!!lua_toboolean(L, -1)) {
                        tls_opts.no_ssl_verify = true;
                }
-               lua_pop(L, 1);
+               tls_items++;
 
-               /* Duplicate string options to avoid ephemeral Lua string pointers */
                lua_pushstring(L, "ssl_ca");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (lua_type(L, -1) == LUA_TSTRING) {
-                       dup_ca_file = g_strdup(lua_tostring(L, -1));
-                       tls_opts.ca_file = dup_ca_file;
+                       tls_opts.ca_file = lua_tostring(L, -1);
                }
-               lua_pop(L, 1);
+               tls_items++;
 
                lua_pushstring(L, "ssl_ca_dir");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (lua_type(L, -1) == LUA_TSTRING) {
-                       dup_ca_dir = g_strdup(lua_tostring(L, -1));
-                       tls_opts.ca_dir = dup_ca_dir;
+                       tls_opts.ca_dir = lua_tostring(L, -1);
                }
-               lua_pop(L, 1);
+               tls_items++;
 
                lua_pushstring(L, "ssl_cert");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (lua_type(L, -1) == LUA_TSTRING) {
-                       dup_cert_file = g_strdup(lua_tostring(L, -1));
-                       tls_opts.cert_file = dup_cert_file;
+                       tls_opts.cert_file = lua_tostring(L, -1);
                }
-               lua_pop(L, 1);
+               tls_items++;
 
                lua_pushstring(L, "ssl_key");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (lua_type(L, -1) == LUA_TSTRING) {
-                       dup_key_file = g_strdup(lua_tostring(L, -1));
-                       tls_opts.key_file = dup_key_file;
+                       tls_opts.key_file = lua_tostring(L, -1);
                }
-               lua_pop(L, 1);
+               tls_items++;
 
                lua_pushstring(L, "sni");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (lua_type(L, -1) == LUA_TSTRING) {
-                       dup_sni = g_strdup(lua_tostring(L, -1));
-                       tls_opts.sni = dup_sni;
+                       tls_opts.sni = lua_tostring(L, -1);
                }
-               lua_pop(L, 1);
+               tls_items++;
 
                lua_pushstring(L, "no_pool");
-               lua_gettable(L, -2);
+               lua_gettable(L, tls_tbl_idx);
                if (!!lua_toboolean(L, -1)) {
                        flags |= LUA_REDIS_NO_POOL;
                }
-               lua_pop(L, 1);
-
-               lua_pop(L, 1); /* table */
+               tls_items++;
 
                if (session && rspamd_session_blocked(session)) {
                        msg_err_task_check("Session is being destroying");
@@ -1139,12 +1133,15 @@ rspamd_lua_redis_prepare_connection(lua_State *L, int *pcbref, gboolean is_async
                                                                                                rspamd_inet_address_get_port(addr->addr),
                                                                                                &tls_opts);
 
-               /* Free temporary TLS strings after they have been consumed */
-               g_free(dup_ca_file);
-               g_free(dup_ca_dir);
-               g_free(dup_cert_file);
-               g_free(dup_key_file);
-               g_free(dup_sni);
+               /* Pop postponed TLS values and the table itself */
+               if (tls_items > 0) {
+                       lua_pop(L, tls_items);
+                       tls_items = 0;
+               }
+               if (tls_tbl_idx != 0) {
+                       lua_pop(L, 1);
+                       tls_tbl_idx = 0;
+               }
 
                if (ip) {
                        rspamd_inet_address_free(ip);
@@ -1178,13 +1175,6 @@ rspamd_lua_redis_prepare_connection(lua_State *L, int *pcbref, gboolean is_async
                rspamd_inet_address_free(ip);
        }
 
-       /* Free any duplicated TLS strings on error path */
-       g_free(dup_ca_file);
-       g_free(dup_ca_dir);
-       g_free(dup_cert_file);
-       g_free(dup_key_file);
-       g_free(dup_sni);
-
        return NULL;
 }