diff --git a/BepInEx/Configuration/TomlTypeConverter.cs b/BepInEx/Configuration/TomlTypeConverter.cs index 4b24a93..baddc4a 100644 --- a/BepInEx/Configuration/TomlTypeConverter.cs +++ b/BepInEx/Configuration/TomlTypeConverter.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Globalization; +using System.Text.RegularExpressions; namespace BepInEx.Configuration { @@ -13,8 +14,14 @@ namespace BepInEx.Configuration { [typeof(string)] = new TypeConverter { - ConvertToString = (obj, type) => (string)obj, - ConvertToObject = (str, type) => str, + ConvertToString = (obj, type) => Regex.Escape((string)obj), + ConvertToObject = (str, type) => + { + // Check if the string is a file path with unescaped \ path separators (e.g. D:\test and not D:\\test) + if (Regex.IsMatch(str, @"^""?\w:\\(?!\\)(?!.+\\\\)")) + return str; + return Regex.Unescape(str); + }, }, [typeof(bool)] = new TypeConverter { diff --git a/BepInExTests/Configuration/ConfigFileTests.cs b/BepInExTests/Configuration/ConfigFileTests.cs index 31c9c4e..cf2d8ff 100644 --- a/BepInExTests/Configuration/ConfigFileTests.cs +++ b/BepInExTests/Configuration/ConfigFileTests.cs @@ -247,5 +247,50 @@ namespace BepInEx.Configuration.Tests c.Reload(); Assert.AreEqual(shortcut, w.Value); } + + [TestMethod] + public void StringEscapeChars() + { + const string testVal = "new line\n test \t\0"; + + var c = MakeConfig(); + var w = c.Wrap("Cat", "Key", testVal, new ConfigDescription("Test")); + + Assert.AreEqual(testVal, w.Value); + Assert.IsFalse(w.ConfigEntry.GetSerializedValue().Any(x => x == '\n')); + + w.ConfigEntry.SetSerializedValue(w.ConfigEntry.GetSerializedValue()); + Assert.AreEqual(testVal, w.Value); + + c.Save(); + c.Reload(); + + Assert.AreEqual(testVal, w.Value); + } + + [TestMethod] + public void UnescapedPathString() + { + var c = MakeConfig(); + + var unescaped = @"D:\test\p ath"; + foreach (string testVal in new[]{ unescaped , @"D:\\test\\p ath" }) + { + File.WriteAllText(c.ConfigFilePath, $"[Cat]\n# Test\nKey={testVal}\n"); + c.Reload(); + + var w = c.Wrap("Cat", "Key", "", new ConfigDescription("Test")); + + Assert.AreEqual(unescaped, w.Value); + + w.ConfigEntry.SetSerializedValue(w.ConfigEntry.GetSerializedValue()); + Assert.AreEqual(unescaped, w.Value); + + c.Save(); + c.Reload(); + + Assert.AreEqual(unescaped, w.Value); + } + } } }