diff options
Diffstat (limited to 'src/mscorlib/src/System/Reflection/AssemblyName.cs')
-rw-r--r-- | src/mscorlib/src/System/Reflection/AssemblyName.cs | 274 |
1 files changed, 222 insertions, 52 deletions
diff --git a/src/mscorlib/src/System/Reflection/AssemblyName.cs b/src/mscorlib/src/System/Reflection/AssemblyName.cs index 051f3b5f0e..48eab33ee5 100644 --- a/src/mscorlib/src/System/Reflection/AssemblyName.cs +++ b/src/mscorlib/src/System/Reflection/AssemblyName.cs @@ -24,6 +24,7 @@ namespace System.Reflection { using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Diagnostics.Contracts; + using System.Text; [Serializable] [ClassInterface(ClassInterfaceType.None)] @@ -103,19 +104,12 @@ namespace System.Reflection { public String CodeBase { -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif get { return _CodeBase; } -#if FEATURE_CORECLR - [System.Security.SecurityCritical] // auto-generated -#endif set { _CodeBase = value; } } public String EscapedCodeBase { - [System.Security.SecuritySafeCritical] // auto-generated get { if (_CodeBase == null) @@ -189,16 +183,15 @@ namespace System.Reflection { * if the file contains an assembly manifest. This method causes * the file to be opened and closed. */ - [System.Security.SecuritySafeCritical] // auto-generated static public AssemblyName GetAssemblyName(String assemblyFile) { if(assemblyFile == null) - throw new ArgumentNullException("assemblyFile"); + throw new ArgumentNullException(nameof(assemblyFile)); Contract.EndContractBlock(); // Assembly.GetNameInternal() will not demand path discovery // permission, so do that first. - String fullPath = Path.GetFullPathInternal(assemblyFile); + string fullPath = Path.GetFullPath(assemblyFile); new FileIOPermission( FileIOPermissionAccess.PathDiscovery, fullPath ).Demand(); return nGetFileInformation(fullPath); } @@ -230,7 +223,6 @@ namespace System.Reflection { // The compressed version of the public key formed from a truncated hash. // Will throw a SecurityException if _PublicKey is invalid - [System.Security.SecuritySafeCritical] // auto-generated public byte[] GetPublicKeyToken() { if (_PublicKeyToken == null) @@ -279,7 +271,6 @@ namespace System.Reflection { public String FullName { - [System.Security.SecuritySafeCritical] // auto-generated get { return nToString(); } @@ -295,11 +286,10 @@ namespace System.Reflection { return s; } - [System.Security.SecurityCritical] // auto-generated_required public void GetObjectData(SerializationInfo info, StreamingContext context) { if (info == null) - throw new ArgumentNullException("info"); + throw new ArgumentNullException(nameof(info)); Contract.EndContractBlock(); //Allocate the serialization info and serialize our static data. @@ -360,11 +350,10 @@ namespace System.Reflection { m_siInfo = info; } - [System.Security.SecuritySafeCritical] // auto-generated public AssemblyName(String assemblyName) { if (assemblyName == null) - throw new ArgumentNullException("assemblyName"); + throw new ArgumentNullException(nameof(assemblyName)); Contract.EndContractBlock(); if ((assemblyName.Length == 0) || (assemblyName[0] == '\0')) @@ -374,7 +363,6 @@ namespace System.Reflection { nInit(); } - [System.Security.SecuritySafeCritical] // auto-generated static public bool ReferenceMatchesDefinition(AssemblyName reference, AssemblyName definition) { @@ -389,7 +377,6 @@ namespace System.Reflection { /// "parse" tells us to parse the simple name of the assembly as if it was the full name /// almost never the right thing to do, but needed for compat - [System.Security.SecuritySafeCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] static internal extern bool ReferenceMatchesDefinitionInternal(AssemblyName reference, AssemblyName definition, @@ -397,11 +384,9 @@ namespace System.Reflection { - [System.Security.SecurityCritical] // auto-generated [MethodImplAttribute(MethodImplOptions.InternalCall)] internal extern void nInit(out RuntimeAssembly assembly, bool forIntrospection, bool raiseResolveEvent); - [System.Security.SecurityCritical] // auto-generated internal void nInit() { RuntimeAssembly dummy = null; @@ -486,54 +471,239 @@ namespace System.Reflection { _StrongNameKeyPair = keyPair; } -#if !FEATURE_CORECLR - void _AssemblyName.GetTypeInfoCount(out uint pcTInfo) + // This call opens and closes the file, but does not add the + // assembly to the domain. + [MethodImplAttribute(MethodImplOptions.InternalCall)] + static internal extern AssemblyName nGetFileInformation(String s); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern String nToString(); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + private extern byte[] nGetPublicKeyToken(); + + static internal String EscapeCodeBase(String codebase) { - throw new NotImplementedException(); + if (codebase == null) + return string.Empty; + + int position = 0; + char[] dest = EscapeString(codebase, 0, codebase.Length, null, ref position, true, c_DummyChar, c_DummyChar, c_DummyChar); + if (dest == null) + return codebase; + + return new string(dest, 0, position); } - void _AssemblyName.GetTypeInfo(uint iTInfo, uint lcid, IntPtr ppTInfo) + // This implementation of EscapeString has been copied from System.Private.Uri from corefx repo + // - forceX characters are always escaped if found + // - rsvd character will remain unescaped + // + // start - starting offset from input + // end - the exclusive ending offset in input + // destPos - starting offset in dest for output, on return this will be an exclusive "end" in the output. + // + // In case "dest" has lack of space it will be reallocated by preserving the _whole_ content up to current destPos + // + // Returns null if nothing has to be escaped AND passed dest was null, otherwise the resulting array with the updated destPos + // + internal unsafe static char[] EscapeString(string input, int start, int end, char[] dest, ref int destPos, + bool isUriString, char force1, char force2, char rsvd) { - throw new NotImplementedException(); + int i = start; + int prevInputPos = start; + byte* bytes = stackalloc byte[c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar]; // 40*4=160 + + fixed (char* pStr = input) + { + for (; i < end; ++i) + { + char ch = pStr[i]; + + // a Unicode ? + if (ch > '\x7F') + { + short maxSize = (short)Math.Min(end - i, (int)c_MaxUnicodeCharsReallocate - 1); + + short count = 1; + for (; count < maxSize && pStr[i + count] > '\x7f'; ++count) + ; + + // Is the last a high surrogate? + if (pStr[i + count - 1] >= 0xD800 && pStr[i + count - 1] <= 0xDBFF) + { + // Should be a rare case where the app tries to feed an invalid Unicode surrogates pair + if (count == 1 || count == end - i) + throw new FormatException(Environment.GetResourceString("Arg_FormatException")); + // need to grab one more char as a Surrogate except when it's a bogus input + ++count; + } + + dest = EnsureDestinationSize(pStr, dest, i, + (short)(count * c_MaxUTF_8BytesPerUnicodeChar * c_EncodedCharsPerByte), + c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar * c_EncodedCharsPerByte, + ref destPos, prevInputPos); + + short numberOfBytes = (short)Encoding.UTF8.GetBytes(pStr + i, count, bytes, + c_MaxUnicodeCharsReallocate * c_MaxUTF_8BytesPerUnicodeChar); + + // This is the only exception that built in UriParser can throw after a Uri ctor. + // Should not happen unless the app tries to feed an invalid Unicode String + if (numberOfBytes == 0) + throw new FormatException(Environment.GetResourceString("Arg_FormatException")); + + i += (count - 1); + + for (count = 0; count < numberOfBytes; ++count) + EscapeAsciiChar((char)bytes[count], dest, ref destPos); + + prevInputPos = i + 1; + } + else if (ch == '%' && rsvd == '%') + { + // Means we don't reEncode '%' but check for the possible escaped sequence + dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte, + c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos); + if (i + 2 < end && EscapedAscii(pStr[i + 1], pStr[i + 2]) != c_DummyChar) + { + // leave it escaped + dest[destPos++] = '%'; + dest[destPos++] = pStr[i + 1]; + dest[destPos++] = pStr[i + 2]; + i += 2; + } + else + { + EscapeAsciiChar('%', dest, ref destPos); + } + prevInputPos = i + 1; + } + else if (ch == force1 || ch == force2) + { + dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte, + c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos); + EscapeAsciiChar(ch, dest, ref destPos); + prevInputPos = i + 1; + } + else if (ch != rsvd && (isUriString ? !IsReservedUnreservedOrHash(ch) : !IsUnreserved(ch))) + { + dest = EnsureDestinationSize(pStr, dest, i, c_EncodedCharsPerByte, + c_MaxAsciiCharsReallocate * c_EncodedCharsPerByte, ref destPos, prevInputPos); + EscapeAsciiChar(ch, dest, ref destPos); + prevInputPos = i + 1; + } + } + + if (prevInputPos != i) + { + // need to fill up the dest array ? + if (prevInputPos != start || dest != null) + dest = EnsureDestinationSize(pStr, dest, i, 0, 0, ref destPos, prevInputPos); + } + } + + return dest; } - void _AssemblyName.GetIDsOfNames([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId) + // + // ensure destination array has enough space and contains all the needed input stuff + // + private unsafe static char[] EnsureDestinationSize(char* pStr, char[] dest, int currentInputPos, + short charsToAdd, short minReallocateChars, ref int destPos, int prevInputPos) { - throw new NotImplementedException(); - } + if ((object)dest == null || dest.Length < destPos + (currentInputPos - prevInputPos) + charsToAdd) + { + // allocating or reallocating array by ensuring enough space based on maxCharsToAdd. + char[] newresult = new char[destPos + (currentInputPos - prevInputPos) + minReallocateChars]; + + if ((object)dest != null && destPos != 0) + Buffer.BlockCopy(dest, 0, newresult, 0, destPos << 1); + dest = newresult; + } - void _AssemblyName.Invoke(uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams, IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr) + // ensuring we copied everything form the input string left before last escaping + while (prevInputPos != currentInputPos) + dest[destPos++] = pStr[prevInputPos++]; + return dest; + } + + internal static void EscapeAsciiChar(char ch, char[] to, ref int pos) { - throw new NotImplementedException(); + to[pos++] = '%'; + to[pos++] = s_hexUpperChars[(ch & 0xf0) >> 4]; + to[pos++] = s_hexUpperChars[ch & 0xf]; } -#endif -#if FEATURE_APTCA - internal string GetNameWithPublicKey() + internal static char EscapedAscii(char digit, char next) { - byte[] key = GetPublicKey(); + if (!(((digit >= '0') && (digit <= '9')) + || ((digit >= 'A') && (digit <= 'F')) + || ((digit >= 'a') && (digit <= 'f')))) + { + return c_DummyChar; + } + + int res = (digit <= '9') + ? ((int)digit - (int)'0') + : (((digit <= 'F') + ? ((int)digit - (int)'A') + : ((int)digit - (int)'a')) + + 10); + + if (!(((next >= '0') && (next <= '9')) + || ((next >= 'A') && (next <= 'F')) + || ((next >= 'a') && (next <= 'f')))) + { + return c_DummyChar; + } + + return (char)((res << 4) + ((next <= '9') + ? ((int)next - (int)'0') + : (((next <= 'F') + ? ((int)next - (int)'A') + : ((int)next - (int)'a')) + + 10))); + } - // The following string should not be localized because it is used in security decisions. - return Name + ", PublicKey=" + System.Security.Util.Hex.EncodeHexString(key); + private static unsafe bool IsReservedUnreservedOrHash(char c) + { + if (IsUnreserved(c)) + { + return true; + } + return (RFC3986ReservedMarks.IndexOf(c) >= 0); } -#endif - // This call opens and closes the file, but does not add the - // assembly to the domain. - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern AssemblyName nGetFileInformation(String s); + internal static unsafe bool IsUnreserved(char c) + { + if (IsAsciiLetterOrDigit(c)) + { + return true; + } + return (RFC3986UnreservedMarks.IndexOf(c) >= 0); + } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern String nToString(); + //Only consider ASCII characters + internal static bool IsAsciiLetter(char character) + { + return (character >= 'a' && character <= 'z') || + (character >= 'A' && character <= 'Z'); + } - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - private extern byte[] nGetPublicKeyToken(); - - [System.Security.SecurityCritical] // auto-generated - [MethodImplAttribute(MethodImplOptions.InternalCall)] - static internal extern String EscapeCodeBase(String codeBase); + internal static bool IsAsciiLetterOrDigit(char character) + { + return IsAsciiLetter(character) || (character >= '0' && character <= '9'); + } + + private static readonly char[] s_hexUpperChars = { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + internal const char c_DummyChar = (char)0xFFFF; //An Invalid Unicode character used as a dummy char passed into the parameter + private const short c_MaxAsciiCharsReallocate = 40; + private const short c_MaxUnicodeCharsReallocate = 40; + private const short c_MaxUTF_8BytesPerUnicodeChar = 4; + private const short c_EncodedCharsPerByte = 3; + private const string RFC3986ReservedMarks = @":/?#[]@!$&'()*+,;="; + private const string RFC3986UnreservedMarks = @"-._~"; } } |