1 //------------------------------------------------------------------------------
2 // <copyright file="Utf16StringValidator.cs" company="Microsoft">
3 // Copyright (c) Microsoft Corporation. All rights reserved.
5 //------------------------------------------------------------------------------
7 namespace System.Web.Util {
10 // This class contains utility methods for dealing with security contexts when crossing AppDomain boundaries.
12 internal static class Utf16StringValidator {
14 private const char UNICODE_NULL_CHAR = '\0';
15 private const char UNICODE_REPLACEMENT_CHAR = '\uFFFD';
17 private static readonly bool _skipUtf16Validation = AppSettings.AllowRelaxedUnicodeDecoding;
19 public static string ValidateString(string input) {
20 return ValidateString(input, _skipUtf16Validation);
23 // only internal for unit testing
24 internal static string ValidateString(string input, bool skipUtf16Validation) {
25 if (skipUtf16Validation || String.IsNullOrEmpty(input)) {
29 // locate the first surrogate character
30 int idxOfFirstSurrogate = -1;
31 for (int i = 0; i < input.Length; i++) {
32 if (Char.IsSurrogate(input[i])) {
33 idxOfFirstSurrogate = i;
38 // fast case: no surrogates = return input string
39 if (idxOfFirstSurrogate < 0) {
43 // slow case: surrogates exist, so we need to validate them
44 char[] chars = input.ToCharArray();
45 for (int i = idxOfFirstSurrogate; i < chars.Length; i++) {
46 char thisChar = chars[i];
48 // If this character is a low surrogate, then it was not preceded by
49 // a high surrogate, so we'll replace it.
50 if (Char.IsLowSurrogate(thisChar)) {
51 chars[i] = UNICODE_REPLACEMENT_CHAR;
55 if (Char.IsHighSurrogate(thisChar)) {
56 // If this character is a high surrogate and it is followed by a
57 // low surrogate, allow both to remain.
58 if (i + 1 < chars.Length && Char.IsLowSurrogate(chars[i + 1])) {
59 i++; // skip the low surrogate also
63 // If this character is a high surrogate and it is not followed
64 // by a low surrogate, replace it.
65 chars[i] = UNICODE_REPLACEMENT_CHAR;
69 // Otherwise, this is a non-surrogate character and just move to the
72 return new String(chars);