diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index dd2a9d8269..72849dd78e 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -1520,6 +1520,21 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP } auto dest_path = plugin_folder / dest_file; std::string dest_zip_file = encode_path(dest_path.string().c_str()); +#ifndef WIN32 + // Validate a symlink's target before anything at the destination is replaced. + const bool is_link = S_ISLNK(stat.m_external_attr >> 16); + std::string link; + if (is_link) { + link.assign(stat.m_uncomp_size, 0); + if (!mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, link.data(), stat.m_uncomp_size, 0) || + !is_symlink_target_within_root(dest_file, link, plugin_folder)) { + BOOST_LOG_TRIVIAL(error) << "[install_plugin] link " << dest_file << " -> " << link << " is unreadable or resolves outside " << plugin_folder.string(); + close_zip_reader(&archive); + if (pro_fn) { pro_fn(InstallStatusUnzipFailed, 0, cancel); } + return InstallStatusUnzipFailed; + } + } +#endif try { boost::filesystem::create_directories(dest_path.parent_path()); // symlink_status so that an existing symlink, dangling or not, is replaced rather than written through. @@ -1551,15 +1566,8 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP } mz_bool res = 0; #ifndef WIN32 - if (S_ISLNK(stat.m_external_attr >> 16)) { - std::string link(stat.m_uncomp_size, 0); - res = mz_zip_reader_extract_to_mem(&archive, stat.m_file_index, link.data(), stat.m_uncomp_size, 0); - if (res && !is_symlink_target_within_root(dest_file, link, plugin_folder)) { - BOOST_LOG_TRIVIAL(error) << "[install_plugin] link " << dest_file << " -> " << link << " resolves outside " << plugin_folder.string(); - close_zip_reader(&archive); - if (pro_fn) { pro_fn(InstallStatusUnzipFailed, 0, cancel); } - return InstallStatusUnzipFailed; - } + if (is_link) { + res = 1; try { boost::filesystem::create_symlink(link, dest_path); } catch (const std::exception &e) {