Skip to content

Commit

Permalink
allow .. in relative filenames in wesnoth.dofile/require
Browse files Browse the repository at this point in the history
This changes the lua loadfile code to store relative filenames (like
~add-ons/campaign1/lua/code.lua) the in descriptions attributes of lua
codechunks. This not only makes the lua error messages easier to read
(previously: 'error in C:\users\... ...ign1/lua/code.lua", now: "Error
in ~add-ons/campaign1/lua/code.lua").
This also removes the possiblity for wml authors to query the wesnoth
install directory path by using lua debug functions.

We have to use a custom function resolve_filename() to resolve filenames
that begin with "./" becasue get_wml_location() expects a abolsute
directoy ("C:\users\....") as second parameter, and i didnt want to
change it becasue it is also used by the wml proprocessor which i don't
want to look at right now.

Since i had to write a custom function resolve_filename() function
anyway i decided to also put support for ../ and  ./ in it, note that
the results is passed to get_wml_location() anyway so all security
checks that were there previously are still there.
  • Loading branch information
gfgtdf committed Feb 18, 2016
1 parent 3e2dfed commit 322a2f7
Showing 1 changed file with 55 additions and 6 deletions.
61 changes: 55 additions & 6 deletions src/scripting/lua_fileops.cpp
Expand Up @@ -26,6 +26,7 @@
#include <string>

#include <boost/scoped_ptr.hpp>
#include <boost/algorithm/string/predicate.hpp>

#include "lua/lauxlib.h"
#include "lua/lua.h"
Expand All @@ -38,6 +39,53 @@ static lg::log_domain log_scripting_lua("scripting/lua");
#define ERR_LUA LOG_STREAM(err, log_scripting_lua)

namespace lua_fileops {
/// resolves @a filename where @a currentdir is the current directory, note that @a currentdir
/// is no absolute directory
/// @returns true iff the filename was sucesful resolved.
static bool resolve_filename(std::string& filename, const std::string& currentdir)
{
if(filename.size() < 2) {
return false;
}
if(filename[0] == '.' && filename[1] == '/') {
filename = currentdir + filename.substr(1);
}
if(std::find(filename.begin(), filename.end(), '\\') != filename.end()) {
return false;
}
//resolve /./
while(true) {
size_t pos = filename.find("/./");
if(pos == std::string::npos) {
break;
}
filename = filename.replace(pos, 2, "");
}
//resolve //
while(true) {
size_t pos = filename.find("//");
if(pos == std::string::npos) {
break;
}
filename = filename.replace(pos, 1, "");
}
//resolve /../
while(true) {
size_t pos = filename.find("/..");
if(pos == std::string::npos) {
break;
}
size_t pos2 = filename.find_last_of('/', pos - 1);
if(pos == std::string::npos || pos2 >= pos) {
return false;
}
filename = filename.replace(pos2, pos- pos2 + 3, "");
}
if(filename.find("..") != std::string::npos) {
return false;
}
return true;
}

/**
* Checks if a file exists (not necessarily a Lua script).
Expand Down Expand Up @@ -83,10 +131,9 @@ class lua_filestream

static int lua_loadfile(lua_State *L, const std::string& fname, const std::string& relativename)
{
UNUSED(relativename);
lua_filestream lfs(fname);
//lua uses '@' to know that this is a file (as opposed to something loaded via loadstring )
std::string chunkname = '@' + fname;
std::string chunkname = '@' + relativename;
LOG_LUA << "starting to read from " << fname << "\n";
return lua_load(L, &lua_filestream::lua_read_data, &lfs, chunkname.c_str(), NULL);
}
Expand All @@ -109,14 +156,16 @@ int load_file(lua_State *L)
if(lua_getstack(L, 1, &ar)) {
lua_getinfo(L, "S", &ar);
if(ar.source[0] == '@') {
// TODO: i don't think it is possible to lua change the .source field by lua but i would still be good if ar.source would contains a relative string (~add-ons/...) which get_wml_location would then expand.
current_dir = filesystem::directory_name(std::string(ar.source + 1));
}
}
std::string p = filesystem::get_wml_location(m, current_dir);
if (p.empty())
if(!resolve_filename(m, current_dir)) {
return luaL_argerror(L, -1, "file not found");

}
std::string p = filesystem::get_wml_location(m);
if (p.empty()) {
return luaL_argerror(L, -1, "file not found");
}
#if 1
try
{
Expand Down

0 comments on commit 322a2f7

Please sign in to comment.