e79aa3c0ed
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
77 lines
2.9 KiB
C#
77 lines
2.9 KiB
C#
//------------------------------------------------------------------------------
|
|
// <copyright file="Utf16StringValidator.cs" company="Microsoft">
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
// </copyright>
|
|
//------------------------------------------------------------------------------
|
|
|
|
namespace System.Web.Util {
|
|
using System;
|
|
|
|
// This class contains utility methods for dealing with security contexts when crossing AppDomain boundaries.
|
|
|
|
internal static class Utf16StringValidator {
|
|
|
|
private const char UNICODE_NULL_CHAR = '\0';
|
|
private const char UNICODE_REPLACEMENT_CHAR = '\uFFFD';
|
|
|
|
private static readonly bool _skipUtf16Validation = AppSettings.AllowRelaxedUnicodeDecoding;
|
|
|
|
public static string ValidateString(string input) {
|
|
return ValidateString(input, _skipUtf16Validation);
|
|
}
|
|
|
|
// only internal for unit testing
|
|
internal static string ValidateString(string input, bool skipUtf16Validation) {
|
|
if (skipUtf16Validation || String.IsNullOrEmpty(input)) {
|
|
return input;
|
|
}
|
|
|
|
// locate the first surrogate character
|
|
int idxOfFirstSurrogate = -1;
|
|
for (int i = 0; i < input.Length; i++) {
|
|
if (Char.IsSurrogate(input[i])) {
|
|
idxOfFirstSurrogate = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// fast case: no surrogates = return input string
|
|
if (idxOfFirstSurrogate < 0) {
|
|
return input;
|
|
}
|
|
|
|
// slow case: surrogates exist, so we need to validate them
|
|
char[] chars = input.ToCharArray();
|
|
for (int i = idxOfFirstSurrogate; i < chars.Length; i++) {
|
|
char thisChar = chars[i];
|
|
|
|
// If this character is a low surrogate, then it was not preceded by
|
|
// a high surrogate, so we'll replace it.
|
|
if (Char.IsLowSurrogate(thisChar)) {
|
|
chars[i] = UNICODE_REPLACEMENT_CHAR;
|
|
continue;
|
|
}
|
|
|
|
if (Char.IsHighSurrogate(thisChar)) {
|
|
// If this character is a high surrogate and it is followed by a
|
|
// low surrogate, allow both to remain.
|
|
if (i + 1 < chars.Length && Char.IsLowSurrogate(chars[i + 1])) {
|
|
i++; // skip the low surrogate also
|
|
continue;
|
|
}
|
|
|
|
// If this character is a high surrogate and it is not followed
|
|
// by a low surrogate, replace it.
|
|
chars[i] = UNICODE_REPLACEMENT_CHAR;
|
|
continue;
|
|
}
|
|
|
|
// Otherwise, this is a non-surrogate character and just move to the
|
|
// next character.
|
|
}
|
|
return new String(chars);
|
|
}
|
|
|
|
}
|
|
}
|