Skip to content

Commit 3498fef

Browse files
committed
fix: sanitize DNS preference inputs
1 parent cd76a34 commit 3498fef

2 files changed

Lines changed: 32 additions & 4 deletions

File tree

app/src/main/java/io/nekohasekai/sagernet/fmt/ConfigBuilder.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ import moe.matsuri.nb4a.utils.Util
4747
import moe.matsuri.nb4a.utils.listByLineOrComma
4848
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
4949

50+
private fun sanitizeDnsEntry(value: String): String {
51+
return value.filterNot { it.isISOControl() }.trim()
52+
}
53+
5054
const val TAG_MIXED = "mixed-in"
5155

5256
const val TAG_PROXY = "proxy"
@@ -144,9 +148,9 @@ fun buildConfig(
144148
val isVPN = DataStore.serviceMode == Key.MODE_VPN
145149
val bind = if (!forTest && DataStore.allowAccess) "0.0.0.0" else LOCALHOST
146150
val remoteDns = DataStore.remoteDns.split("\n")
147-
.mapNotNull { dns -> dns.trim().takeIf { it.isNotBlank() && !it.startsWith("#") } }
151+
.mapNotNull { dns -> sanitizeDnsEntry(dns).takeIf { it.isNotBlank() && !it.startsWith("#") } }
148152
val directDNS = DataStore.directDns.split("\n")
149-
.mapNotNull { dns -> dns.trim().takeIf { it.isNotBlank() && !it.startsWith("#") } }
153+
.mapNotNull { dns -> sanitizeDnsEntry(dns).takeIf { it.isNotBlank() && !it.startsWith("#") } }
150154
val enableDnsRouting = DataStore.enableDnsRouting
151155
val useFakeDns = DataStore.enableFakeDns && !forTest
152156
val needSniff = DataStore.trafficSniffing > 0

app/src/main/java/io/nekohasekai/sagernet/ui/SettingsPreferenceFragment.kt

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,26 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
4141
true
4242
}
4343

44+
private fun sanitizeDnsPreferenceValue(value: String): String {
45+
return value.lines().joinToString("\n") { line ->
46+
line.filterNot { it.isISOControl() }.trim()
47+
}
48+
}
49+
50+
private fun dnsReloadListener(preference: Preference, newValue: Any?): Boolean {
51+
val rawValue = newValue as? String ?: return reloadListener.onPreferenceChange(preference, newValue)
52+
val sanitizedValue = sanitizeDnsPreferenceValue(rawValue)
53+
if (sanitizedValue != rawValue) {
54+
if (preference is EditTextPreference) {
55+
preference.text = sanitizedValue
56+
}
57+
needReload()
58+
return false
59+
}
60+
needReload()
61+
return true
62+
}
63+
4464
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
4565
preferenceManager.preferenceDataStore = DataStore.configurationStore
4666
DataStore.initGlobal()
@@ -203,8 +223,12 @@ class SettingsPreferenceFragment : PreferenceFragmentCompat() {
203223
concurrentDial.onPreferenceChangeListener = reloadListener
204224

205225
enableFakeDns.onPreferenceChangeListener = reloadListener
206-
remoteDns.onPreferenceChangeListener = reloadListener
207-
directDns.onPreferenceChangeListener = reloadListener
226+
remoteDns.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference, newValue ->
227+
dnsReloadListener(preference, newValue)
228+
}
229+
directDns.onPreferenceChangeListener = Preference.OnPreferenceChangeListener { preference, newValue ->
230+
dnsReloadListener(preference, newValue)
231+
}
208232
enableDnsRouting.onPreferenceChangeListener = reloadListener
209233

210234
ipv6Mode.onPreferenceChangeListener = reloadListener

0 commit comments

Comments
 (0)