按源保护 PythonPlugin 路径列表边界
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include <cstring>
|
||||
#include <limits.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
|
||||
// LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc provides the
|
||||
@@ -31,13 +32,13 @@ std::string trim_ini_value(std::string value) {
|
||||
return std::string(first, last);
|
||||
}
|
||||
|
||||
bool find_ini_value(const char *iniFilename,
|
||||
const char *section,
|
||||
const char *key,
|
||||
std::string &value) {
|
||||
std::vector<std::string> find_ini_values(const char *iniFilename,
|
||||
const char *section,
|
||||
const char *key) {
|
||||
std::vector<std::string> values;
|
||||
FILE *file = std::fopen(iniFilename, "r");
|
||||
if (!file) {
|
||||
return false;
|
||||
return values;
|
||||
}
|
||||
|
||||
bool in_section = false;
|
||||
@@ -59,14 +60,55 @@ bool find_ini_value(const char *iniFilename,
|
||||
continue;
|
||||
}
|
||||
if (trim_ini_value(text.substr(0, equals)) == key) {
|
||||
value = trim_ini_value(text.substr(equals + 1));
|
||||
std::fclose(file);
|
||||
return true;
|
||||
values.push_back(trim_ini_value(text.substr(equals + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
std::fclose(file);
|
||||
return false;
|
||||
return values;
|
||||
}
|
||||
|
||||
bool find_ini_value(const char *iniFilename,
|
||||
const char *section,
|
||||
const char *key,
|
||||
std::string &value) {
|
||||
const std::vector<std::string> values = find_ini_values(iniFilename, section, key);
|
||||
if (values.empty()) {
|
||||
return false;
|
||||
}
|
||||
value = values.front();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool tilde_expand_path(const std::string &path, std::string &expanded) {
|
||||
// LinuxCNC source basis: IniFile::tildeExpand() copies non-"~/" paths and
|
||||
// returns failure for "~/" paths when HOME is unavailable.
|
||||
if (path.size() < 2 || path[0] != '~' || path[1] != '/') {
|
||||
expanded = path;
|
||||
return true;
|
||||
}
|
||||
const char *home = std::getenv("HOME");
|
||||
if (!home) {
|
||||
return false;
|
||||
}
|
||||
expanded = std::string(home) + path.substr(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
int check_python_path_entries(const char *iniFilename,
|
||||
const char *key,
|
||||
pp_status failure_status) {
|
||||
for (const std::string &entry : find_ini_values(iniFilename, "PYTHON", key)) {
|
||||
std::string expanded;
|
||||
// LinuxCNC source basis: python_plugin.cc configure() runs
|
||||
// TildeExpansion on [PYTHON] PATH_PREPEND/PATH_APPEND before
|
||||
// PyRun_SimpleString(); browser-safe probes preserve the expansion
|
||||
// failure status without executing Python path mutation.
|
||||
if (!tilde_expand_path(entry, expanded)) {
|
||||
return failure_status;
|
||||
}
|
||||
}
|
||||
return PLUGIN_OK;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -115,6 +157,21 @@ int PythonPlugin::configure(const char *iniFilename, const char *section) {
|
||||
}
|
||||
}
|
||||
|
||||
status = check_python_path_entries(iniFilename,
|
||||
"PATH_PREPEND",
|
||||
PLUGIN_EXCEPTION_DURING_PATH_PREPEND);
|
||||
if (status != PLUGIN_OK) {
|
||||
error_msg = "bad path prepend";
|
||||
return status;
|
||||
}
|
||||
status = check_python_path_entries(iniFilename,
|
||||
"PATH_APPEND",
|
||||
PLUGIN_EXCEPTION_DURING_PATH_APPEND);
|
||||
if (status != PLUGIN_OK) {
|
||||
error_msg = "bad path append";
|
||||
return status;
|
||||
}
|
||||
|
||||
return initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
#include <string>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
@@ -86,6 +87,102 @@ int main() {
|
||||
return 36;
|
||||
}
|
||||
std::remove(bad_path_ini);
|
||||
const char *path_prepend_ini = "/tmp/cnc_sim_python_plugin_probe_path_prepend.ini";
|
||||
{
|
||||
FILE *file = std::fopen(path_prepend_ini, "w");
|
||||
if (!file) {
|
||||
std::remove(ini);
|
||||
return 37;
|
||||
}
|
||||
std::fputs("[PYTHON]\nPATH_PREPEND = ~/linuxcnc-python\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
const char *saved_home = std::getenv("HOME");
|
||||
const std::string saved_home_value = saved_home ? saved_home : "";
|
||||
unsetenv("HOME");
|
||||
if (plugin->configure(path_prepend_ini, "PYTHON") != PLUGIN_EXCEPTION_DURING_PATH_PREPEND) {
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(ini);
|
||||
std::remove(path_prepend_ini);
|
||||
return 38;
|
||||
}
|
||||
if (plugin->usable()) {
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(ini);
|
||||
std::remove(path_prepend_ini);
|
||||
return 39;
|
||||
}
|
||||
if (plugin->last_errmsg() != "bad path prepend") {
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(ini);
|
||||
std::remove(path_prepend_ini);
|
||||
return 40;
|
||||
}
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(path_prepend_ini);
|
||||
const char *path_append_ini = "/tmp/cnc_sim_python_plugin_probe_path_append.ini";
|
||||
{
|
||||
FILE *file = std::fopen(path_append_ini, "w");
|
||||
if (!file) {
|
||||
std::remove(ini);
|
||||
return 41;
|
||||
}
|
||||
std::fputs("[PYTHON]\nPATH_APPEND = ~/linuxcnc-python\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
unsetenv("HOME");
|
||||
if (plugin->configure(path_append_ini, "PYTHON") != PLUGIN_EXCEPTION_DURING_PATH_APPEND) {
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(ini);
|
||||
std::remove(path_append_ini);
|
||||
return 42;
|
||||
}
|
||||
if (plugin->usable()) {
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(ini);
|
||||
std::remove(path_append_ini);
|
||||
return 43;
|
||||
}
|
||||
if (plugin->last_errmsg() != "bad path append") {
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(ini);
|
||||
std::remove(path_append_ini);
|
||||
return 44;
|
||||
}
|
||||
if (saved_home) {
|
||||
setenv("HOME", saved_home_value.c_str(), 1);
|
||||
}
|
||||
std::remove(path_append_ini);
|
||||
const char *plain_path_ini = "/tmp/cnc_sim_python_plugin_probe_plain_path.ini";
|
||||
{
|
||||
FILE *file = std::fopen(plain_path_ini, "w");
|
||||
if (!file) {
|
||||
std::remove(ini);
|
||||
return 45;
|
||||
}
|
||||
std::fputs("[PYTHON]\nPATH_PREPEND = /tmp\nPATH_APPEND = /tmp\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
if (plugin->configure(plain_path_ini, "PYTHON") != PLUGIN_PYTHON_NOT_INITIALIZED) {
|
||||
std::remove(ini);
|
||||
std::remove(plain_path_ini);
|
||||
return 46;
|
||||
}
|
||||
std::remove(plain_path_ini);
|
||||
setenv("INI_FILE_NAME", ini, 1);
|
||||
if (plugin->configure(nullptr, "PYTHON") != PLUGIN_PYTHON_NOT_INITIALIZED) {
|
||||
std::remove(ini);
|
||||
|
||||
Reference in New Issue
Block a user