Skip to content

Commit 2e9c3e9

Browse files
committed
Added parameters for max filesize for local files and allowed local media path
1 parent 261da51 commit 2e9c3e9

File tree

4 files changed

+40
-6
lines changed

4 files changed

+40
-6
lines changed

common/arg.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3281,6 +3281,20 @@ common_params_context common_params_parser_init(common_params & params, llama_ex
32813281
params.port = value;
32823282
}
32833283
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_PORT"));
3284+
add_opt(common_arg(
3285+
{"--allowed-local-media-path"}, "PATH",
3286+
string_format("path from which local media files are allowed to be read from (default: none)"),
3287+
[](common_params & params, const std::string & value) {
3288+
params.allowed_local_media_path = value;
3289+
}
3290+
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_ALLOWED_LOCAL_MEDIA_PATH"));
3291+
add_opt(common_arg(
3292+
{"--local-media-max-size-mb"}, "N",
3293+
string_format("max size in mb for local media files (default: %d)", 15), // 15MB
3294+
[](common_params & params, int value) {
3295+
params.local_media_max_size_mb = value;
3296+
}
3297+
).set_examples({LLAMA_EXAMPLE_SERVER}).set_env("LLAMA_ARG_LOCAL_MEDIA_MAX_SIZE_MB"));
32843298
add_opt(common_arg(
32853299
{"--path"}, "PATH",
32863300
string_format("path to serve static files from (default: %s)", params.public_path.c_str()),

common/common.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,11 @@ struct common_params {
427427
int32_t n_cache_reuse = 0; // min chunk size to reuse from the cache via KV shifting
428428
int32_t n_ctx_checkpoints = 8; // max number of context checkpoints per slot
429429
int32_t cache_ram_mib = 8192; // -1 = no limit, 0 - disable, 1 = 1 MiB, etc.
430+
int32_t local_media_max_size_mb = 15; // max size of loaded local media files
430431

431432
std::string hostname = "127.0.0.1";
432433
std::string public_path = ""; // NOLINT
434+
std::string allowed_local_media_path = ""; // NOLINT
433435
std::string api_prefix = ""; // NOLINT
434436
std::string chat_template = ""; // NOLINT
435437
bool use_jinja = false; // NOLINT

tools/server/server.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2585,6 +2585,8 @@ struct server_context {
25852585
/* allow_image */ mctx ? mtmd_support_vision(mctx) : false,
25862586
/* allow_audio */ mctx ? mtmd_support_audio (mctx) : false,
25872587
/* enable_thinking */ enable_thinking,
2588+
/* local_media_max_size_mb */ params_base.local_media_max_size_mb,
2589+
/* allowed_local_media_path */ params_base.allowed_local_media_path,
25882590
};
25892591
}
25902592

tools/server/utils.hpp

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,8 @@ struct oaicompat_parser_options {
528528
bool allow_image;
529529
bool allow_audio;
530530
bool enable_thinking = true;
531+
int32_t local_media_max_size_mb;
532+
std::string allowed_local_media_path;
531533
};
532534

533535
// used by /chat/completions endpoint
@@ -637,17 +639,31 @@ static json oaicompat_chat_params_parse(
637639
}
638640

639641
} else if (string_starts_with(url, "file://")) {
640-
// Strip off the leading "file://"
641-
std::string fname = url.substr(7);
642-
// load local file path
643-
raw_buffer buf;
642+
// Strip off the leading "file://"
643+
std::string fname = url.substr(7);
644+
std::vector<std::string> fparts = string_split<std::string>(fname, std::filesystem::path::preferred_separator);
645+
for (const auto &piece : fparts) {
646+
if (piece != "" && !fs_validate_filename(piece)) {
647+
throw std::runtime_error("Invalid filename piece '" + piece + "': " + fname);
648+
}
649+
}
650+
// Check allowed local media path - fs_validate_filename already validated that there is no ".." or "."
651+
if (opt.allowed_local_media_path == "" || !string_starts_with(fname, opt.allowed_local_media_path)) {
652+
throw std::runtime_error("File path not allowed");
653+
}
654+
// load local file path
655+
raw_buffer buf;
644656
FILE * f = fopen(fname.c_str(), "rb");
645657
if (!f) {
646658
LOG_ERR("Unable to open file %s: %s\n", fname.c_str(), strerror(errno));
647659
throw std::runtime_error("Unable to open image file");
648660
}
649661
fseek(f, 0, SEEK_END);
650662
long file_size = ftell(f);
663+
if (file_size > opt.local_media_max_size_mb * 1024 * 1024) {
664+
fclose(f);
665+
throw std::runtime_error("Local file exceeds maximum allowed size");
666+
}
651667
fseek(f, 0, SEEK_SET);
652668
buf.resize(file_size);
653669
size_t n_read = fread(buf.data(), 1, file_size, f);
@@ -656,9 +672,9 @@ static json oaicompat_chat_params_parse(
656672
LOG_ERR("Failed to read entire file %s", fname.c_str());
657673
throw std::runtime_error("Failed to read entire image file");
658674
}
659-
out_files.push_back(buf);
675+
out_files.push_back(buf);
660676

661-
} else {
677+
} else {
662678
// try to decode base64 image
663679
std::vector<std::string> parts = string_split<std::string>(url, /*separator*/ ',');
664680
if (parts.size() != 2) {

0 commit comments

Comments
 (0)