From d768c51cda194446e215242432ee19b1f15bf67b Mon Sep 17 00:00:00 2001 From: blumf Date: Mon, 4 Jul 2016 14:06:55 +0100 Subject: [PATCH] BUG: Referencing value after it's popped off stack --- src/luasql.c | 458 ++++++++++++++++++++++++++------------------------- 1 file changed, 233 insertions(+), 225 deletions(-) diff --git a/src/luasql.c b/src/luasql.c index 7a0d926..a170c35 100644 --- a/src/luasql.c +++ b/src/luasql.c @@ -1,225 +1,233 @@ -/* -** $Id: luasql.c,v 1.28 2009/02/11 12:08:50 tomas Exp $ -** See Copyright Notice in license.html -*/ - -#include - -#include "lua.h" -#include "lauxlib.h" - - -#include "luasql.h" - -#if !defined(lua_pushliteral) -#define lua_pushliteral(L, s) \ - lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1) -#endif - - -/* -** Typical database error situation -*/ -LUASQL_API int luasql_faildirect(lua_State *L, const char *err) { - lua_pushnil(L); - lua_pushliteral(L, LUASQL_PREFIX); - lua_pushstring(L, err); - lua_concat(L, 2); - return 2; -} - - -/* -** Database error with LuaSQL message -** @param err LuaSQL error message. -** @param m Driver error message. -*/ -LUASQL_API int luasql_failmsg(lua_State *L, const char *err, const char *m) { - lua_pushnil(L); - lua_pushliteral(L, LUASQL_PREFIX); - lua_pushstring(L, err); - lua_pushstring(L, m); - lua_concat(L, 3); - return 2; -} - - -typedef struct { short closed; } pseudo_data; - -/* -** Return the name of the object's metatable. -** This function is used by `tostring'. -*/ -static int luasql_tostring (lua_State *L) { - pseudo_data *obj = (pseudo_data *)lua_touserdata (L, 1); - - if (obj->closed) { - lua_pushfstring (L, "%s (closed)", lua_tostring(L,lua_upvalueindex(1))); - } else { - lua_pushfstring (L, "%s (%p)", lua_tostring(L,lua_upvalueindex(1)), (void *)obj); - } - - return 1; -} - - -#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 -/* -** Adapted from Lua 5.2.0 -*/ -void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { - luaL_checkstack(L, nup+1, "too many upvalues"); - for (; l->name != NULL; l++) { /* fill the table with given functions */ - int i; - lua_pushstring(L, l->name); - for (i = 0; i < nup; i++) /* copy upvalues to the top */ - lua_pushvalue(L, -(nup + 1)); - lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ - lua_settable(L, -(nup + 3)); - } - lua_pop(L, nup); /* remove upvalues */ -} -#endif - -/* -** Create a metatable and leave it on top of the stack. -*/ -LUASQL_API int luasql_createmeta (lua_State *L, const char *name, const luaL_Reg *methods) { - if (!luaL_newmetatable (L, name)) - return 0; - - /* define methods */ - luaL_setfuncs (L, methods, 0); - - /* define metamethods */ - lua_pushliteral (L, "__index"); - lua_pushvalue (L, -2); - lua_settable (L, -3); - - lua_pushliteral (L, "__tostring"); - lua_pushstring (L, name); - lua_pushcclosure (L, luasql_tostring, 1); - lua_settable (L, -3); - - lua_pushliteral (L, "__metatable"); - lua_pushliteral (L, LUASQL_PREFIX"you're not allowed to get this metatable"); - lua_settable (L, -3); - - return 1; -} - - -/* -** Define the metatable for the object on top of the stack -*/ -LUASQL_API void luasql_setmeta (lua_State *L, const char *name) { - luaL_getmetatable (L, name); - lua_setmetatable (L, -2); -} - - -/* -** Assumes the table is on top of the stack. -*/ -LUASQL_API void luasql_set_info (lua_State *L) { - lua_pushliteral (L, "_COPYRIGHT"); - lua_pushliteral (L, "Copyright (C) 2003-2015 Kepler Project"); - lua_settable (L, -3); - lua_pushliteral (L, "_DESCRIPTION"); - lua_pushliteral (L, "LuaSQL is a simple interface from Lua to a DBMS"); - lua_settable (L, -3); - lua_pushliteral (L, "_VERSION"); - lua_pushliteral (L, "LuaSQL 3.0.0"); - lua_settable (L, -3); -} - -/* -** Finds a pre-existing LuaSQL table, or creates a new one. -*/ -LUASQL_API void luasql_find_driver_table (lua_State *L) { - lua_getglobal(L, "package"); - if(lua_istable(L, -1)) { - lua_getfield(L, -1, "loaded"); - lua_remove(L, -2); - - lua_pushnil(L); - while(lua_next(L, -2) != 0) { - const char *key = lua_tostring(L, -2); - if(strncmp(key, LUASQL_TABLENAME, strlen(LUASQL_TABLENAME)) == 0) { - lua_remove(L, -2); - lua_remove(L, -2); - return; - } - - lua_pop(L, 1); - } - lua_pop(L, 2); - } else { - lua_pop(L, 1); - } - - lua_newtable (L); -} - -/* -** registers a driver, taking account of the Lua version differences -** Lua Returns: -** The new/existing 'luasql' driver table on the top of the stack -*/ -LUASQL_API void luasql_reg_driver (lua_State *L, const luaL_Reg *driver) -{ -#if LUA_VERSION_NUM<=501 - luaL_register (L, LUASQL_TABLENAME, driver); -#else - luasql_find_driver_table (L); - luaL_setfuncs (L, driver, 0); -#endif - luasql_set_info (L); -} - -LUASQL_API const char* luasql_table_optstring(lua_State *L, int idx, const char* name, const char* def) { - const char* res = NULL; - - lua_pushstring(L, name); - lua_gettable(L, idx); - - res = lua_tostring(L, -1); - lua_pop(L, 1); - - return (res != NULL) ? res : def; -} - - -LUASQL_API lua_Number luasql_table_optnumber(lua_State *L, int idx, const char* name, lua_Number def) { - lua_Number res = 0; - - lua_pushstring(L, name); - lua_gettable(L, idx); - - res = lua_tonumber(L, -1); - lua_pop(L, 1); - - return lua_isnumber(L, -1) ? res : def; -} - -/* -** Registers a given C object in the registry to avoid GC -*/ -void luasql_registerobj(lua_State *L, int index, void *obj) -{ - lua_pushvalue(L, index); - lua_pushlightuserdata(L, obj); - lua_pushvalue(L, -2); - lua_settable(L, LUA_REGISTRYINDEX); - lua_pop(L, 1); -} - -/* -** Unregisters a given C object from the registry -*/ -void luasql_unregisterobj(lua_State *L, void *obj) -{ - lua_pushlightuserdata(L, obj); - lua_pushnil(L); - lua_settable(L, LUA_REGISTRYINDEX); -} +/* +** $Id: luasql.c,v 1.28 2009/02/11 12:08:50 tomas Exp $ +** See Copyright Notice in license.html +*/ + +#include + +#include "lua.h" +#include "lauxlib.h" + + +#include "luasql.h" + +#if !defined(lua_pushliteral) +#define lua_pushliteral(L, s) \ + lua_pushstring(L, "" s, (sizeof(s)/sizeof(char))-1) +#endif + + +/* +** Typical database error situation +*/ +LUASQL_API int luasql_faildirect(lua_State *L, const char *err) { + lua_pushnil(L); + lua_pushliteral(L, LUASQL_PREFIX); + lua_pushstring(L, err); + lua_concat(L, 2); + return 2; +} + + +/* +** Database error with LuaSQL message +** @param err LuaSQL error message. +** @param m Driver error message. +*/ +LUASQL_API int luasql_failmsg(lua_State *L, const char *err, const char *m) { + lua_pushnil(L); + lua_pushliteral(L, LUASQL_PREFIX); + lua_pushstring(L, err); + lua_pushstring(L, m); + lua_concat(L, 3); + return 2; +} + + +typedef struct { short closed; } pseudo_data; + +/* +** Return the name of the object's metatable. +** This function is used by `tostring'. +*/ +static int luasql_tostring (lua_State *L) { + pseudo_data *obj = (pseudo_data *)lua_touserdata (L, 1); + + if (obj->closed) { + lua_pushfstring (L, "%s (closed)", lua_tostring(L,lua_upvalueindex(1))); + } else { + lua_pushfstring (L, "%s (%p)", lua_tostring(L,lua_upvalueindex(1)), (void *)obj); + } + + return 1; +} + + +#if !defined LUA_VERSION_NUM || LUA_VERSION_NUM==501 +/* +** Adapted from Lua 5.2.0 +*/ +void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup+1, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + lua_pushstring(L, l->name); + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -(nup + 1)); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_settable(L, -(nup + 3)); + } + lua_pop(L, nup); /* remove upvalues */ +} +#endif + +/* +** Create a metatable and leave it on top of the stack. +*/ +LUASQL_API int luasql_createmeta (lua_State *L, const char *name, const luaL_Reg *methods) { + if (!luaL_newmetatable (L, name)) + return 0; + + /* define methods */ + luaL_setfuncs (L, methods, 0); + + /* define metamethods */ + lua_pushliteral (L, "__index"); + lua_pushvalue (L, -2); + lua_settable (L, -3); + + lua_pushliteral (L, "__tostring"); + lua_pushstring (L, name); + lua_pushcclosure (L, luasql_tostring, 1); + lua_settable (L, -3); + + lua_pushliteral (L, "__metatable"); + lua_pushliteral (L, LUASQL_PREFIX"you're not allowed to get this metatable"); + lua_settable (L, -3); + + return 1; +} + + +/* +** Define the metatable for the object on top of the stack +*/ +LUASQL_API void luasql_setmeta (lua_State *L, const char *name) { + luaL_getmetatable (L, name); + lua_setmetatable (L, -2); +} + + +/* +** Assumes the table is on top of the stack. +*/ +LUASQL_API void luasql_set_info (lua_State *L) { + lua_pushliteral (L, "_COPYRIGHT"); + lua_pushliteral (L, "Copyright (C) 2003-2015 Kepler Project"); + lua_settable (L, -3); + lua_pushliteral (L, "_DESCRIPTION"); + lua_pushliteral (L, "LuaSQL is a simple interface from Lua to a DBMS"); + lua_settable (L, -3); + lua_pushliteral (L, "_VERSION"); + lua_pushliteral (L, "LuaSQL 3.0.0"); + lua_settable (L, -3); +} + +/* +** Finds a pre-existing LuaSQL table, or creates a new one. +*/ +LUASQL_API void luasql_find_driver_table (lua_State *L) { + lua_getglobal(L, "package"); + if(lua_istable(L, -1)) { + lua_getfield(L, -1, "loaded"); + lua_remove(L, -2); + + lua_pushnil(L); + while(lua_next(L, -2) != 0) { + const char *key = lua_tostring(L, -2); + if(strncmp(key, LUASQL_TABLENAME, strlen(LUASQL_TABLENAME)) == 0) { + lua_remove(L, -2); + lua_remove(L, -2); + return; + } + + lua_pop(L, 1); + } + lua_pop(L, 2); + } else { + lua_pop(L, 1); + } + + lua_newtable (L); +} + +/* +** registers a driver, taking account of the Lua version differences +** Lua Returns: +** The new/existing 'luasql' driver table on the top of the stack +*/ +LUASQL_API void luasql_reg_driver (lua_State *L, const luaL_Reg *driver) +{ +#if LUA_VERSION_NUM<=501 + luaL_register (L, LUASQL_TABLENAME, driver); +#else + luasql_find_driver_table (L); + luaL_setfuncs (L, driver, 0); +#endif + luasql_set_info (L); +} + +/* +** Pulls an optional string value from the table at idx +*/ +LUASQL_API const char* luasql_table_optstring(lua_State *L, int idx, const char* name, const char* def) { + const char* res = NULL; + + lua_pushstring(L, name); + lua_gettable(L, idx); + + res = lua_tostring(L, -1); + lua_pop(L, 1); + + return (res != NULL) ? res : def; +} + + +/* +** Pulls an optional number value from the table at idx +*/ +LUASQL_API lua_Number luasql_table_optnumber(lua_State *L, int idx, const char* name, lua_Number def) { + lua_Number res = def; + + lua_pushstring(L, name); + lua_gettable(L, idx); + + if(lua_isnumber(L, -1)) { + res = lua_tonumber(L, -1); + } + lua_pop(L, 1); + + return res; +} + +/* +** Registers a given C object in the registry to avoid GC +*/ +void luasql_registerobj(lua_State *L, int index, void *obj) +{ + lua_pushvalue(L, index); + lua_pushlightuserdata(L, obj); + lua_pushvalue(L, -2); + lua_settable(L, LUA_REGISTRYINDEX); + lua_pop(L, 1); +} + +/* +** Unregisters a given C object from the registry +*/ +void luasql_unregisterobj(lua_State *L, void *obj) +{ + lua_pushlightuserdata(L, obj); + lua_pushnil(L); + lua_settable(L, LUA_REGISTRYINDEX); +}