fix(validator,migration,fuzzer): resilient domain validation, strip prefixed comments and fix zapret1 fuzzer fwmark
This commit is contained in:
@@ -1,7 +1,13 @@
|
||||
export function parseValueList(value: string): string[] {
|
||||
return value
|
||||
.split(/\n/)
|
||||
.map((line) => line.split('//')[0].split('#')[0])
|
||||
.split(/\r?\n/)
|
||||
.map((line) => {
|
||||
const stripped = line.replace(
|
||||
/^(full|keyword|regex):[ \t]*(\/\/|#).*$/,
|
||||
'',
|
||||
);
|
||||
return stripped.split('//')[0].split('#')[0];
|
||||
})
|
||||
.join(' ')
|
||||
.split(/[,\s]+/)
|
||||
.map((s) => s.trim())
|
||||
|
||||
@@ -1046,7 +1046,13 @@ function validateProxyUrl(url) {
|
||||
|
||||
// src/helpers/parseValueList.ts
|
||||
function parseValueList(value) {
|
||||
return value.split(/\n/).map((line) => line.split("//")[0].split("#")[0]).join(" ").split(/[,\s]+/).map((s) => s.trim()).filter(Boolean);
|
||||
return value.split(/\r?\n/).map((line) => {
|
||||
const stripped = line.replace(
|
||||
/^(full|keyword|regex):[ \t]*(\/\/|#).*$/,
|
||||
""
|
||||
);
|
||||
return stripped.split("//")[0].split("#")[0];
|
||||
}).join(" ").split(/[,\s]+/).map((s) => s.trim()).filter(Boolean);
|
||||
}
|
||||
|
||||
// src/helpers/getProxyUrlName.ts
|
||||
|
||||
@@ -5521,8 +5521,9 @@ function parseCommentAwareListTokens(value) {
|
||||
let offset = 0;
|
||||
|
||||
lines.forEach((line, index) => {
|
||||
const hashIndex = line.indexOf("#");
|
||||
const slashIndex = line.indexOf("//");
|
||||
const cleanLine = line.replace(/^(full|keyword|regex):[ \t]*(\/\/|#).*$/, "");
|
||||
const hashIndex = cleanLine.indexOf("#");
|
||||
const slashIndex = cleanLine.indexOf("//");
|
||||
let commentIndex = -1;
|
||||
|
||||
if (hashIndex >= 0 && slashIndex >= 0) {
|
||||
@@ -5533,7 +5534,7 @@ function parseCommentAwareListTokens(value) {
|
||||
commentIndex = slashIndex;
|
||||
}
|
||||
|
||||
const source = commentIndex >= 0 ? line.slice(0, commentIndex) : line;
|
||||
const source = commentIndex >= 0 ? cleanLine.slice(0, commentIndex) : cleanLine;
|
||||
const matcher = /[^,\s]+/g;
|
||||
let match;
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ let core_url = require("core.url");
|
||||
let constants_module = require("core.constants");
|
||||
let singbox_constants_module = require("singbox.constants");
|
||||
let domain_config = require("config.domain");
|
||||
let rule_config = require("config.rule");
|
||||
let subscription_share_link = require("subscription.share_link");
|
||||
|
||||
let as_string = common.as_string;
|
||||
@@ -925,7 +926,9 @@ function migrate_connection_section(ctx, section, constants, legacy_connection_k
|
||||
}
|
||||
|
||||
function strip_list_comment(line) {
|
||||
line = replace(as_string(line), /[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(as_string(line), /^(full|keyword|regex):[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(line, /^(full|keyword|regex):[[:space:]]*#.*$/, "");
|
||||
line = replace(line, /[[:space:]]*\/\/.*$/, "");
|
||||
return replace(line, /[[:space:]]*#.*$/, "");
|
||||
}
|
||||
|
||||
@@ -1004,7 +1007,11 @@ function has_domain_condition_prefix(value) {
|
||||
function add_values_with_prefix(result, seen, values, prefix) {
|
||||
for (let value in values) {
|
||||
value = trim(as_string(value));
|
||||
add_unique_value(result, seen, has_domain_condition_prefix(value) ? value : prefix + value);
|
||||
if (value == "")
|
||||
continue;
|
||||
let candidate = has_domain_condition_prefix(value) ? value : prefix + value;
|
||||
if (rule_config.prefixed_domain_kind_value(candidate) != null)
|
||||
add_unique_value(result, seen, candidate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1038,10 +1045,14 @@ function migrate_combined_domain_conditions(ctx, section) {
|
||||
let values = [];
|
||||
let seen = {};
|
||||
|
||||
for (let value in list_option(section, "domain_suffix"))
|
||||
for (let value in list_option(section, "domain_suffix")) {
|
||||
if (rule_config.prefixed_domain_kind_value(value) != null)
|
||||
add_unique_value(values, seen, value);
|
||||
for (let value in raw_text_condition_values(section, "domain_suffix_text"))
|
||||
}
|
||||
for (let value in raw_text_condition_values(section, "domain_suffix_text")) {
|
||||
if (rule_config.prefixed_domain_kind_value(value) != null)
|
||||
add_unique_value(values, seen, value);
|
||||
}
|
||||
|
||||
add_domain_values_with_prefix(values, seen, section, "domain", "full:", "domains");
|
||||
add_domain_values_with_prefix(values, seen, section, "domain_keyword", "keyword:", "generic");
|
||||
|
||||
@@ -7,7 +7,9 @@ let common = require("core.common");
|
||||
let as_string = common.as_string;
|
||||
|
||||
function strip_list_comment(line) {
|
||||
line = replace(as_string(line), /[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(as_string(line), /^(full|keyword|regex):[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(line, /^(full|keyword|regex):[[:space:]]*#.*$/, "");
|
||||
line = replace(line, /[[:space:]]*\/\/.*$/, "");
|
||||
return replace(line, /[[:space:]]*#.*$/, "");
|
||||
}
|
||||
|
||||
@@ -72,7 +74,7 @@ function prefixed_domain_kind_value(value) {
|
||||
if (prefix != "")
|
||||
body = strip_repeated_domain_prefix(prefix, body);
|
||||
|
||||
if (body == "")
|
||||
if (body == "" || substr(body, 0, 2) == "//" || substr(body, 0, 1) == "#")
|
||||
return null;
|
||||
|
||||
if (prefix == "") {
|
||||
|
||||
@@ -1203,14 +1203,17 @@ function validate_combined_domain_value(value, section) {
|
||||
if (as_string(value) == "" || combined_domain_valid(value))
|
||||
return;
|
||||
|
||||
fail_validation("Invalid domain condition '" + value + "' in rule '" + section + "'. Use plain domains or full:, keyword:, regex: prefixes. Aborted.");
|
||||
log_message("Ignoring invalid domain condition '" + value + "' in rule '" + section + "'. Use plain domains or full:, keyword:, regex: prefixes.", "warn");
|
||||
}
|
||||
|
||||
function validate_combined_domain_text_value(value, section) {
|
||||
if (as_string(value) == "" || combined_domain_text_valid(value))
|
||||
if (as_string(value) == "")
|
||||
return;
|
||||
|
||||
fail_validation("Invalid domain conditions in rule '" + section + "'. Use plain domains or full:, keyword:, regex: prefixes. Aborted.");
|
||||
for (let item in rule_config.text_list_values(value, "comma-space")) {
|
||||
if (!combined_domain_valid(item))
|
||||
log_message("Ignoring invalid domain condition '" + item + "' in rule '" + section + "'. Use plain domains or full:, keyword:, regex: prefixes.", "warn");
|
||||
}
|
||||
}
|
||||
|
||||
function validate_service_value(service, context) {
|
||||
|
||||
@@ -383,7 +383,9 @@ function normalize_strategy_whitespace(value) {
|
||||
}
|
||||
|
||||
function strip_list_comment(line) {
|
||||
line = replace(as_string(line), /[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(as_string(line), /^(full|keyword|regex):[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(line, /^(full|keyword|regex):[[:space:]]*#.*$/, "");
|
||||
line = replace(line, /[[:space:]]*\/\/.*$/, "");
|
||||
return replace(line, /[[:space:]]*#.*$/, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -2245,7 +2245,16 @@ function run_probe(engine, args_str, target_key, custom_url) {
|
||||
filter_prefix += "--filter-udp=443 --payload=quic_initial ";
|
||||
}
|
||||
|
||||
let spawn_cmd = sprintf("cd /tmp && %s --qnum=%d --fwmark=%s %s%s%s%s --pidfile=%s --daemon 2>%s", bin, qnum, FUZZER_FWMARK, lua_init_flags, blob_flags, filter_prefix, args_str, pid_path, shell_quote(stderr_log));
|
||||
let fwmark_flag = "";
|
||||
if (is_z2) {
|
||||
if (index(args_str, "--fwmark") < 0)
|
||||
fwmark_flag = sprintf("--fwmark=%s ", FUZZER_FWMARK);
|
||||
} else {
|
||||
if (index(args_str, "--dpi-desync-fwmark") < 0)
|
||||
fwmark_flag = sprintf("--dpi-desync-fwmark=%s ", FUZZER_FWMARK);
|
||||
}
|
||||
|
||||
let spawn_cmd = sprintf("cd /tmp && %s --qnum=%d %s%s%s%s%s --pidfile=%s --daemon 2>%s", bin, qnum, fwmark_flag, lua_init_flags, blob_flags, filter_prefix, args_str, pid_path, shell_quote(stderr_log));
|
||||
system(common.background_command(spawn_cmd));
|
||||
|
||||
let pid_running = false;
|
||||
|
||||
@@ -140,7 +140,9 @@ function log_fatal(message) {
|
||||
}
|
||||
|
||||
function strip_list_comment(line) {
|
||||
line = replace(as_string(line), /[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(as_string(line), /^(full|keyword|regex):[[:space:]]*\/\/.*$/, "");
|
||||
line = replace(line, /^(full|keyword|regex):[[:space:]]*#.*$/, "");
|
||||
line = replace(line, /[[:space:]]*\/\/.*$/, "");
|
||||
return replace(line, /[[:space:]]*#.*$/, "");
|
||||
}
|
||||
|
||||
|
||||
@@ -522,4 +522,29 @@ fi
|
||||
printf '%s\n' "$output" | grep -Fq "ByeDPI listen address and port are assigned" ||
|
||||
fail "executable byedpi provider: unexpected message '$output'"
|
||||
|
||||
# ─── Domain condition validation resilience ─────────────────────────────────
|
||||
cat >"$WORK_DIR/domain_resilience.json" <<'JSON'
|
||||
{
|
||||
"settings": {
|
||||
".name": "settings",
|
||||
".type": "settings",
|
||||
"dns_server": [ "77.88.8.8" ],
|
||||
"bootstrap_dns_server": [ "77.88.8.8" ]
|
||||
},
|
||||
"section": [
|
||||
{
|
||||
".name": "resilient_rule",
|
||||
".type": "section",
|
||||
"enabled": "1",
|
||||
"action": "bypass",
|
||||
"domain": "valid.example.com\nfull://\nfull:=====\nfull:(не\nanother.example.org"
|
||||
}
|
||||
]
|
||||
}
|
||||
JSON
|
||||
|
||||
if ! TACHYON_LIB="$TACHYON_LIB" ucode -L "$TACHYON_LIB" "$VALIDATOR" validate-runtime-fixture "$WORK_DIR/domain_resilience.json" "{}" >/dev/null 2>&1; then
|
||||
fail "Validator must not abort startup on invalid domain conditions in rules"
|
||||
fi
|
||||
|
||||
printf 'config validator runtime checks passed\n'
|
||||
|
||||
Reference in New Issue
Block a user