@@ -37,6 +37,19 @@ namespace fs = std::filesystem;
3737#define SAFE_STR (s ) ((s) ? (s) : " " )
3838#define BOOL_STR (b ) ((b) ? " true" : " false" )
3939
40+ static bool is_path_safe (const fs::path& base_dir, const fs::path& target_path) {
41+ try {
42+ // 获取目标路径的绝对路径(weakly_canonical 允许文件尚不存在,但能处理 .. 和 .)
43+ fs::path abs_target = fs::weakly_canonical (target_path);
44+
45+ auto base_str = base_dir.string ();
46+ auto target_str = abs_target.string ();
47+ return target_str.rfind (base_str, 0 ) == 0 ;
48+ } catch (...) {
49+ return false ;
50+ }
51+ }
52+
4053const char * modes_str[] = {
4154 " img_gen" ,
4255 " vid_gen" ,
@@ -1632,15 +1645,16 @@ struct SDGenerationParams {
16321645 }
16331646
16341647 void extract_and_remove_lora (const std::string& lora_model_dir) {
1635- if (lora_model_dir.empty ()) {
1636- return ;
1637- }
1648+ if (lora_model_dir.empty ()) return ;
1649+
16381650 static const std::regex re (R"( <lora:([^:>]+):([^>]+)>)" );
16391651 static const std::vector<std::string> valid_ext = {" .gguf" , " .safetensors" , " .pt" };
16401652 std::smatch m;
16411653
16421654 std::string tmp = prompt;
16431655
1656+ fs::path base_path = fs::absolute (lora_model_dir);
1657+
16441658 while (std::regex_search (tmp, m, re)) {
16451659 std::string raw_path = m[1 ].str ();
16461660 const std::string raw_mul = m[2 ].str ();
@@ -1663,10 +1677,22 @@ struct SDGenerationParams {
16631677
16641678 fs::path final_path;
16651679 if (is_absolute_path (raw_path)) {
1680+ #ifdef SD_SAFE_LORA
1681+ LOG_WARN (" This LoRA path is forbidden [SD_SAFE_LORA]: %s" , raw_path.c_str ());
1682+ goto next_match;
1683+ #else
16661684 final_path = raw_path;
1685+ #endif
16671686 } else {
1668- final_path = fs::path (lora_model_dir) / raw_path;
1687+ final_path = base_path / raw_path;
1688+ #ifdef SD_SAFE_LORA
1689+ if (!is_path_safe (base_path, final_path)) {
1690+ LOG_WARN (" This LoRA path is forbidden [SD_SAFE_LORA]: %s" , raw_path.c_str ());
1691+ goto next_match;
1692+ }
1693+ #endif
16691694 }
1695+
16701696 if (!fs::exists (final_path)) {
16711697 bool found = false ;
16721698 for (const auto & ext : valid_ext) {
@@ -1686,13 +1712,17 @@ struct SDGenerationParams {
16861712 }
16871713 }
16881714
1715+ {
16891716 const std::string key = final_path.lexically_normal ().string ();
16901717
16911718 if (is_high_noise)
16921719 high_noise_lora_map[key] += mul;
16931720 else
16941721 lora_map[key] += mul;
1722+ }
1723+
16951724
1725+ next_match:
16961726 prompt = std::regex_replace (prompt, re, " " , std::regex_constants::format_first_only);
16971727
16981728 tmp = m.suffix ().str ();
@@ -1999,7 +2029,7 @@ uint8_t* load_image_common(bool from_memory,
19992029 int c = 0 ;
20002030 const char * image_path;
20012031 uint8_t * image_buffer = nullptr ;
2002-
2032+
20032033 bool is_qoi = false ;
20042034 if (from_memory) {
20052035 // magic bytes
@@ -2039,7 +2069,7 @@ uint8_t* load_image_common(bool from_memory,
20392069 image_path_or_bytes, &width, &height, &c, expected_channel);
20402070 }
20412071 }
2042-
2072+
20432073 if (image_buffer == nullptr ) {
20442074 LOG_ERROR (" load image from '%s' failed" , image_path);
20452075 return nullptr ;
@@ -2180,6 +2210,6 @@ bool save_image_as_qoi(const char* filename, int width, int height, int channels
21802210 desc.height = height;
21812211 desc.channels = channels;
21822212 desc.colorspace = QOI_SRGB;
2183-
2213+
21842214 return qoi_write (filename, data, &desc) > 0 ;
21852215}
0 commit comments