]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Fix] lua_redis: add defensive check in GC handler
authorVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 29 Jan 2026 15:17:15 +0000 (15:17 +0000)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Thu, 29 Jan 2026 15:17:15 +0000 (15:17 +0000)
Add validation in lua_redis_gc to check that the context pointer
appears valid before releasing. This prevents crashes when Lua GC
collects stale userdata pointing to already-freed memory.

src/lua/lua_redis.c

index 214f6433ed027866b1c162a029813c85a535e5f3..b1c29f939187c942bd7fe4bcf086d45924c22e8a 100644 (file)
@@ -246,10 +246,24 @@ lua_redis_dtor(struct lua_redis_ctx *ctx)
 static int
 lua_redis_gc(lua_State *L)
 {
-       struct lua_redis_ctx *ctx = lua_check_redis(L, 1);
+       void *ud = rspamd_lua_check_udata(L, 1, rspamd_redis_classname);
 
-       if (ctx) {
-               REDIS_RELEASE(ctx);
+       if (ud) {
+               struct lua_redis_ctx **pctx = (struct lua_redis_ctx **) ud;
+               struct lua_redis_ctx *ctx = *pctx;
+
+               /*
+                * Defensive check: verify the context appears valid before releasing.
+                * The context might be freed by another code path while this userdata
+                * still holds a pointer to it. Check that the destructor matches and
+                * refcount is reasonable to detect garbage/freed memory.
+                */
+               if (ctx && ctx->ref.dtor == (ref_dtor_cb_t) lua_redis_dtor &&
+                       ctx->ref.refcount > 0 && ctx->ref.refcount < 10000) {
+                       REDIS_RELEASE(ctx);
+               }
+
+               *pctx = NULL;
        }
 
        return 0;