chore: update packages
This commit is contained in:
@@ -13,13 +13,13 @@ let
|
|||||||
in
|
in
|
||||||
buildGoModule (finalAttrs: {
|
buildGoModule (finalAttrs: {
|
||||||
pname = "llama-swap";
|
pname = "llama-swap";
|
||||||
version = "180";
|
version = "182";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "mostlygeek";
|
owner = "mostlygeek";
|
||||||
repo = "llama-swap";
|
repo = "llama-swap";
|
||||||
tag = "v${finalAttrs.version}";
|
tag = "v${finalAttrs.version}";
|
||||||
hash = "sha256-WPDmENGH1uwNrobcIPA2vuNEsb9sP7Wl7T0wtUv1H/s=";
|
hash = "sha256-w/VQS8uCpgniwLiJsH/8IG/AGasRxjCv7fADTfpvWLw=";
|
||||||
# populate values that require us to use git. By doing this in postFetch we
|
# populate values that require us to use git. By doing this in postFetch we
|
||||||
# can delete .git afterwards and maintain better reproducibility of the src.
|
# can delete .git afterwards and maintain better reproducibility of the src.
|
||||||
leaveDotGit = true;
|
leaveDotGit = true;
|
||||||
|
|||||||
@@ -13,12 +13,12 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
pname = "opencode";
|
pname = "opencode";
|
||||||
version = "1.0.223";
|
version = "1.1.4";
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "sst";
|
owner = "anomalyco";
|
||||||
repo = "opencode";
|
repo = "opencode";
|
||||||
tag = "v${version}";
|
tag = "v${version}";
|
||||||
hash = "sha256-CzbWv48UySgXfNgtWdIdFBcqx8GHT4rSJNDdpn39b0c="; # "sha256-Y0thIZ20p0FSBAH0mJfFn8e+OEUvlZyTuk+/yEt8Sy8=";
|
hash = "sha256-i9IO9FSZ2Mw0tPqFxfQfSbejx04J1eJ0IYy5fa77O2Y=";
|
||||||
};
|
};
|
||||||
|
|
||||||
node_modules = stdenvNoCC.mkDerivation {
|
node_modules = stdenvNoCC.mkDerivation {
|
||||||
@@ -75,7 +75,7 @@ let
|
|||||||
# NOTE: Required else we get errors that our fixed-output derivation references store paths
|
# NOTE: Required else we get errors that our fixed-output derivation references store paths
|
||||||
dontFixup = true;
|
dontFixup = true;
|
||||||
|
|
||||||
outputHash = "sha256-+HEd3I11VqejTi7cikbTL5+DmNGyvUC4Cm4ysfujwes=";
|
outputHash = "sha256-tea/pSuUOELsSSMdwi0mmG5GsFZpqR5MlyQvVUno7dM=";
|
||||||
outputHashAlgo = "sha256";
|
outputHashAlgo = "sha256";
|
||||||
outputHashMode = "recursive";
|
outputHashMode = "recursive";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ let
|
|||||||
in
|
in
|
||||||
effectiveStdenv.mkDerivation (finalAttrs: {
|
effectiveStdenv.mkDerivation (finalAttrs: {
|
||||||
pname = "stable-diffusion-cpp";
|
pname = "stable-diffusion-cpp";
|
||||||
version = "master-453-4ff2c8c";
|
version = "master-462-c5602a6";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "leejet";
|
owner = "leejet";
|
||||||
repo = "stable-diffusion.cpp";
|
repo = "stable-diffusion.cpp";
|
||||||
rev = "master-453-4ff2c8c";
|
rev = "master-462-c5602a6";
|
||||||
hash = "sha256-8cN6dYOQAKnJpuQdtayp6+o71s64lG+FcTn8GsIM4jI=";
|
hash = "sha256-6uW9k30QqvozJACw+Hv4nRj9PyTzQqY/M0/CWjqrV28=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -102,6 +102,12 @@ effectiveStdenv.mkDerivation (finalAttrs: {
|
|||||||
(cmakeFeature "CMAKE_HIP_ARCHITECTURES" (builtins.concatStringsSep ";" rocmGpuTargets))
|
(cmakeFeature "CMAKE_HIP_ARCHITECTURES" (builtins.concatStringsSep ";" rocmGpuTargets))
|
||||||
];
|
];
|
||||||
|
|
||||||
|
patchFlags = [ "-p1" ];
|
||||||
|
patches = [
|
||||||
|
./lora_enable.patch # https://github.com/leejet/stable-diffusion.cpp/pull/1156
|
||||||
|
./server_mask.patch # https://github.com/leejet/stable-diffusion.cpp/pull/1178
|
||||||
|
];
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
description = "Stable Diffusion inference in pure C/C++";
|
description = "Stable Diffusion inference in pure C/C++";
|
||||||
homepage = "https://github.com/leejet/stable-diffusion.cpp";
|
homepage = "https://github.com/leejet/stable-diffusion.cpp";
|
||||||
|
|||||||
221
packages/stable-diffusion-cpp/lora_enable.patch
Normal file
221
packages/stable-diffusion-cpp/lora_enable.patch
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
From 4aaca67479469faab232dc276afe12acdcd7f801 Mon Sep 17 00:00:00 2001
|
||||||
|
From: mateusgpe <mushgp@gmail.com>
|
||||||
|
Date: Wed, 31 Dec 2025 18:42:23 -0300
|
||||||
|
Subject: [PATCH 1/2] fix(server): sanitize LoRA paths and enable dynamic
|
||||||
|
loading
|
||||||
|
|
||||||
|
- Implement `sanitize_lora_path` in `SDGenerationParams` to prevent directory traversal attacks via LoRA tags in prompts.
|
||||||
|
- Restrict LoRA paths to be relative and strictly within the configured LoRA directory (no subdirectories allowed, optional? drawback: users cannot organize their LoRAs into subfolders.).
|
||||||
|
- Update server example to pass `lora_model_dir` to `process_and_check`, enabling LoRA extraction from prompts.
|
||||||
|
- Force `LORA_APPLY_AT_RUNTIME` in the server to allow applying LoRAs dynamically per request without reloading the model.
|
||||||
|
---
|
||||||
|
examples/common/common.hpp | 67 +++++++++++++++++++++++++++++++++++---
|
||||||
|
examples/server/main.cpp | 5 +--
|
||||||
|
2 files changed, 65 insertions(+), 7 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/examples/common/common.hpp b/examples/common/common.hpp
|
||||||
|
index 7ea95ed14..7f869868c 100644
|
||||||
|
--- a/examples/common/common.hpp
|
||||||
|
+++ b/examples/common/common.hpp
|
||||||
|
@@ -1601,6 +1601,63 @@ struct SDGenerationParams {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ static bool sanitize_lora_path(const std::string& lora_model_dir,
|
||||||
|
+ const std::string& raw_path_str,
|
||||||
|
+ fs::path& full_path) {
|
||||||
|
+ if (lora_model_dir.empty()) {
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fs::path raw_path(raw_path_str);
|
||||||
|
+
|
||||||
|
+ // Disallow absolute paths.
|
||||||
|
+ if (raw_path.is_absolute()) {
|
||||||
|
+ LOG_WARN("lora path must be relative: %s", raw_path_str.c_str());
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // Disallow '..' in the raw path to prevent basic traversal attempts.
|
||||||
|
+ for (const auto& part : raw_path) {
|
||||||
|
+ if (part == "..") {
|
||||||
|
+ LOG_WARN("lora path cannot contain '..': %s", raw_path_str.c_str());
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ fs::path lora_dir(lora_model_dir);
|
||||||
|
+ full_path = lora_dir / raw_path;
|
||||||
|
+
|
||||||
|
+ // --- Security Checks on Canonical Path ---
|
||||||
|
+ // Canonicalize paths to resolve symlinks and normalize separators for robust checks.
|
||||||
|
+ // weakly_canonical is used because the target file might not exist yet.
|
||||||
|
+ auto canonical_lora_dir = fs::weakly_canonical(lora_dir);
|
||||||
|
+ auto canonical_full_path = fs::weakly_canonical(full_path);
|
||||||
|
+
|
||||||
|
+ // 1. The resolved path must not be a directory.
|
||||||
|
+ if (fs::is_directory(canonical_full_path)) {
|
||||||
|
+ LOG_WARN("lora path resolved to a directory, not a file: %s", raw_path_str.c_str());
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // 2. The file must be inside the designated lora directory.
|
||||||
|
+ // We check this by ensuring the relative path does not climb up with '..'.
|
||||||
|
+ fs::path relative_path = canonical_full_path.lexically_relative(canonical_lora_dir);
|
||||||
|
+ for (const auto& part : relative_path) {
|
||||||
|
+ if (part == "..") {
|
||||||
|
+ LOG_WARN("lora path is outside of the lora model directory: %s", raw_path_str.c_str());
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ // 3. The file must be directly in the lora directory, not in a subdirectory.
|
||||||
|
+ if (relative_path.has_parent_path() && !relative_path.parent_path().empty()) {
|
||||||
|
+ LOG_WARN("lora path in subdirectories is not allowed: %s", raw_path_str.c_str());
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
void extract_and_remove_lora(const std::string& lora_model_dir) {
|
||||||
|
if (lora_model_dir.empty()) {
|
||||||
|
return;
|
||||||
|
@@ -1632,10 +1689,10 @@ struct SDGenerationParams {
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path final_path;
|
||||||
|
- if (is_absolute_path(raw_path)) {
|
||||||
|
- final_path = raw_path;
|
||||||
|
- } else {
|
||||||
|
- final_path = fs::path(lora_model_dir) / raw_path;
|
||||||
|
+ if (!sanitize_lora_path(lora_model_dir, raw_path, final_path)) {
|
||||||
|
+ tmp = m.suffix().str();
|
||||||
|
+ prompt = std::regex_replace(prompt, re, "", std::regex_constants::format_first_only);
|
||||||
|
+ continue;
|
||||||
|
}
|
||||||
|
if (!fs::exists(final_path)) {
|
||||||
|
bool found = false;
|
||||||
|
@@ -1643,7 +1700,7 @@ struct SDGenerationParams {
|
||||||
|
fs::path try_path = final_path;
|
||||||
|
try_path += ext;
|
||||||
|
if (fs::exists(try_path)) {
|
||||||
|
- final_path = try_path;
|
||||||
|
+ final_path = try_path.lexically_normal();
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
diff --git a/examples/server/main.cpp b/examples/server/main.cpp
|
||||||
|
index c540958f8..69c75d322 100644
|
||||||
|
--- a/examples/server/main.cpp
|
||||||
|
+++ b/examples/server/main.cpp
|
||||||
|
@@ -293,6 +293,7 @@ int main(int argc, const char** argv) {
|
||||||
|
LOG_DEBUG("%s", default_gen_params.to_string().c_str());
|
||||||
|
|
||||||
|
sd_ctx_params_t sd_ctx_params = ctx_params.to_sd_ctx_params_t(false, false, false);
|
||||||
|
+ ctx_params.lora_apply_mode = LORA_APPLY_AT_RUNTIME;
|
||||||
|
sd_ctx_t* sd_ctx = new_sd_ctx(&sd_ctx_params);
|
||||||
|
|
||||||
|
if (sd_ctx == nullptr) {
|
||||||
|
@@ -414,7 +415,7 @@ int main(int argc, const char** argv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!gen_params.process_and_check(IMG_GEN, "")) {
|
||||||
|
+ if (!gen_params.process_and_check(IMG_GEN, ctx_params.lora_model_dir)) {
|
||||||
|
res.status = 400;
|
||||||
|
res.set_content(R"({"error":"invalid params"})", "application/json");
|
||||||
|
return;
|
||||||
|
@@ -592,7 +593,7 @@ int main(int argc, const char** argv) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (!gen_params.process_and_check(IMG_GEN, "")) {
|
||||||
|
+ if (!gen_params.process_and_check(IMG_GEN, ctx_params.lora_model_dir)) {
|
||||||
|
res.status = 400;
|
||||||
|
res.set_content(R"({"error":"invalid params"})", "application/json");
|
||||||
|
return;
|
||||||
|
|
||||||
|
From 4b80b61003aa06f41c6bdec47ff926e37007b87d Mon Sep 17 00:00:00 2001
|
||||||
|
From: mateusgpe <mushgp@gmail.com>
|
||||||
|
Date: Thu, 1 Jan 2026 15:24:01 -0300
|
||||||
|
Subject: [PATCH 2/2] fix: sanitize LoRA paths and enable dynamic loading
|
||||||
|
|
||||||
|
- Remove the restriction that LoRA models must be in the root of the LoRA directory, allowing them to be organized in subfolders.
|
||||||
|
- Refactor the directory containment check to use `std::mismatch` instead of `lexically_relative` to verify the path is inside the allowed root.
|
||||||
|
- Remove redundant `lexically_normal()` call when resolving file extensions.
|
||||||
|
---
|
||||||
|
examples/common/common.hpp | 29 ++++++++++-------------------
|
||||||
|
1 file changed, 10 insertions(+), 19 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/examples/common/common.hpp b/examples/common/common.hpp
|
||||||
|
index 7f869868c..a2e919409 100644
|
||||||
|
--- a/examples/common/common.hpp
|
||||||
|
+++ b/examples/common/common.hpp
|
||||||
|
@@ -1610,13 +1610,12 @@ struct SDGenerationParams {
|
||||||
|
|
||||||
|
fs::path raw_path(raw_path_str);
|
||||||
|
|
||||||
|
- // Disallow absolute paths.
|
||||||
|
+ // Disallow absolute paths and '..' components
|
||||||
|
if (raw_path.is_absolute()) {
|
||||||
|
LOG_WARN("lora path must be relative: %s", raw_path_str.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- // Disallow '..' in the raw path to prevent basic traversal attempts.
|
||||||
|
for (const auto& part : raw_path) {
|
||||||
|
if (part == "..") {
|
||||||
|
LOG_WARN("lora path cannot contain '..': %s", raw_path_str.c_str());
|
||||||
|
@@ -1624,34 +1623,26 @@ struct SDGenerationParams {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // Construct and canonicalize paths
|
||||||
|
fs::path lora_dir(lora_model_dir);
|
||||||
|
full_path = lora_dir / raw_path;
|
||||||
|
|
||||||
|
- // --- Security Checks on Canonical Path ---
|
||||||
|
- // Canonicalize paths to resolve symlinks and normalize separators for robust checks.
|
||||||
|
- // weakly_canonical is used because the target file might not exist yet.
|
||||||
|
auto canonical_lora_dir = fs::weakly_canonical(lora_dir);
|
||||||
|
auto canonical_full_path = fs::weakly_canonical(full_path);
|
||||||
|
|
||||||
|
- // 1. The resolved path must not be a directory.
|
||||||
|
+ // Check if path is a directory
|
||||||
|
if (fs::is_directory(canonical_full_path)) {
|
||||||
|
LOG_WARN("lora path resolved to a directory, not a file: %s", raw_path_str.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
- // 2. The file must be inside the designated lora directory.
|
||||||
|
- // We check this by ensuring the relative path does not climb up with '..'.
|
||||||
|
- fs::path relative_path = canonical_full_path.lexically_relative(canonical_lora_dir);
|
||||||
|
- for (const auto& part : relative_path) {
|
||||||
|
- if (part == "..") {
|
||||||
|
- LOG_WARN("lora path is outside of the lora model directory: %s", raw_path_str.c_str());
|
||||||
|
- return false;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ // Verify path stays within lora directory
|
||||||
|
+ auto [root_end, nothing] = std::mismatch(
|
||||||
|
+ canonical_lora_dir.begin(), canonical_lora_dir.end(),
|
||||||
|
+ canonical_full_path.begin(), canonical_full_path.end());
|
||||||
|
|
||||||
|
- // 3. The file must be directly in the lora directory, not in a subdirectory.
|
||||||
|
- if (relative_path.has_parent_path() && !relative_path.parent_path().empty()) {
|
||||||
|
- LOG_WARN("lora path in subdirectories is not allowed: %s", raw_path_str.c_str());
|
||||||
|
+ if (root_end != canonical_lora_dir.end()) {
|
||||||
|
+ LOG_WARN("lora path is outside of the lora model directory: %s", raw_path_str.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -1700,7 +1691,7 @@ struct SDGenerationParams {
|
||||||
|
fs::path try_path = final_path;
|
||||||
|
try_path += ext;
|
||||||
|
if (fs::exists(try_path)) {
|
||||||
|
- final_path = try_path.lexically_normal();
|
||||||
|
+ final_path = try_path;
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
13
packages/stable-diffusion-cpp/server_mask.patch
Normal file
13
packages/stable-diffusion-cpp/server_mask.patch
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
diff --git i/examples/server/main.cpp w/examples/server/main.cpp
|
||||||
|
index 9fa8804..b15daca 100644
|
||||||
|
--- i/examples/server/main.cpp
|
||||||
|
+++ w/examples/server/main.cpp
|
||||||
|
@@ -537,7 +537,7 @@ int main(int argc, const char** argv) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> mask_bytes;
|
||||||
|
- if (req.form.has_field("mask")) {
|
||||||
|
+ if (req.form.has_file("mask")) {
|
||||||
|
auto file = req.form.get_file("mask");
|
||||||
|
mask_bytes.assign(file.content.begin(), file.content.end());
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user