5 Commits

Author SHA1 Message Date
Devid HW 12fba8ad4b bump version to 1.32.3
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 01:26:08 +07:00
Devid HW b6171d0c56 fix: INI newline injection in backtest config generation
Add ini_safe() helper that strips CR/LF from user-supplied string params
before they are written into terminal.ini and backtest_config.ini.
Applies to: expert path, symbol, timeframe, set_file — any value that
could carry an embedded newline and inject extra INI directives.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-23 01:24:59 +07:00
Devid HW 05214ff34b revert version to 1.32.1 2026-04-23 01:15:27 +07:00
github-actions[bot] 498126dfd4 ci: update server.json SHA256 for v1.32.1 [skip ci] 2026-04-22 18:11:41 +00:00
Devid HW 147da213d6 bump version to 1.32.2 for crates.io republication 2026-04-23 01:11:14 +07:00
4 changed files with 18 additions and 13 deletions
Generated
+1 -1
View File
@@ -481,7 +481,7 @@ dependencies = [
[[package]]
name = "mt5-quant"
version = "1.32.1"
version = "1.32.3"
dependencies = [
"anyhow",
"base64",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "mt5-quant"
version = "1.32.1"
version = "1.32.3"
edition = "2021"
description = "MCP server for MT5 strategy development on macOS/Linux"
authors = ["masdevid <masdevid@example.com>"]
+4 -4
View File
@@ -7,13 +7,13 @@
"url": "https://github.com/masdevid/mt5-quant",
"source": "github"
},
"version": "1.32.0",
"version": "1.32.1",
"packages": [
{
"registryType": "mcpb",
"version": "1.32.0",
"identifier": "https://github.com/masdevid/mt5-quant/releases/download/v1.32.0/mcp-mt5-quant-macos-arm64.tar.gz",
"fileSha256": "8b4e058d7b42265e8a89c0dcd9567cc7bd06b8358f7b2799966a1e92cea816f7",
"version": "1.32.1",
"identifier": "https://github.com/masdevid/mt5-quant/releases/download/v1.32.1/mcp-mt5-quant-macos-arm64.tar.gz",
"fileSha256": "a2525e1c0e74587d87f37414652b29b402983625663eb2b3435496e31a2e9714",
"transport": {
"type": "stdio"
},
+12 -7
View File
@@ -823,12 +823,12 @@ impl BacktestPipeline {
};
let set_file_line = params.set_file.as_ref()
.map(|p| format!("ExpertParameters={}\n", p))
.map(|p| format!("ExpertParameters={}\n", Self::ini_safe(p)))
.unwrap_or_default();
let updates: &[(&str, String)] = &[
("Expert", expert_path),
("Symbol", params.symbol.clone()),
("Expert", Self::ini_safe(&expert_path)),
("Symbol", Self::ini_safe(&params.symbol)),
("Period", period.to_string()),
("DateRange", "3".into()),
("DateFrom", from_ts.to_string()),
@@ -855,6 +855,11 @@ impl BacktestPipeline {
Ok(())
}
/// Strip CR/LF from a user-supplied INI value to prevent newline injection.
fn ini_safe(value: &str) -> String {
value.replace(['\n', '\r'], "")
}
fn patch_ini_section(text: &str, section: &str, updates: &[(&str, String)]) -> String {
let section_header = format!("[{}]", section);
let mut result = String::with_capacity(text.len() + 256);
@@ -1025,9 +1030,9 @@ impl BacktestPipeline {
ini.push_str("[Tester]\n");
// Expert path is relative to MQL5/Experts/ in the /config: format (no "Experts\" prefix).
ini.push_str(&format!("Expert={}\n", self.resolve_backtest_ini_expert_path(&params.expert)));
ini.push_str(&format!("Symbol={}\n", params.symbol));
ini.push_str(&format!("Period={}\n", params.timeframe));
ini.push_str(&format!("Expert={}\n", Self::ini_safe(&self.resolve_backtest_ini_expert_path(&params.expert))));
ini.push_str(&format!("Symbol={}\n", Self::ini_safe(&params.symbol)));
ini.push_str(&format!("Period={}\n", Self::ini_safe(&params.timeframe)));
ini.push_str("Optimization=0\n");
ini.push_str(&format!("Model={}\n", params.model));
ini.push_str(&format!("FromDate={}\n", params.from_date));
@@ -1044,7 +1049,7 @@ impl BacktestPipeline {
ini.push_str(&format!("ShutdownTerminal={}\n", if params.shutdown { "1" } else { "0" }));
if let Some(set_file) = &params.set_file {
ini.push_str(&format!("ExpertParameters={}\n", set_file));
ini.push_str(&format!("ExpertParameters={}\n", Self::ini_safe(set_file)));
}
Ok(ini)