Skip to content

Commit fa7902b

Browse files
committed
fix: validate DNS override on save and free version string
- Add MihomoValidateDns to the bridge (yaml.Unmarshal syntax check), exposed as MihomoCore.validateDns; the DNS editor now rejects malformed input with an error dialog instead of failing at reconnect. - Free the Go-allocated string in the nativeVersion JNI wrapper, which previously leaked on every call. Both touch mihomo_jni.cpp, so they share one commit.
1 parent 96ca5cc commit fa7902b

7 files changed

Lines changed: 53 additions & 2 deletions

File tree

app/src/main/cpp/mihomo_jni.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ char* MihomoTraffic();
1010
char* MihomoProxies();
1111
int MihomoSelectProxy(char* group, char* name);
1212
char* MihomoProxyDelay(char* name, char* url, int timeout_ms);
13+
char* MihomoValidateDns(char* dns_yaml);
1314
}
1415

1516
extern "C" JNIEXPORT jint JNICALL
@@ -44,7 +45,9 @@ Java_top_uwu_mikubox_core_MihomoCore_nativeLastError(JNIEnv* env, jobject /* thi
4445
extern "C" JNIEXPORT jstring JNICALL
4546
Java_top_uwu_mikubox_core_MihomoCore_nativeVersion(JNIEnv* env, jobject /* thiz */) {
4647
char* version = MihomoVersion();
47-
return env->NewStringUTF(version == nullptr ? "unknown" : version);
48+
jstring result = env->NewStringUTF(version == nullptr ? "unknown" : version);
49+
std::free(version);
50+
return result;
4851
}
4952

5053
extern "C" JNIEXPORT jstring JNICALL
@@ -88,3 +91,14 @@ Java_top_uwu_mikubox_core_MihomoCore_nativeProxyDelay(
8891
std::free(delay);
8992
return result;
9093
}
94+
95+
extern "C" JNIEXPORT jstring JNICALL
96+
Java_top_uwu_mikubox_core_MihomoCore_nativeValidateDns(
97+
JNIEnv* env, jobject /* thiz */, jstring dns_yaml) {
98+
const char* dns_chars = env->GetStringUTFChars(dns_yaml, nullptr);
99+
char* err = MihomoValidateDns(const_cast<char*>(dns_chars));
100+
env->ReleaseStringUTFChars(dns_yaml, dns_chars);
101+
jstring result = env->NewStringUTF(err == nullptr ? "" : err);
102+
std::free(err);
103+
return result;
104+
}

app/src/main/java/top/uwu/mikubox/core/MihomoCore.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ object MihomoCore {
9696
runCatching { JSONObject(nativeProxyDelay(name, url, timeoutMs)).optInt("delay", -1) }
9797
.getOrDefault(-1)
9898

99+
/** Validates a DNS override block; returns null when valid, or an error message. */
100+
fun validateDns(yaml: String): String? = nativeValidateDns(yaml).ifBlank { null }
101+
99102
private fun JSONArray?.toStringList(): List<String> =
100103
if (this == null) emptyList() else List(length()) { optString(it) }
101104

@@ -112,4 +115,5 @@ object MihomoCore {
112115
private external fun nativeProxies(): String
113116
private external fun nativeSelectProxy(group: String, name: String): Int
114117
private external fun nativeProxyDelay(name: String, url: String, timeoutMs: Int): String
118+
private external fun nativeValidateDns(dnsYaml: String): String
115119
}

app/src/main/java/top/uwu/mikubox/ui/DnsActivity.kt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package top.uwu.mikubox.ui
22

33
import android.os.Bundle
44
import android.widget.Toast
5+
import com.google.android.material.dialog.MaterialAlertDialogBuilder
56
import top.uwu.mikubox.R
7+
import top.uwu.mikubox.core.MihomoCore
68
import top.uwu.mikubox.core.MihomoDnsSettings
79
import top.uwu.mikubox.databinding.ActivityDnsBinding
810

@@ -27,7 +29,17 @@ class DnsActivity : EdgeToEdgeActivity() {
2729
applyEnabled(checked)
2830
}
2931
binding.btnSave.setOnClickListener {
30-
MihomoDnsSettings.setYaml(this, binding.etDns.text?.toString().orEmpty())
32+
val yaml = binding.etDns.text?.toString().orEmpty()
33+
val error = MihomoCore.validateDns(yaml)
34+
if (error != null) {
35+
MaterialAlertDialogBuilder(this)
36+
.setTitle(R.string.dns_invalid_title)
37+
.setMessage(error)
38+
.setPositiveButton(android.R.string.ok, null)
39+
.show()
40+
return@setOnClickListener
41+
}
42+
MihomoDnsSettings.setYaml(this, yaml)
3143
toast(R.string.toast_dns_saved)
3244
}
3345
binding.btnReset.setOnClickListener {

app/src/main/res/values-zh-rCN/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
<string name="dns_override">覆盖 DNS</string>
145145
<string name="dns_override_summary">用下方的内容替换每个配置的 dns 部分</string>
146146
<string name="dns_yaml_hint">DNS(YAML)</string>
147+
<string name="dns_invalid_title">DNS 配置无效</string>
147148
<string name="dns_restart_hint">重新连接以应用更改。</string>
148149
<string name="action_save">保存</string>
149150
<string name="action_reset">重置</string>

app/src/main/res/values-zh-rTW/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,7 @@
144144
<string name="dns_override">覆寫 DNS</string>
145145
<string name="dns_override_summary">以下方的區塊取代每個設定檔的 dns 區段</string>
146146
<string name="dns_yaml_hint">DNS(YAML)</string>
147+
<string name="dns_invalid_title">DNS 設定無效</string>
147148
<string name="dns_restart_hint">重新連線以套用變更。</string>
148149
<string name="action_save">儲存</string>
149150
<string name="action_reset">重設</string>

app/src/main/res/values/strings.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,7 @@
154154
<string name="dns_override">Override DNS</string>
155155
<string name="dns_override_summary">Replace each profile\'s dns section with the block below</string>
156156
<string name="dns_yaml_hint">DNS (YAML)</string>
157+
<string name="dns_invalid_title">Invalid DNS configuration</string>
157158
<string name="dns_restart_hint">Reconnect to apply changes.</string>
158159
<string name="action_save">Save</string>
159160
<string name="action_reset">Reset</string>

core/mihomo-bridge/main.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import "C"
88
import (
99
"context"
1010
"encoding/json"
11+
"strings"
1112
"sync"
1213
"time"
1314

@@ -167,6 +168,23 @@ func MihomoProxyDelay(proxyName *C.char, testURL *C.char, timeoutMS C.int) *C.ch
167168
return C.CString(string(payload))
168169
}
169170

171+
// MihomoValidateDns checks that a DNS override block is well-formed YAML that
172+
// unmarshals to a mapping. Returns an empty string when valid (or blank), or a
173+
// human-readable error otherwise, so the editor can reject bad input up front.
174+
//
175+
//export MihomoValidateDns
176+
func MihomoValidateDns(dnsYaml *C.char) *C.char {
177+
text := strings.TrimSpace(C.GoString(dnsYaml))
178+
if text == "" {
179+
return C.CString("")
180+
}
181+
dns := map[string]any{}
182+
if err := yaml.Unmarshal([]byte(text), &dns); err != nil {
183+
return C.CString(err.Error())
184+
}
185+
return C.CString("")
186+
}
187+
170188
func start(configText, homeDir string, tunFD int, dnsOverride string) error {
171189
constant.SetHomeDir(homeDir)
172190
if err := config.Init(homeDir); err != nil {

0 commit comments

Comments
 (0)