]> granicus.if.org Git - pdns/commitdiff
fix leaving table on the lua stack while waiting for answers
authorbert hubert <bert.hubert@powerdns.com>
Mon, 26 Oct 2015 13:53:09 +0000 (14:53 +0100)
committerbert hubert <bert.hubert@powerdns.com>
Mon, 26 Oct 2015 13:53:09 +0000 (14:53 +0100)
pdns/lua-pdns.cc
pdns/lua-pdns.hh
pdns/lua-recursor.cc

index ae59864bddcfeaf3e0795b5189b4698ded520694..18e955260bb05f91ffb7532a31799efbb0e95be8 100644 (file)
@@ -85,6 +85,46 @@ static bool getFromTable(lua_State *lua, const std::string &key, uint32_t& value
 }
 
 
+void pushLuaTable(lua_State* lua, const vector<pair<string,string>>& table)
+{
+  lua_newtable(lua);
+  int pos=0;
+  for(const auto& e : table) {
+    lua_pushstring(lua, e.second.c_str());
+    lua_setfield(lua, -2, e.first.c_str());
+  }
+}
+
+vector<pair<string,string>> getLuaTable(lua_State* lua, int index)
+{
+  vector<pair<string,string>> ret;
+  // Push another reference to the table on top of the stack (so we know
+  // where it is, and this function can work for negative, positive and
+  // pseudo indices
+  lua_pushvalue(lua, index);
+  // stack now contains: -1 => table
+  lua_pushnil(lua);
+  // stack now contains: -1 => nil; -2 => table
+  while (lua_next(lua, -2)) {
+    // stack now contains: -1 => value; -2 => key; -3 => table
+    // copy the key so that lua_tostring does not modify the original
+    lua_pushvalue(lua, -2);
+    // stack now contains: -1 => key; -2 => value; -3 => key; -4 => table
+    const char *key = lua_tostring(lua, -1);
+    const char *value = lua_tostring(lua, -2);
+    ret.push_back({key,value});
+    // pop value + copy of key, leaving original key
+    lua_pop(lua, 2);
+    // stack now contains: -1 => key; -2 => table
+  }
+  // stack now contains: -1 => table (when lua_next returns 0 it pops the key
+  // but does not push anything.)
+  // Pop table
+  lua_pop(lua, 1);
+  // Stack is now the same as it was on entry to this function
+  return ret;
+}
+
 
 void pushResourceRecordsTable(lua_State* lua, const vector<DNSRecord>& records)
 {
index 07e394bc2f726512fa6a5308ed1e4c13785ce47d..0b71b18264772166e7b18f3a68ca9bd88cbbf6c6 100644 (file)
@@ -37,6 +37,8 @@ void pushResourceRecordsTable(lua_State* lua, const vector<DNSRecord>& records);
 void popResourceRecordsTable(lua_State *lua, const DNSName &query, vector<DNSRecord>& ret);
 void pushSyslogSecurityLevelTable(lua_State *lua);
 int getLuaTableLength(lua_State* lua, int depth);
+std::vector<std::pair<std::string, std::string>> getLuaTable(lua_State* lua, int index=0);
+void pushLuaTable(lua_State* lua, const vector<pair<string,string>>& table);
 void luaStackDump (lua_State *lua);
 extern "C" int luaopen_iputils(lua_State*);
 #endif
index 09cbd9f6cfd5dbfec91023453195bcd6d288dc84..2726f40532121eaabcacd3865894ad09017d13c2 100644 (file)
@@ -288,9 +288,8 @@ bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, co
       string callback;
       getFromTable("callback", callback);
 
-      lua_remove(d_lua, -2);
-
-      // XXX THIS IS PLAIN WRONG - WE LEAVE STUFF ON THE LUA STACK AND EXPECT IT TO STILL BE HERE WHEN WE GET BACK!
+      auto table = getLuaTable(d_lua, -1);
+      lua_pop(d_lua, 2);
       string answer = GenUDPQueryResponse(ComboAddress(dest), uquery);
 
       lua_getglobal(d_lua,  callback.c_str());
@@ -298,12 +297,8 @@ bool RecursorLua::passthrough(const string& func, const ComboAddress& remote, co
       lua_pushstring(d_lua,  remote.toString().c_str() );
       lua_pushstring(d_lua,  query.toString().c_str() );
       lua_pushnumber(d_lua,  qtype.getCode() );
-
-      lua_pushvalue(d_lua, -5);
-      lua_remove(d_lua, -6);
-
-      lua_pushstring(d_lua, answer.c_str());
-      lua_setfield(d_lua, -2, "response");
+      table.push_back({"response", answer});
+      pushLuaTable(d_lua, table);
 
       if(lua_pcall(d_lua,  4, 3, 0)) {   // NOTE! Means we always get 3 stack entries back, no matter what our lua hook returned!
        string error=string("lua error in '"+func+"' while callback for '"+query.toString()+"|"+qtype.getName()+": ")+lua_tostring(d_lua, -1);