diff --git a/src/coders/vec3.cpp b/src/coders/vec3.cpp index e00bdd662..119cbed92 100644 --- a/src/coders/vec3.cpp +++ b/src/coders/vec3.cpp @@ -133,6 +133,9 @@ static model::Mesh load_mesh( if (flags == FLAG_ZLIB) { throw std::runtime_error("compression is not supported yet"); } + if (attributeCount <= 0) { + throw std::runtime_error("mesh must have at least one attribute"); + } std::vector attributes; for (int i = 0; i < attributeCount; i++) { attributes.push_back(load_attribute(reader)); diff --git a/src/io/devices/StdfsDevice.cpp b/src/io/devices/StdfsDevice.cpp index fc0602b52..6f0e37e0e 100644 --- a/src/io/devices/StdfsDevice.cpp +++ b/src/io/devices/StdfsDevice.cpp @@ -20,10 +20,29 @@ StdfsDevice::StdfsDevice(fs::path root, bool createDirectory) << ": " << ec.message(); } } + absoluteRoot = fs::absolute(this->root).lexically_normal(); + if (!absoluteRoot.has_filename() && absoluteRoot.has_relative_path()) { + absoluteRoot = absoluteRoot.parent_path(); + } } fs::path StdfsDevice::resolve(std::string_view path) { - return root / fs::u8path(io::path(std::string(path)).normalized().string()); + if (path.find_first_of(std::string_view("\0\\:", 3)) != std::string_view::npos) { + throw std::runtime_error("invalid path"); + } + fs::path rel = fs::u8path(io::path(std::string(path)).normalized().string()); + if (rel.has_root_name() || rel.has_root_directory()) { + throw std::runtime_error("absolute paths are not allowed"); + } + fs::path full = (absoluteRoot / rel).lexically_normal(); + fs::path inside = full.lexically_relative(absoluteRoot); + if (inside.empty() || *inside.begin() == "..") { + throw std::runtime_error("path escapes device root"); + } + if (inside == ".") { + return absoluteRoot; + } + return full; } std::unique_ptr StdfsDevice::write(std::string_view path) { @@ -90,17 +109,32 @@ bool StdfsDevice::mkdirs(std::string_view path) { bool StdfsDevice::remove(std::string_view path) { auto resolved = resolve(path); - return fs::remove(resolved); + if (resolved == absoluteRoot) { + throw std::runtime_error("unable to remove device root"); + } + std::error_code ec; + bool removed = fs::remove(resolved, ec); + if (ec) { + logger.error() << "error removing " << resolved << ": " << ec.message(); + } + return removed; } uint64_t StdfsDevice::removeAll(std::string_view path) { auto resolved = resolve(path); - if (fs::exists(resolved)) { - logger.info() << "removeAll " << resolved; - return fs::remove_all(resolved); - } else { + if (resolved == absoluteRoot) { + throw std::runtime_error("unable to remove device root"); + } + std::error_code ec; + auto removed = fs::remove_all(resolved, ec); + if (ec) { + logger.error() << "error removing " << resolved << ": " << ec.message(); return 0; } + if (removed > 0) { + logger.info() << "removeAll " << resolved << ": " << removed; + } + return removed; } class StdfsPathsGenerator : public PathsGenerator { diff --git a/src/io/devices/StdfsDevice.hpp b/src/io/devices/StdfsDevice.hpp index 677cad25b..9259a9256 100644 --- a/src/io/devices/StdfsDevice.hpp +++ b/src/io/devices/StdfsDevice.hpp @@ -23,5 +23,6 @@ namespace io { std::unique_ptr list(std::string_view path) override; private: std::filesystem::path root; + std::filesystem::path absoluteRoot; }; } diff --git a/src/io/io.cpp b/src/io/io.cpp index 638108587..d550654e4 100644 --- a/src/io/io.cpp +++ b/src/io/io.cpp @@ -152,6 +152,9 @@ std::vector io::read_bytes(const path& filename) { std::string io::read_string(const path& filename) { size_t size; auto bytes = read_bytes(filename, size); + if (bytes == nullptr) { + throw std::runtime_error("could not read file " + filename.string()); + } return std::string((const char*)bytes.get(), size); } diff --git a/src/logic/scripting/lua/libs/libnetwork.cpp b/src/logic/scripting/lua/libs/libnetwork.cpp index 59d50f075..0d48e4a29 100644 --- a/src/logic/scripting/lua/libs/libnetwork.cpp +++ b/src/logic/scripting/lua/libs/libnetwork.cpp @@ -266,8 +266,10 @@ static int l_peek(lua::State* L, network::Network& network) { static int l_available(lua::State* L, network::Network& network) { u64id_t id = lua::tointeger(L, 1); - if (auto connection = network.getConnection(id, false)) { - return lua::pushinteger(L, dynamic_cast(connection)->available()); + if (auto connection = dynamic_cast( + network.getConnection(id, false) + )) { + return lua::pushinteger(L, connection->available()); } return 0; diff --git a/src/logic/scripting/lua/lua_engine.cpp b/src/logic/scripting/lua/lua_engine.cpp index 812f67665..1e73ea903 100644 --- a/src/logic/scripting/lua/lua_engine.cpp +++ b/src/logic/scripting/lua/lua_engine.cpp @@ -196,6 +196,10 @@ void lua::init_state(State* L, StateType stateType) { if (stateType == StateType::GENERATOR) { pushnil(L); setglobal(L, "ffi"); + + static const char* removed_debug[] { + "getregistry", "getupvalue", "setupvalue", "getinfo", nullptr}; + remove_lib_funcs(L, "debug", removed_debug); } } diff --git a/src/network/Curl.cpp b/src/network/Curl.cpp index 0e08162fb..11afa5ae5 100644 --- a/src/network/Curl.cpp +++ b/src/network/Curl.cpp @@ -113,6 +113,14 @@ public: curl_easy_setopt(curl, CURLOPT_URL, request.url.c_str()); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, request.method.c_str()); + +#if LIBCURL_VERSION_NUM >= 0x075500 + curl_easy_setopt(curl, CURLOPT_PROTOCOLS_STR, "http,https"); + curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS_STR, "http,https"); +#else + curl_easy_setopt(curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); + curl_easy_setopt(curl, CURLOPT_REDIR_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS); +#endif curl_slist* hs = nullptr;