From 32a5d96dfc846ccfe63e6272d385fe963e025b61 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Mon, 16 Sep 2002 16:49:45 -0300 Subject: `setmetatable' cannot change protected objects --- lauxlib.c | 11 +++++++++-- lauxlib.h | 3 ++- lbaselib.c | 14 +++++--------- 3 files changed, 16 insertions(+), 12 deletions(-) diff --git a/lauxlib.c b/lauxlib.c index 84d7feaa..3f863602 100644 --- a/lauxlib.c +++ b/lauxlib.c @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.c,v 1.84 2002/08/30 20:00:59 roberto Exp roberto $ +** $Id: lauxlib.c,v 1.85 2002/09/05 19:45:42 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -147,7 +147,7 @@ LUALIB_API lua_Number luaL_opt_number (lua_State *L, int narg, lua_Number def) { } -LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { if (!lua_getmetatable(L, obj)) /* no metatable? */ return 0; lua_pushstring(L, event); @@ -156,6 +156,13 @@ LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { lua_pop(L, 2); /* remove metatable and metafield */ return 0; } + return 1; +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; lua_pushvalue(L, obj); lua_call(L, 1, 1); return 1; diff --git a/lauxlib.h b/lauxlib.h index 7687f25e..f4d42d13 100644 --- a/lauxlib.h +++ b/lauxlib.h @@ -1,5 +1,5 @@ /* -** $Id: lauxlib.h,v 1.52 2002/08/08 20:08:41 roberto Exp roberto $ +** $Id: lauxlib.h,v 1.53 2002/08/30 20:00:59 roberto Exp roberto $ ** Auxiliary functions for building Lua libraries ** See Copyright Notice in lua.h */ @@ -30,6 +30,7 @@ typedef struct luaL_reg { LUALIB_API void luaL_openlib (lua_State *L, const luaL_reg *l, int nup); LUALIB_API void luaL_opennamedlib (lua_State *L, const char *libname, const luaL_reg *l, int nup); +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *e); LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *e); LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname); LUALIB_API int luaL_argerror (lua_State *L, int numarg, const char *extramsg); diff --git a/lbaselib.c b/lbaselib.c index 6baa5ccf..bded9332 100644 --- a/lbaselib.c +++ b/lbaselib.c @@ -1,5 +1,5 @@ /* -** $Id: lbaselib.c,v 1.97 2002/08/08 20:08:41 roberto Exp roberto $ +** $Id: lbaselib.c,v 1.98 2002/09/05 19:45:42 roberto Exp roberto $ ** Basic library ** See Copyright Notice in lua.h */ @@ -109,14 +109,8 @@ static int luaB_getmetatable (lua_State *L) { lua_pushnil(L); return 1; /* no metatable */ } - else { - lua_pushliteral(L, "__metatable"); - lua_rawget(L, -2); - if (lua_isnil(L, -1)) - lua_pop(L, 1); - /* otherwise returns metatable.__metatable */ - } - return 1; + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ } @@ -125,6 +119,8 @@ static int luaB_setmetatable (lua_State *L) { luaL_check_type(L, 1, LUA_TTABLE); luaL_arg_check(L, t == LUA_TNIL || t == LUA_TTABLE, 2, "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); lua_settop(L, 2); lua_setmetatable(L, 1); return 1; -- cgit v1.2.3-55-g6feb