diff options
Diffstat (limited to 'src/mscorlib/src/System/Security/Util/StringExpressionSet.cs')
-rw-r--r-- | src/mscorlib/src/System/Security/Util/StringExpressionSet.cs | 752 |
1 files changed, 0 insertions, 752 deletions
diff --git a/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs b/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs deleted file mode 100644 index 8a12235106..0000000000 --- a/src/mscorlib/src/System/Security/Util/StringExpressionSet.cs +++ /dev/null @@ -1,752 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace System.Security.Util { - using System.Text; - using System; - using System.Collections; - using System.Collections.Generic; - using System.Runtime.CompilerServices; - using System.Runtime.InteropServices; - using System.Globalization; - using System.Runtime.Versioning; - using System.IO; - using System.Diagnostics; - using System.Diagnostics.Contracts; - - [Serializable] - internal class StringExpressionSet - { - // This field, as well as the expressions fields below are critical since they may contain - // canonicalized full path data potentially built out of relative data passed as input to the - // StringExpressionSet. Full trust code using the string expression set needs to ensure that before - // exposing this data out to partial trust, they protect against this. Possibilities include: - // - // 1. Using the throwOnRelative flag - // 2. Ensuring that the partial trust code has permission to see full path data - // 3. Not using this set for paths (eg EnvironmentStringExpressionSet) - // - protected ArrayList m_list; - protected bool m_ignoreCase; - protected String m_expressions; - protected String[] m_expressionsArray; - - protected bool m_throwOnRelative; - - protected static readonly char[] m_separators = { ';' }; - protected static readonly char[] m_trimChars = { ' ' }; -#if !PLATFORM_UNIX - protected static readonly char m_directorySeparator = '\\'; - protected static readonly char m_alternateDirectorySeparator = '/'; -#else - protected static readonly char m_directorySeparator = '/'; - protected static readonly char m_alternateDirectorySeparator = '\\'; -#endif // !PLATFORM_UNIX - - public StringExpressionSet() - : this( true, null, false ) - { - } - - public StringExpressionSet( String str ) - : this( true, str, false ) - { - } - - public StringExpressionSet( bool ignoreCase, bool throwOnRelative ) - : this( ignoreCase, null, throwOnRelative ) - { - } - - public StringExpressionSet( bool ignoreCase, String str, bool throwOnRelative ) - { - m_list = null; - m_ignoreCase = ignoreCase; - m_throwOnRelative = throwOnRelative; - if (str == null) - m_expressions = null; - else - AddExpressions( str ); - } - - protected virtual StringExpressionSet CreateNewEmpty() - { - return new StringExpressionSet(); - } - - public virtual StringExpressionSet Copy() - { - // SafeCritical: just copying this value around, not leaking it - - StringExpressionSet copy = CreateNewEmpty(); - if (this.m_list != null) - copy.m_list = new ArrayList(this.m_list); - - copy.m_expressions = this.m_expressions; - copy.m_ignoreCase = this.m_ignoreCase; - copy.m_throwOnRelative = this.m_throwOnRelative; - return copy; - } - - public void SetThrowOnRelative( bool throwOnRelative ) - { - this.m_throwOnRelative = throwOnRelative; - } - - private static String StaticProcessWholeString( String str ) - { - return str.Replace( m_alternateDirectorySeparator, m_directorySeparator ); - } - - private static String StaticProcessSingleString( String str ) - { - return str.Trim( m_trimChars ); - } - - protected virtual String ProcessWholeString( String str ) - { - return StaticProcessWholeString(str); - } - - protected virtual String ProcessSingleString( String str ) - { - return StaticProcessSingleString(str); - } - - public void AddExpressions( String str ) - { - if (str == null) - throw new ArgumentNullException( nameof(str) ); - Contract.EndContractBlock(); - if (str.Length == 0) - return; - - str = ProcessWholeString( str ); - - if (m_expressions == null) - m_expressions = str; - else - m_expressions = m_expressions + m_separators[0] + str; - - m_expressionsArray = null; - - // We have to parse the string and compute the list here. - // The logic in this class tries to delay this parsing but - // since operations like IsSubsetOf are called during - // demand evaluation, it is not safe to delay this step - // as that would cause concurring threads to update the object - // at the same time. The CheckList operation should ideally be - // removed from this class, but for the sake of keeping the - // changes to a minimum here, we simply make sure m_list - // cannot be null by parsing m_expressions eagerly. - - String[] arystr = Split( str ); - - if (m_list == null) - m_list = new ArrayList(); - - for (int index = 0; index < arystr.Length; ++index) - { - if (arystr[index] != null && !arystr[index].Equals( "" )) - { - String temp = ProcessSingleString( arystr[index] ); - int indexOfNull = temp.IndexOf( '\0' ); - - if (indexOfNull != -1) - temp = temp.Substring( 0, indexOfNull ); - - if (temp != null && !temp.Equals( "" )) - { - if (m_throwOnRelative) - { - if (PathInternal.IsPartiallyQualified(temp)) - { - throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) ); - } - - temp = CanonicalizePath( temp ); - } - - m_list.Add( temp ); - } - } - } - - Reduce(); - } - - public void AddExpressions( String[] str, bool checkForDuplicates, bool needFullPath ) - { - AddExpressions(CreateListFromExpressions(str, needFullPath), checkForDuplicates); - } - - public void AddExpressions( ArrayList exprArrayList, bool checkForDuplicates) - { - Debug.Assert( m_throwOnRelative, "This should only be called when throw on relative is set" ); - - m_expressionsArray = null; - m_expressions = null; - - if (m_list != null) - m_list.AddRange(exprArrayList); - else - m_list = new ArrayList(exprArrayList); - - if (checkForDuplicates) - Reduce(); - } - - - internal static ArrayList CreateListFromExpressions(String[] str, bool needFullPath) - { - if (str == null) - { - throw new ArgumentNullException( nameof(str) ); - } - Contract.EndContractBlock(); - ArrayList retArrayList = new ArrayList(); - for (int index = 0; index < str.Length; ++index) - { - if (str[index] == null) - throw new ArgumentNullException( nameof(str) ); - - // Replace alternate directory separators - String oneString = StaticProcessWholeString( str[index] ); - - if (oneString != null && oneString.Length != 0) - { - // Trim leading and trailing spaces - String temp = StaticProcessSingleString( oneString); - - int indexOfNull = temp.IndexOf( '\0' ); - - if (indexOfNull != -1) - temp = temp.Substring( 0, indexOfNull ); - - if (temp != null && temp.Length != 0) - { - if (PathInternal.IsPartiallyQualified(temp)) - { - throw new ArgumentException(Environment.GetResourceString( "Argument_AbsolutePathRequired" ) ); - } - - temp = CanonicalizePath( temp, needFullPath ); - - retArrayList.Add( temp ); - } - } - } - - return retArrayList; - } - - protected void CheckList() - { - if (m_list == null && m_expressions != null) - { - CreateList(); - } - } - - protected String[] Split( String expressions ) - { - if (m_throwOnRelative) - { - List<String> tempList = new List<String>(); - - String[] quoteSplit = expressions.Split( '\"' ); - - for (int i = 0; i < quoteSplit.Length; ++i) - { - if (i % 2 == 0) - { - String[] semiSplit = quoteSplit[i].Split( ';' ); - - for (int j = 0; j < semiSplit.Length; ++j) - { - if (semiSplit[j] != null && !semiSplit[j].Equals( "" )) - tempList.Add( semiSplit[j] ); - } - } - else - { - tempList.Add( quoteSplit[i] ); - } - } - - String[] finalArray = new String[tempList.Count]; - - IEnumerator enumerator = tempList.GetEnumerator(); - - int index = 0; - while (enumerator.MoveNext()) - { - finalArray[index++] = (String)enumerator.Current; - } - - return finalArray; - } - else - { - return expressions.Split( m_separators ); - } - } - - - protected void CreateList() - { - String[] expressionsArray = Split( m_expressions ); - - m_list = new ArrayList(); - - for (int index = 0; index < expressionsArray.Length; ++index) - { - if (expressionsArray[index] != null && !expressionsArray[index].Equals( "" )) - { - String temp = ProcessSingleString( expressionsArray[index] ); - - int indexOfNull = temp.IndexOf( '\0' ); - - if (indexOfNull != -1) - temp = temp.Substring( 0, indexOfNull ); - - if (temp != null && !temp.Equals( "" )) - { - if (m_throwOnRelative) - { - if (PathInternal.IsPartiallyQualified(temp)) - { - throw new ArgumentException( Environment.GetResourceString( "Argument_AbsolutePathRequired" ) ); - } - - temp = CanonicalizePath( temp ); - } - - m_list.Add( temp ); - } - } - } - } - - public bool IsEmpty() - { - // SafeCritical: we're just showing that the expressions are empty, the sensitive portion is their - // contents - not the existence of the contents - if (m_list == null) - { - return m_expressions == null; - } - else - { - return m_list.Count == 0; - } - } - - public bool IsSubsetOf( StringExpressionSet ses ) - { - if (this.IsEmpty()) - return true; - - if (ses == null || ses.IsEmpty()) - return false; - - CheckList(); - ses.CheckList(); - - for (int index = 0; index < this.m_list.Count; ++index) - { - if (!StringSubsetStringExpression( (String)this.m_list[index], ses, m_ignoreCase )) - { - return false; - } - } - return true; - } - - public bool IsSubsetOfPathDiscovery( StringExpressionSet ses ) - { - if (this.IsEmpty()) - return true; - - if (ses == null || ses.IsEmpty()) - return false; - - CheckList(); - ses.CheckList(); - - for (int index = 0; index < this.m_list.Count; ++index) - { - if (!StringSubsetStringExpressionPathDiscovery( (String)this.m_list[index], ses, m_ignoreCase )) - { - return false; - } - } - return true; - } - - - public StringExpressionSet Union( StringExpressionSet ses ) - { - // If either set is empty, the union represents a copy of the other. - - if (ses == null || ses.IsEmpty()) - return this.Copy(); - - if (this.IsEmpty()) - return ses.Copy(); - - CheckList(); - ses.CheckList(); - - // Perform the union - // note: insert smaller set into bigger set to reduce needed comparisons - - StringExpressionSet bigger = ses.m_list.Count > this.m_list.Count ? ses : this; - StringExpressionSet smaller = ses.m_list.Count <= this.m_list.Count ? ses : this; - - StringExpressionSet unionSet = bigger.Copy(); - - unionSet.Reduce(); - - for (int index = 0; index < smaller.m_list.Count; ++index) - { - unionSet.AddSingleExpressionNoDuplicates( (String)smaller.m_list[index] ); - } - - unionSet.GenerateString(); - - return unionSet; - } - - - public StringExpressionSet Intersect( StringExpressionSet ses ) - { - // If either set is empty, the intersection is empty - - if (this.IsEmpty() || ses == null || ses.IsEmpty()) - return CreateNewEmpty(); - - CheckList(); - ses.CheckList(); - - // Do the intersection for real - - StringExpressionSet intersectSet = CreateNewEmpty(); - - for (int this_index = 0; this_index < this.m_list.Count; ++this_index) - { - for (int ses_index = 0; ses_index < ses.m_list.Count; ++ses_index) - { - if (StringSubsetString( (String)this.m_list[this_index], (String)ses.m_list[ses_index], m_ignoreCase )) - { - if (intersectSet.m_list == null) - { - intersectSet.m_list = new ArrayList(); - } - intersectSet.AddSingleExpressionNoDuplicates( (String)this.m_list[this_index] ); - } - else if (StringSubsetString( (String)ses.m_list[ses_index], (String)this.m_list[this_index], m_ignoreCase )) - { - if (intersectSet.m_list == null) - { - intersectSet.m_list = new ArrayList(); - } - intersectSet.AddSingleExpressionNoDuplicates( (String)ses.m_list[ses_index] ); - } - } - } - - intersectSet.GenerateString(); - - return intersectSet; - } - - protected void GenerateString() - { - // SafeCritical - moves critical data around, but doesn't expose it out - if (m_list != null) - { - StringBuilder sb = new StringBuilder(); - - IEnumerator enumerator = this.m_list.GetEnumerator(); - bool first = true; - - while (enumerator.MoveNext()) - { - if (!first) - sb.Append( m_separators[0] ); - else - first = false; - - String currentString = (String)enumerator.Current; - if (currentString != null) - { - int indexOfSeparator = currentString.IndexOf( m_separators[0] ); - - if (indexOfSeparator != -1) - sb.Append( '\"' ); - - sb.Append( currentString ); - - if (indexOfSeparator != -1) - sb.Append( '\"' ); - } - } - - m_expressions = sb.ToString(); - } - else - { - m_expressions = null; - } - } - - // We don't override ToString since that API must be either transparent or safe citical. If the - // expressions contain paths that were canonicalized and expanded from the input that would cause - // information disclosure, so we instead only expose this out to trusted code that can ensure they - // either don't leak the information or required full path information. - public string UnsafeToString() - { - CheckList(); - - Reduce(); - - GenerateString(); - - return m_expressions; - } - - public String[] UnsafeToStringArray() - { - if (m_expressionsArray == null && m_list != null) - { - m_expressionsArray = (String[])m_list.ToArray(typeof(String)); - } - - return m_expressionsArray; - } - - - //------------------------------- - // protected static helper functions - //------------------------------- - - private bool StringSubsetStringExpression( String left, StringExpressionSet right, bool ignoreCase ) - { - for (int index = 0; index < right.m_list.Count; ++index) - { - if (StringSubsetString( left, (String)right.m_list[index], ignoreCase )) - { - return true; - } - } - return false; - } - - private static bool StringSubsetStringExpressionPathDiscovery( String left, StringExpressionSet right, bool ignoreCase ) - { - for (int index = 0; index < right.m_list.Count; ++index) - { - if (StringSubsetStringPathDiscovery( left, (String)right.m_list[index], ignoreCase )) - { - return true; - } - } - return false; - } - - - protected virtual bool StringSubsetString( String left, String right, bool ignoreCase ) - { - StringComparison strComp = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); - if (right == null || left == null || right.Length == 0 || left.Length == 0 || - right.Length > left.Length) - { - return false; - } - else if (right.Length == left.Length) - { - // if they are equal in length, just do a normal compare - return String.Compare( right, left, strComp) == 0; - } - else if (left.Length - right.Length == 1 && left[left.Length-1] == m_directorySeparator) - { - return String.Compare( left, 0, right, 0, right.Length, strComp) == 0; - } - else if (right[right.Length-1] == m_directorySeparator) - { - // right is definitely a directory, just do a substring compare - return String.Compare( right, 0, left, 0, right.Length, strComp) == 0; - } - else if (left[right.Length] == m_directorySeparator) - { - // left is hinting at being a subdirectory on right, do substring compare to make find out - return String.Compare( right, 0, left, 0, right.Length, strComp) == 0; - } - else - { - return false; - } - } - - protected static bool StringSubsetStringPathDiscovery( String left, String right, bool ignoreCase ) - { - StringComparison strComp = (ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal); - if (right == null || left == null || right.Length == 0 || left.Length == 0) - { - return false; - } - else if (right.Length == left.Length) - { - // if they are equal in length, just do a normal compare - return String.Compare( right, left, strComp) == 0; - } - else - { - String shortString, longString; - - if (right.Length < left.Length) - { - shortString = right; - longString = left; - } - else - { - shortString = left; - longString = right; - } - - if (String.Compare( shortString, 0, longString, 0, shortString.Length, strComp) != 0) - { - return false; - } - -#if !PLATFORM_UNIX - if (shortString.Length == 3 && - shortString.EndsWith( ":\\", StringComparison.Ordinal ) && - ((shortString[0] >= 'A' && shortString[0] <= 'Z') || - (shortString[0] >= 'a' && shortString[0] <= 'z'))) -#else - if (shortString.Length == 1 && shortString[0]== m_directorySeparator) -#endif // !PLATFORM_UNIX - return true; - - return longString[shortString.Length] == m_directorySeparator; - } - } - - - //------------------------------- - // protected helper functions - //------------------------------- - - protected void AddSingleExpressionNoDuplicates( String expression ) - { - // SafeCritical: We're not exposing out the string sets, just allowing modification of them - int index = 0; - - m_expressionsArray = null; - m_expressions = null; - - if (this.m_list == null) - this.m_list = new ArrayList(); - - while (index < this.m_list.Count) - { - if (StringSubsetString( (String)this.m_list[index], expression, m_ignoreCase )) - { - this.m_list.RemoveAt( index ); - } - else if (StringSubsetString( expression, (String)this.m_list[index], m_ignoreCase )) - { - return; - } - else - { - index++; - } - } - this.m_list.Add( expression ); - } - - protected void Reduce() - { - CheckList(); - - if (this.m_list == null) - return; - - int j; - - for (int i = 0; i < this.m_list.Count - 1; i++) - { - j = i + 1; - - while (j < this.m_list.Count) - { - if (StringSubsetString( (String)this.m_list[j], (String)this.m_list[i], m_ignoreCase )) - { - this.m_list.RemoveAt( j ); - } - else if (StringSubsetString( (String)this.m_list[i], (String)this.m_list[j], m_ignoreCase )) - { - // write the value at j into position i, delete the value at position j and keep going. - this.m_list[i] = this.m_list[j]; - this.m_list.RemoveAt( j ); - j = i + 1; - } - else - { - j++; - } - } - } - } - - [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)] - [SuppressUnmanagedCodeSecurity] - internal static extern void GetLongPathName( String path, StringHandleOnStack retLongPath ); - - internal static String CanonicalizePath( String path ) - { - return CanonicalizePath( path, true ); - } - - internal static string CanonicalizePath(string path, bool needFullPath) - { - if (needFullPath) - { - string newPath = Path.GetFullPath(path); - if (path.EndsWith(m_directorySeparator + ".", StringComparison.Ordinal)) - { - if (newPath.EndsWith(m_directorySeparator)) - { - newPath += "."; - } - else - { - newPath += m_directorySeparator + "."; - } - } - path = newPath; - } -#if !PLATFORM_UNIX - else if (path.IndexOf('~') != -1) - { - // GetFullPathInternal() will expand 8.3 file names - string longPath = null; - GetLongPathName(path, JitHelpers.GetStringHandleOnStack(ref longPath)); - path = (longPath != null) ? longPath : path; - } - - // This blocks usage of alternate data streams and some extended syntax paths (\\?\C:\). Checking after - // normalization allows valid paths such as " C:\" to be considered ok (as it will become "C:\"). - if (path.IndexOf(':', 2) != -1) - throw new NotSupportedException(Environment.GetResourceString("Argument_PathFormatNotSupported")); -#endif // !PLATFORM_UNIX - - return path; - } - } -} |