From 266b6ff6e17077ff481d54b125800477b96eb7ed Mon Sep 17 00:00:00 2001 From: spaceeye Date: Sun, 11 Jun 2023 18:44:32 +0300 Subject: [PATCH] merge --- src/io.h | 80 +++++++++++++++++++------- src/isolated_os.h | 142 ---------------------------------------------- src/pocketpy.h | 6 +- 3 files changed, 61 insertions(+), 167 deletions(-) delete mode 100644 src/isolated_os.h diff --git a/src/io.h b/src/io.h index be950072..a303c1f9 100644 --- a/src/io.h +++ b/src/io.h @@ -10,21 +10,36 @@ #include namespace pkpy{ +inline std::filesystem::path get_rel(const VM* vm, const std::filesystem::path & rel) { + return rel.lexically_relative(vm->_lowest_isolated_cwd_path); +} + +inline bool check_if_path_is_isolated(const std::string & path_to_check_str, + const std::string & toplevel_path_str) { + //.lexically_normal() expands somepath/somdir/.. to somepath/ + auto toplevel_path = std::filesystem::path(toplevel_path_str).lexically_normal(); + auto path_to_check = (toplevel_path / std::filesystem::path(path_to_check_str)).lexically_normal(); + + //toplevel_path is part of toplevel_path, so if toplevel_path is less than path_to_check, then toplevel_path is certainly not a part of it + if (path_to_check < toplevel_path) {return false;} + if (path_to_check == toplevel_path) {return true;} + while (true) { + auto temp = path_to_check.parent_path(); + if (path_to_check == temp) { break;} + path_to_check = temp; + if (path_to_check < toplevel_path) {return false;} + if (path_to_check == toplevel_path) {return true;} + } + + return false; +} + +static inline void helper_process_isolated(VM *vm, std::filesystem::path & path) { + if (!vm->isolated_os) { return;} + path = std::filesystem::path(vm->_lowest_isolated_cwd_path) / path; + if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) {vm->IOError(Str("Invalid path."));} +} -inline Bytes _default_import_handler(const Str& name){ - std::filesystem::path path(name.sv()); - bool exists = std::filesystem::exists(path); - if(!exists) return Bytes(); - std::string cname = name.str(); - FILE* fp = fopen(cname.c_str(), "rb"); - if(!fp) return Bytes(); - fseek(fp, 0, SEEK_END); - std::vector buffer(ftell(fp)); - fseek(fp, 0, SEEK_SET); - fread(buffer.data(), 1, buffer.size(), fp); - fclose(fp); - return Bytes(std::move(buffer)); -}; struct FileIO { PY_CLASS(FileIO, io, FileIO) @@ -36,7 +51,8 @@ struct FileIO { bool is_text() const { return mode != "rb" && mode != "wb" && mode != "ab"; } FileIO(VM* vm, std::string file, std::string mode): file(file), mode(mode) { - if (vm->check_is_invalid_io_path(file)) {vm->IOError(strerror(errno));} + if (vm->isolated_os && !check_if_path_is_isolated(file, vm->_lowest_isolated_cwd_path)) {vm->IOError(strerror(errno));} + if (vm->isolated_os) {file = vm->_lowest_isolated_cwd_path / std::filesystem::path(file);} fp = fopen(file.c_str(), mode.c_str()); if(!fp) vm->IOError(strerror(errno)); } @@ -110,17 +126,24 @@ inline void add_module_os(VM* vm){ // Working directory is shared by all VMs!! vm->bind_func<0>(mod, "getcwd", [](VM* vm, ArgsView args){ - return VAR(std::filesystem::current_path().string()); + if (!vm->isolated_os) { + return VAR(std::filesystem::current_path().string()); + } else { + return VAR(get_rel(vm, std::filesystem::current_path()).string());//TODO BUG! while technically correct, cwd needs to change to a file path upon executing + } }); vm->bind_func<1>(mod, "chdir", [](VM* vm, ArgsView args){ std::filesystem::path path(CAST(Str&, args[0]).sv()); + helper_process_isolated(vm, path); std::filesystem::current_path(path); return vm->None; }); vm->bind_func<1>(mod, "listdir", [](VM* vm, ArgsView args){ std::filesystem::path path(CAST(Str&, args[0]).sv()); + helper_process_isolated(vm, path); + std::filesystem::directory_iterator di; try{ di = std::filesystem::directory_iterator(path); @@ -131,28 +154,40 @@ inline void add_module_os(VM* vm){ vm->IOError(Str(msg).lstrip()); } List ret; - for(auto& p: di) ret.push_back(VAR(p.path().filename().string())); + if (!vm->isolated_os) { + for (auto &p: di) ret.push_back(VAR(p.path().filename().string())); + } else { + for(auto& p: di) ret.push_back(VAR(get_rel(vm, p.path()).filename().string())); + } return VAR(ret); }); vm->bind_func<1>(mod, "remove", [](VM* vm, ArgsView args){ std::filesystem::path path(CAST(Str&, args[0]).sv()); + helper_process_isolated(vm, path); + bool ok = std::filesystem::remove(path); - if(!ok) vm->IOError("operation failed"); + if(!ok) vm->IOError("Operation failed."); return vm->None; }); vm->bind_func<1>(mod, "mkdir", [](VM* vm, ArgsView args){ std::filesystem::path path(CAST(Str&, args[0]).sv()); + helper_process_isolated(vm, path); + + std::cout << path.string().c_str() << "\n"; + bool ok = std::filesystem::create_directory(path); - if(!ok) vm->IOError("operation failed"); + if(!ok) vm->IOError("Operation failed."); return vm->None; }); vm->bind_func<1>(mod, "rmdir", [](VM* vm, ArgsView args){ std::filesystem::path path(CAST(Str&, args[0]).sv()); + helper_process_isolated(vm, path); + bool ok = std::filesystem::remove(path); - if(!ok) vm->IOError("operation failed"); + if(!ok) vm->IOError("Operation failed."); return vm->None; }); @@ -166,6 +201,11 @@ inline void add_module_os(VM* vm){ vm->bind_func<1>(path_obj, "exists", [](VM* vm, ArgsView args){ std::filesystem::path path(CAST(Str&, args[0]).sv()); + if (vm->isolated_os) { + path = vm->_lowest_isolated_cwd_path / path; + if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) {return VAR(false);} + } + bool exists = std::filesystem::exists(path); return VAR(exists); }); diff --git a/src/isolated_os.h b/src/isolated_os.h deleted file mode 100644 index cff3dc3b..00000000 --- a/src/isolated_os.h +++ /dev/null @@ -1,142 +0,0 @@ -#pragma once - -#include "ceval.h" -#include "cffi.h" -#include "common.h" - -#if PK_ENABLE_OS - -#include -#include - -namespace pkpy { - -inline std::filesystem::path get_rel(const VM* vm, const std::filesystem::path & rel) { - return rel.lexically_relative(vm->_lowest_isolated_cwd_path); -} - -inline bool check_if_path_is_isolated(const std::string & path_to_check_str, - const std::string & toplevel_path_str) { - //.lexically_normal() expands somepath/somdir/.. to somepath/ - auto toplevel_path = std::filesystem::path(toplevel_path_str).lexically_normal(); - auto path_to_check = std::filesystem::path(toplevel_path_str+path_to_check_str).lexically_normal(); - - //toplevel_path is part of toplevel_path, so if toplevel_path is less than path_to_check, then toplevel_path is certainly not a part of it - if (path_to_check < toplevel_path) {return false;} - if (path_to_check == toplevel_path) {return true;} - while (true) { - auto temp = path_to_check.parent_path(); - if (path_to_check == temp) { break;} - path_to_check = temp; - if (path_to_check < toplevel_path) {return false;} - if (path_to_check == toplevel_path) {return true;} - } - - return false; -} - -inline void add_module_isolated_os(VM *vm) { - if (vm->_lowest_isolated_cwd_path.empty()) { - throw std::invalid_argument("vm->_lowest_isolated_cwd_path is empty. Change it to a path of VM's allowed operation."); - } - if (!std::filesystem::exists(vm->_lowest_isolated_cwd_path)) { - throw std::invalid_argument("vm->_lowest_isolated_cwd_path doesn't exist."); - } - - PyObject* mod = vm->new_module("os"); - PyObject* path_obj = vm->heap.gcnew(vm->tp_object, {}); - mod->attr().set("path", path_obj); - - vm->bind_func<0>(mod, "getcwd", [](VM* vm, ArgsView args){ - return VAR(get_rel(vm, std::filesystem::current_path()).string()); - }); - - vm->bind_func<1>(mod, "chdir", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) { - std::filesystem::current_path(vm->_lowest_isolated_cwd_path); - return vm->None; - } - std::filesystem::current_path(vm->_lowest_isolated_cwd_path / path); - return vm->None; - }); - - vm->bind_func<1>(mod, "listdir", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) {vm->IOError(Str("Invalid path."));} - path = vm->_lowest_isolated_cwd_path / path; - - std::filesystem::directory_iterator di; - try{ - di = std::filesystem::directory_iterator(path); - }catch(std::filesystem::filesystem_error& e){ - std::string msg = e.what(); - auto pos = msg.find_last_of(':'); - if(pos != std::string::npos) msg = msg.substr(pos + 1); - vm->IOError(Str(msg).lstrip()); - } - List ret; - for(auto& p: di) ret.push_back(VAR(get_rel(vm, p.path()).filename().string())); - return VAR(ret); - }); - - vm->bind_func<1>(mod, "remove", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) {vm->IOError(Str("Operation failed."));} - path = vm->_lowest_isolated_cwd_path / path; - - bool ok = std::filesystem::remove(path); - if(!ok) vm->IOError("Operation failed."); - return vm->None; - }); - - vm->bind_func<1>(mod, "mkdir", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) {vm->IOError(Str("Operation failed."));} - path = vm->_lowest_isolated_cwd_path / path; - - bool ok = std::filesystem::create_directory(path); - if(!ok) vm->IOError("Operation failed."); - return vm->None; - }); - - vm->bind_func<1>(mod, "rmdir", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - if (!check_if_path_is_isolated(path, vm->_lowest_isolated_cwd_path)) {vm->IOError(Str("Operation failed."));} - path = vm->_lowest_isolated_cwd_path / path; - - bool ok = std::filesystem::remove(path); - if(!ok) vm->IOError("Operation failed."); - return vm->None; - }); - - vm->bind_func<-1>(path_obj, "join", [](VM* vm, ArgsView args){ - std::filesystem::path path; - for(int i=0; ibind_func<1>(path_obj, "exists", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - path = vm->_lowest_isolated_cwd_path / path; - bool exists = std::filesystem::exists(path); - return VAR(exists); - }); - - vm->bind_func<1>(path_obj, "basename", [](VM* vm, ArgsView args){ - std::filesystem::path path(CAST(Str&, args[0]).sv()); - return VAR(path.filename().string()); - }); -} - -}// namespace pkpy - -#else - -namespace pkpy{ -inline void add_module_isolated_os(void* vm){} -} // namespace pkpy - -#endif diff --git a/src/pocketpy.h b/src/pocketpy.h index 62c508c5..dec24633 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -1334,11 +1334,7 @@ inline void VM::post_init(){ if(enable_os){ add_module_io(this); - if (isolated_os) { - add_module_isolated_os(this); - } else { - add_module_os(this); - } + add_module_os(this); add_module_requests(this); _import_handler = _default_import_handler; }