Browse Source

Less aggressive string unescaping

ManlyMarco 4 years ago
parent
commit
47a248e623
1 changed files with 109 additions and 2 deletions
  1. 109 2
      BepInEx/Configuration/TomlTypeConverter.cs

+ 109 - 2
BepInEx/Configuration/TomlTypeConverter.cs

@@ -2,6 +2,7 @@
 using System.Collections.Generic;
 using System.Globalization;
 using System.Runtime.CompilerServices;
+using System.Text;
 using System.Text.RegularExpressions;
 using UnityEngine;
 using Logger = BepInEx.Logging.Logger;
@@ -18,13 +19,13 @@ namespace BepInEx.Configuration
 		{
 			[typeof(string)] = new TypeConverter
 			{
-				ConvertToString = (obj, type) => Regex.Escape((string)obj),
+				ConvertToString = (obj, type) => 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);
+					return Unescape(str);
 				},
 			},
 			[typeof(bool)] = new TypeConverter
@@ -199,6 +200,112 @@ namespace BepInEx.Configuration
 			try { LazyTomlConverterLoader.AddUnityEngineConverters(); }
 			catch (Exception ex) { Logger.LogWarning("Failed to load UnityEngine Toml converters - " + ex.Message); }
 		}
+
+		private static string Escape(this string txt)
+		{
+			var stringBuilder = new StringBuilder(txt.Length + 2);
+			foreach (char c in txt)
+				switch (c)
+				{
+					case '\0':
+						stringBuilder.Append(@"\0");
+						break;
+					case '\a':
+						stringBuilder.Append(@"\a");
+						break;
+					case '\b':
+						stringBuilder.Append(@"\b");
+						break;
+					case '\t':
+						stringBuilder.Append(@"\t");
+						break;
+					case '\n':
+						stringBuilder.Append(@"\n");
+						break;
+					case '\v':
+						stringBuilder.Append(@"\v");
+						break;
+					case '\f':
+						stringBuilder.Append(@"\f");
+						break;
+					case '\r':
+						stringBuilder.Append(@"\r");
+						break;
+					case '\'':
+						stringBuilder.Append(@"\'");
+						break;
+					case '\\':
+						stringBuilder.Append(@"\");
+						break;
+					case '\"':
+						stringBuilder.Append(@"\""");
+						break;
+					default:
+						stringBuilder.Append(c);
+						break;
+				}
+			return stringBuilder.ToString();
+		}
+
+		private static string Unescape(this string txt)
+		{
+			if (string.IsNullOrEmpty(txt))
+				return txt;
+			var stringBuilder = new StringBuilder(txt.Length);
+			for (int i = 0; i < txt.Length;)
+			{
+				int num = txt.IndexOf('\\', i);
+				if (num < 0 || num == txt.Length - 1)
+					num = txt.Length;
+				stringBuilder.Append(txt, i, num - i);
+				if (num >= txt.Length)
+					break;
+				char c = txt[num + 1];
+				switch (c)
+				{
+					case '0':
+						stringBuilder.Append('\0');
+						break;
+					case 'a':
+						stringBuilder.Append('\a');
+						break;
+					case 'b':
+						stringBuilder.Append('\b');
+						break;
+					case 't':
+						stringBuilder.Append('\t');
+						break;
+					case 'n':
+						stringBuilder.Append('\n');
+						break;
+					case 'v':
+						stringBuilder.Append('\v');
+						break;
+					case 'f':
+						stringBuilder.Append('\f');
+						break;
+					case 'r':
+						stringBuilder.Append('\r');
+						break;
+					case '\'':
+						stringBuilder.Append('\'');
+						break;
+					case '\"':
+						stringBuilder.Append('\"');
+						break;
+					case '\\':
+						stringBuilder.Append('\\');
+						break;
+					default:
+						stringBuilder.Append('\\').Append(c);
+						break;
+				}
+
+				i = num + 2;
+			}
+
+			return stringBuilder.ToString();
+		}
 	}
 
 	/// <summary>