按源保护 PythonPlugin TOPLEVEL 路径边界
This commit is contained in:
@@ -1,7 +1,12 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <limits.h>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
// LinuxCNC source basis: src/emc/pythonplugin/python_plugin.cc provides the
|
||||
// native PythonPlugin implementation called by RS274 Python/remap paths.
|
||||
@@ -11,6 +16,61 @@ __attribute__((weak)) std::string handle_pyerror() {
|
||||
|
||||
PythonPlugin *python_plugin = nullptr;
|
||||
|
||||
namespace {
|
||||
|
||||
std::string trim_ini_value(std::string value) {
|
||||
const auto first = std::find_if_not(value.begin(), value.end(), [](unsigned char ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
|
||||
});
|
||||
const auto last = std::find_if_not(value.rbegin(), value.rend(), [](unsigned char ch) {
|
||||
return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
|
||||
}).base();
|
||||
if (first >= last) {
|
||||
return {};
|
||||
}
|
||||
return std::string(first, last);
|
||||
}
|
||||
|
||||
bool find_ini_value(const char *iniFilename,
|
||||
const char *section,
|
||||
const char *key,
|
||||
std::string &value) {
|
||||
FILE *file = std::fopen(iniFilename, "r");
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool in_section = false;
|
||||
char line[PATH_MAX + 256];
|
||||
while (std::fgets(line, sizeof(line), file)) {
|
||||
std::string text = trim_ini_value(line);
|
||||
if (text.empty() || text[0] == ';' || text[0] == '#') {
|
||||
continue;
|
||||
}
|
||||
if (text.front() == '[' && text.back() == ']') {
|
||||
in_section = text.substr(1, text.size() - 2) == section;
|
||||
continue;
|
||||
}
|
||||
if (!in_section) {
|
||||
continue;
|
||||
}
|
||||
const auto equals = text.find('=');
|
||||
if (equals == std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
if (trim_ini_value(text.substr(0, equals)) == key) {
|
||||
value = trim_ini_value(text.substr(equals + 1));
|
||||
std::fclose(file);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::fclose(file);
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
PythonPlugin *PythonPlugin::instantiate(struct _inittab *) {
|
||||
static PythonPlugin plugin;
|
||||
python_plugin = &plugin;
|
||||
@@ -42,6 +102,19 @@ int PythonPlugin::configure(const char *iniFilename, const char *section) {
|
||||
}
|
||||
std::fclose(file);
|
||||
|
||||
std::string toplevel;
|
||||
if (find_ini_value(iniFilename, section, "TOPLEVEL", toplevel)) {
|
||||
char resolved_path[PATH_MAX];
|
||||
// LinuxCNC source basis: python_plugin.cc configure() expands and
|
||||
// resolves [PYTHON] TOPLEVEL before initialize(); a missing path
|
||||
// returns PLUGIN_BAD_PATH before Python runtime status is considered.
|
||||
if (realpath(toplevel.c_str(), resolved_path) == nullptr) {
|
||||
error_msg = "bad path";
|
||||
status = PLUGIN_BAD_PATH;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
return initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,32 @@ int main() {
|
||||
std::fputs("[PYTHON]\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
const char *bad_path_ini = "/tmp/cnc_sim_python_plugin_probe_bad_path.ini";
|
||||
{
|
||||
FILE *file = std::fopen(bad_path_ini, "w");
|
||||
if (!file) {
|
||||
std::remove(ini);
|
||||
return 33;
|
||||
}
|
||||
std::fputs("[PYTHON]\nTOPLEVEL = /tmp/cnc_sim_missing_python_toplevel.py\n", file);
|
||||
std::fclose(file);
|
||||
}
|
||||
if (plugin->configure(bad_path_ini, "PYTHON") != PLUGIN_BAD_PATH) {
|
||||
std::remove(ini);
|
||||
std::remove(bad_path_ini);
|
||||
return 34;
|
||||
}
|
||||
if (plugin->usable()) {
|
||||
std::remove(ini);
|
||||
std::remove(bad_path_ini);
|
||||
return 35;
|
||||
}
|
||||
if (plugin->last_errmsg() != "bad path") {
|
||||
std::remove(ini);
|
||||
std::remove(bad_path_ini);
|
||||
return 36;
|
||||
}
|
||||
std::remove(bad_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