mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-29 20:01:26 +00:00
Validate Plugin Symlink Targets Before Replacing Existing Files
A symlink entry's target is now read and checked before anything already at its destination is removed or renamed aside, so an archive rejected for its link target leaves the installed plugin files in place.
This commit is contained in:
@@ -1520,6 +1520,21 @@ int GUI_App::install_plugin(std::string name, std::string package_name, InstallP
|
|||||||
}
|
}
|
||||||
auto dest_path = plugin_folder / dest_file;
|
auto dest_path = plugin_folder / dest_file;
|
||||||
std::string dest_zip_file = encode_path(dest_path.string().c_str());
|
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 {
|
try {
|
||||||
boost::filesystem::create_directories(dest_path.parent_path());
|
boost::filesystem::create_directories(dest_path.parent_path());
|
||||||
// symlink_status so that an existing symlink, dangling or not, is replaced rather than written through.
|
// 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;
|
mz_bool res = 0;
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if (S_ISLNK(stat.m_external_attr >> 16)) {
|
if (is_link) {
|
||||||
std::string link(stat.m_uncomp_size, 0);
|
res = 1;
|
||||||
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;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
boost::filesystem::create_symlink(link, dest_path);
|
boost::filesystem::create_symlink(link, dest_path);
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
|
|||||||
Reference in New Issue
Block a user