From 1485ea2ee742779b0030152ebde92a8370518afa Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Thu, 12 Apr 2012 13:25:25 -0300 Subject: [PATCH] Finalizers may call functions from a dynamic library after the library has been unloaded --- bugs | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 102 insertions(+), 2 deletions(-) diff --git a/bugs b/bugs index 8708dd92..ff499e50 100644 --- a/bugs +++ b/bugs @@ -1880,8 +1880,8 @@ patch = [[ +++ lundump.c 2008/04/04 19:51:41 2.7.1.4 @@ -1,5 +1,5 @@ /* --** $Id: bugs,v 1.111 2011/10/21 19:34:23 roberto Exp roberto $ -+** $Id: bugs,v 1.111 2011/10/21 19:34:23 roberto Exp roberto $ +-** $Id: bugs,v 1.112 2012/01/20 18:32:13 roberto Exp roberto $ ++** $Id: bugs,v 1.112 2012/01/20 18:32:13 roberto Exp roberto $ ** load precompiled Lua chunks ** See Copyright Notice in lua.h */ @@ -2520,6 +2520,106 @@ patch = [[ ]] } +Bug{ +what = [[Finalizers may call functions from a dynamic library after +the library has been unloaded]], +report = [[Josh Haberman, 2012/04/08]], +since = [[5.1]], +example = [[ +local u = setmetatable({}, {__gc = function () foo() end}) +local m = require 'mod' -- 'mod' may be any dynamic library written in C +foo = m.foo -- 'foo' may be any function from 'mod' +-- end program; it crashes +]], +patch = [[ +=================================================================== +RCS file: RCS/loadlib.c,v +retrieving revision 1.108 +diff -r1.108 loadlib.c +95c95 +< #define LIBPREFIX "LOADLIB: " +--- +> #define CLIBS "_CLIBS" +251,266c251,256 +< +< static void **ll_register (lua_State *L, const char *path) { +< void **plib; +< lua_pushfstring(L, "%s%s", LIBPREFIX, path); +< lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ +< if (!lua_isnil(L, -1)) /* is there an entry? */ +< plib = (void **)lua_touserdata(L, -1); +< else { /* no entry yet; create one */ +< lua_pop(L, 1); /* remove result from gettable */ +< plib = (void **)lua_newuserdata(L, sizeof(const void *)); +< *plib = NULL; +< luaL_setmetatable(L, "_LOADLIB"); +< lua_pushfstring(L, "%s%s", LIBPREFIX, path); +< lua_pushvalue(L, -2); +< lua_settable(L, LUA_REGISTRYINDEX); +< } +--- +> static void *ll_checkclib (lua_State *L, const char *path) { +> void *plib; +> lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); +> lua_getfield(L, -1, path); +> plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ +> lua_pop(L, 2); /* pop CLIBS table and 'plib' */ +270a261,270 +> static void ll_addtoclib (lua_State *L, const char *path, void *plib) { +> lua_getfield(L, LUA_REGISTRYINDEX, CLIBS); +> lua_pushlightuserdata(L, plib); +> lua_pushvalue(L, -1); +> lua_setfield(L, -3, path); /* CLIBS[path] = plib */ +> lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ +> lua_pop(L, 1); /* pop CLIBS table */ +> } +> +> +272,273c272,273 +< ** __gc tag method: calls library's `ll_unloadlib' function with the lib +< ** handle +--- +> ** __gc tag method for CLIBS table: calls 'll_unloadlib' for all lib +> ** handles in list CLIBS +276,278c276,281 +< void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); +< if (*lib) ll_unloadlib(*lib); +< *lib = NULL; /* mark library as closed */ +--- +> int n = luaL_len(L, 1); +> for (; n >= 1; n--) { /* for each handle, in reverse order */ +> lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ +> ll_unloadlib(lua_touserdata(L, -1)); +> lua_pop(L, 1); /* pop handle */ +> } +284,286c287,292 +< void **reg = ll_register(L, path); +< if (*reg == NULL) *reg = ll_load(L, path, *sym == '*'); +< if (*reg == NULL) return ERRLIB; /* unable to load library */ +--- +> void *reg = ll_checkclib(L, path); /* check loaded C libraries */ +> if (reg == NULL) { /* must load library? */ +> reg = ll_load(L, path, *sym == '*'); +> if (reg == NULL) return ERRLIB; /* unable to load library */ +> ll_addtoclib(L, path, reg); +> } +292c298 +< lua_CFunction f = ll_sym(L, *reg, sym); +--- +> lua_CFunction f = ll_sym(L, reg, sym); +675,676c681,683 +< /* create new type _LOADLIB */ +< luaL_newmetatable(L, "_LOADLIB"); +--- +> /* create table CLIBS to keep track of loaded C libraries */ +> luaL_getsubtable(L, LUA_REGISTRYINDEX, CLIBS); +> lua_createtable(L, 0, 1); /* metatable for CLIBS */ +678a686 +> lua_setmetatable(L, -2); +]] +} + + --[=[ Bug{ what = [[ ]],