nghttpx: Detect loop in --include paths

This commit is contained in:
Tatsuhiro Tsujikawa 2015-07-13 21:44:06 +09:00
parent f96edbf987
commit fb7775e382
3 changed files with 40 additions and 13 deletions

View File

@ -2030,11 +2030,13 @@ int main(int argc, char **argv) {
} }
if (conf_exists(get_config()->conf_path.get())) { if (conf_exists(get_config()->conf_path.get())) {
if (load_config(get_config()->conf_path.get()) == -1) { std::set<std::string> include_set;
if (load_config(get_config()->conf_path.get(), include_set) == -1) {
LOG(FATAL) << "Failed to load configuration from " LOG(FATAL) << "Failed to load configuration from "
<< get_config()->conf_path.get(); << get_config()->conf_path.get();
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
assert(include_set.empty());
} }
if (argc - optind >= 2) { if (argc - optind >= 2) {
@ -2046,13 +2048,20 @@ int main(int argc, char **argv) {
// parsing option values. // parsing option values.
reopen_log_files(); reopen_log_files();
{
std::set<std::string> include_set;
for (size_t i = 0, len = cmdcfgs.size(); i < len; ++i) { for (size_t i = 0, len = cmdcfgs.size(); i < len; ++i) {
if (parse_config(cmdcfgs[i].first, cmdcfgs[i].second) == -1) { if (parse_config(cmdcfgs[i].first, cmdcfgs[i].second, include_set) ==
-1) {
LOG(FATAL) << "Failed to parse command-line argument."; LOG(FATAL) << "Failed to parse command-line argument.";
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
} }
assert(include_set.empty());
}
if (get_config()->accesslog_syslog || get_config()->errorlog_syslog) { if (get_config()->accesslog_syslog || get_config()->errorlog_syslog) {
openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID, openlog("nghttpx", LOG_NDELAY | LOG_NOWAIT | LOG_PID,
get_config()->syslog_facility); get_config()->syslog_facility);

View File

@ -505,7 +505,8 @@ void parse_mapping(const DownstreamAddr &addr, const char *src) {
} }
} // namespace } // namespace
int parse_config(const char *opt, const char *optarg) { int parse_config(const char *opt, const char *optarg,
std::set<std::string> &included_set) {
char host[NI_MAXHOST]; char host[NI_MAXHOST];
uint16_t port; uint16_t port;
@ -1220,7 +1221,20 @@ int parse_config(const char *opt, const char *optarg) {
} }
if (util::strieq(opt, SHRPX_OPT_INCLUDE)) { if (util::strieq(opt, SHRPX_OPT_INCLUDE)) {
return load_config(optarg); if (included_set.count(optarg)) {
LOG(ERROR) << opt << ": " << optarg << " has already been included";
return -1;
}
included_set.emplace(optarg);
auto rv = load_config(optarg, included_set);
included_set.erase(optarg);
if (rv != 0) {
return -1;
}
return 0;
} }
if (util::strieq(opt, "conf")) { if (util::strieq(opt, "conf")) {
@ -1234,7 +1248,7 @@ int parse_config(const char *opt, const char *optarg) {
return -1; return -1;
} }
int load_config(const char *filename) { int load_config(const char *filename, std::set<std::string> &include_set) {
std::ifstream in(filename, std::ios::binary); std::ifstream in(filename, std::ios::binary);
if (!in) { if (!in) {
LOG(ERROR) << "Could not open config file " << filename; LOG(ERROR) << "Could not open config file " << filename;
@ -1258,7 +1272,7 @@ int load_config(const char *filename) {
} }
line[i] = '\0'; line[i] = '\0';
auto s = line.c_str(); auto s = line.c_str();
if (parse_config(s, s + i + 1) == -1) { if (parse_config(s, s + i + 1, include_set) == -1) {
return -1; return -1;
} }
} }

View File

@ -42,6 +42,7 @@
#include <cstdio> #include <cstdio>
#include <vector> #include <vector>
#include <memory> #include <memory>
#include <set>
#include <openssl/ssl.h> #include <openssl/ssl.h>
@ -379,13 +380,16 @@ void create_config();
// Parses option name |opt| and value |optarg|. The results are // Parses option name |opt| and value |optarg|. The results are
// stored into statically allocated Config object. This function // stored into statically allocated Config object. This function
// returns 0 if it succeeds, or -1. // returns 0 if it succeeds, or -1. The |included_set| contains the
int parse_config(const char *opt, const char *optarg); // all paths already included while processing this configuration, to
// avoid loop in --include option.
int parse_config(const char *opt, const char *optarg,
std::set<std::string> &included_set);
// Loads configurations from |filename| and stores them in statically // Loads configurations from |filename| and stores them in statically
// allocated Config object. This function returns 0 if it succeeds, or // allocated Config object. This function returns 0 if it succeeds, or
// -1. // -1. See parse_config() for |include_set|.
int load_config(const char *filename); int load_config(const char *filename, std::set<std::string> &include_set);
// Read passwd from |filename| // Read passwd from |filename|
std::string read_passwd_from_file(const char *filename); std::string read_passwd_from_file(const char *filename);