Disallow accessing files whose names are in the default ignore list
This commit is contained in:
parent
eed3927d12
commit
c5e972b8b4
7 changed files with 61 additions and 21 deletions
|
@ -89,6 +89,8 @@ public:
|
|||
directory_patterns_.push_back(pattern);
|
||||
}
|
||||
|
||||
void remove_blacklisted_files_and_dirs(std::vector<std::string>& files, std::vector<std::string>& directories) const;
|
||||
|
||||
private:
|
||||
std::vector<std::string> file_patterns_;
|
||||
std::vector<std::string> directory_patterns_;
|
||||
|
@ -97,7 +99,7 @@ private:
|
|||
static const blacklist_pattern_list default_blacklist{
|
||||
{
|
||||
/* Blacklist dot-files/dirs, which are hidden files in UNIX platforms */
|
||||
".*",
|
||||
".+",
|
||||
"#*#",
|
||||
"*~",
|
||||
"*-bak",
|
||||
|
@ -122,7 +124,7 @@ static const blacklist_pattern_list default_blacklist{
|
|||
"*.project",
|
||||
},
|
||||
{
|
||||
".*",
|
||||
".+",
|
||||
/* macOS metadata-like cruft (http://floatingsun.net/2007/02/07/whats-with-__macosx-in-zip-files/) */
|
||||
"__MACOSX",
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <boost/iostreams/device/file_descriptor.hpp>
|
||||
#include <boost/iostreams/stream.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <algorithm>
|
||||
#include <set>
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -1135,27 +1136,34 @@ void clear_binary_paths_cache()
|
|||
binary_paths_cache.clear();
|
||||
}
|
||||
|
||||
static bool is_legal_file(const std::string &filename)
|
||||
static bool is_legal_file(const std::string &filename_str)
|
||||
{
|
||||
DBG_FS << "Looking for '" << filename << "'.\n";
|
||||
DBG_FS << "Looking for '" << filename_str << "'.\n";
|
||||
|
||||
if (filename.empty()) {
|
||||
if(filename_str.empty()) {
|
||||
LOG_FS << " invalid filename\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filename.find("..") != std::string::npos) {
|
||||
ERR_FS << "Illegal path '" << filename << "' (\"..\" not allowed).\n";
|
||||
if(filename_str.find("..") != std::string::npos) {
|
||||
ERR_FS << "Illegal path '" << filename_str << "' (\"..\" not allowed).\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filename.find('\\') != std::string::npos) {
|
||||
ERR_FS << "Illegal path '" << filename << R"end(' ("\" not allowed, for compatibility with GNU/Linux and macOS).)end" << std::endl;
|
||||
if(filename_str.find('\\') != std::string::npos) {
|
||||
ERR_FS << "Illegal path '" << filename_str << R"end(' ("\" not allowed, for compatibility with GNU/Linux and macOS).)end" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (looks_like_pbl(filename)) {
|
||||
ERR_FS << "Illegal path '" << filename << "' (.pbl files are not allowed)." << std::endl;
|
||||
path filepath(filename_str);
|
||||
|
||||
if(default_blacklist.match_file(filepath.filename().string())) {
|
||||
ERR_FS << "Illegal path '" << filename_str << "' (blacklisted filename)." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(std::any_of(filepath.begin(), filepath.end(), [](const path& dirname) { return default_blacklist.match_dir(dirname.string()); })) {
|
||||
ERR_FS << "Illegal path '" << filename_str << "' (blacklisted directory name)." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,16 @@ static lg::log_domain log_filesystem("filesystem");
|
|||
namespace filesystem
|
||||
{
|
||||
|
||||
void blacklist_pattern_list::remove_blacklisted_files_and_dirs(std::vector<std::string>& files, std::vector<std::string>& directories) const
|
||||
{
|
||||
files.erase(
|
||||
std::remove_if(files.begin(), files.end(), [this](const std::string& name) { return match_file(name); }),
|
||||
files.end());
|
||||
directories.erase(
|
||||
std::remove_if(directories.begin(), directories.end(), [this](const std::string& name) { return match_dir(name); }),
|
||||
directories.end());
|
||||
}
|
||||
|
||||
std::string get_prefs_file()
|
||||
{
|
||||
return get_user_config_dir() + "/preferences";
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "scripting/lua_common.hpp" // for chat_message, luaW_pcall
|
||||
#include "scripting/push_check.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
|
@ -149,6 +150,7 @@ int intf_read_file(lua_State *L)
|
|||
if(filesystem::is_directory(p)) {
|
||||
std::vector<std::string> files, dirs;
|
||||
filesystem::get_files_in_dir(p, &files, &dirs);
|
||||
filesystem::default_blacklist.remove_blacklisted_files_and_dirs(files, dirs);
|
||||
size_t ndirs = dirs.size();
|
||||
std::copy(files.begin(), files.end(), std::back_inserter(dirs));
|
||||
lua_push(L, dirs);
|
||||
|
|
|
@ -701,17 +701,23 @@ bool word_match(const std::string& message, const std::string& word) {
|
|||
}
|
||||
|
||||
bool wildcard_string_match(const std::string& str, const std::string& match) {
|
||||
const bool wild_matching = (!match.empty() && match[0] == '*');
|
||||
const std::string::size_type solid_begin = match.find_first_not_of('*');
|
||||
const bool wild_matching = (!match.empty() && (match[0] == '*' || match[0] == '+'));
|
||||
const std::string::size_type solid_begin = match.find_first_not_of("*+");
|
||||
const bool have_solids = (solid_begin != std::string::npos);
|
||||
// Check the simple case first
|
||||
if(str.empty() || !have_solids) {
|
||||
return wild_matching || str == match;
|
||||
// Check the simple cases first
|
||||
if(!have_solids) {
|
||||
const std::string::size_type plus_count = std::count(match.begin(), match.end(), '+');
|
||||
return match.empty() ? str.empty() : str.length() >= plus_count;
|
||||
} else if(str.empty()) {
|
||||
return false;
|
||||
}
|
||||
const std::string::size_type solid_end = match.find_first_of('*', solid_begin);
|
||||
|
||||
const std::string::size_type solid_end = match.find_first_of("*+", solid_begin);
|
||||
const std::string::size_type solid_len = (solid_end == std::string::npos)
|
||||
? match.length() - solid_begin : solid_end - solid_begin;
|
||||
std::string::size_type current = 0;
|
||||
// Since + always consumes at least one character, increment current if the match
|
||||
// begins with one
|
||||
std::string::size_type current = match[0] == '+' ? 1 : 0;
|
||||
bool matches;
|
||||
do {
|
||||
matches = true;
|
||||
|
|
|
@ -321,8 +321,8 @@ bool word_completion(std::string& text, std::vector<std::string>& wordlist);
|
|||
bool word_match(const std::string& message, const std::string& word);
|
||||
|
||||
/**
|
||||
* Match using '*' as any number of characters (including none), and '?' as any
|
||||
* one character.
|
||||
* Match using '*' as any number of characters (including none),
|
||||
* '+' as one or more characters, and '?' as any one character.
|
||||
*/
|
||||
bool wildcard_string_match(const std::string& str, const std::string& match);
|
||||
|
||||
|
|
|
@ -106,12 +106,16 @@ BOOST_AUTO_TEST_CASE( test_wildcard_string_match )
|
|||
const std::string str = "foo bar baz";
|
||||
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, "*bar*"));
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, "+bar+"));
|
||||
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, "*BAR*"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, "+BAR+"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, "bar"));
|
||||
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, "*ba? b*"));
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, "+ba? b+"));
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, "*?a?*"));
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, "+?a?+"));
|
||||
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, "foo? "));
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, "?foo"));
|
||||
|
@ -126,11 +130,19 @@ BOOST_AUTO_TEST_CASE( test_wildcard_string_match )
|
|||
BOOST_CHECK(utils::wildcard_string_match(str, superfluous_mask));
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, superfluous_mask + '*'));
|
||||
|
||||
superfluous_mask = std::string(str.length(), '+');
|
||||
BOOST_CHECK(utils::wildcard_string_match(str, superfluous_mask));
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, superfluous_mask + '+'));
|
||||
|
||||
BOOST_CHECK(utils::wildcard_string_match("", ""));
|
||||
BOOST_CHECK(!utils::wildcard_string_match(str, ""));
|
||||
|
||||
BOOST_CHECK(utils::wildcard_string_match("", "*"));
|
||||
BOOST_CHECK(utils::wildcard_string_match("", "***?**"));
|
||||
BOOST_CHECK(utils::wildcard_string_match("", "***"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match("", "+"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match("", "*bar"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match("", "***?**"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match("", "+++?++"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match("", "?"));
|
||||
BOOST_CHECK(!utils::wildcard_string_match("", "???"));
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue