You've already forked linux-packaging-mono
Imported Upstream version 4.3.2.467
Former-commit-id: 9c2cb47f45fa221e661ab616387c9cda183f283d
This commit is contained in:
@@ -124,6 +124,12 @@ namespace System.Web.Util {
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:EnsureSessionStateLockedOnFlush"], out _ensureSessionStateLockedOnFlush))
|
||||
_ensureSessionStateLockedOnFlush = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:UseRandomizedStringHashAlgorithm"], out _useRandomizedStringHashAlgorithm))
|
||||
_useRandomizedStringHashAlgorithm = false;
|
||||
|
||||
if (settings == null || !Boolean.TryParse(settings["aspnet:EnableAsyncModelBinding"], out _enableAsyncModelBinding))
|
||||
_enableAsyncModelBinding = BinaryCompatibility.Current.TargetsAtLeastFramework46;
|
||||
|
||||
_settingsInitialized = true;
|
||||
}
|
||||
}
|
||||
@@ -465,5 +471,26 @@ namespace System.Web.Util {
|
||||
return _ensureSessionStateLockedOnFlush;
|
||||
}
|
||||
}
|
||||
|
||||
// false [default] - don't force randomized hash code algorithm. Exisiting behavior
|
||||
// true - use randomized hash code algorithm
|
||||
private static bool _useRandomizedStringHashAlgorithm;
|
||||
internal static bool UseRandomizedStringHashAlgorithm {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _useRandomizedStringHashAlgorithm;
|
||||
}
|
||||
}
|
||||
|
||||
// false - disable async model binding
|
||||
// true - enable async model binding
|
||||
// defaults to true when targeting >= 4.6, otherwise false
|
||||
private static bool _enableAsyncModelBinding;
|
||||
internal static bool EnableAsyncModelBinding {
|
||||
get {
|
||||
EnsureSettingsLoaded();
|
||||
return _enableAsyncModelBinding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,6 +38,11 @@
|
||||
{ AppVerifierErrorCode.BeginHandlerReturnedUnexpectedAsyncResultInstance, SR.AppVerifier_Errors_AsyncCallbackInvokedWithUnexpectedAsyncResultInstance },
|
||||
{ AppVerifierErrorCode.BeginHandlerReturnedUnexpectedAsyncResultAsyncState, SR.AppVerifier_Errors_BeginHandlerReturnedUnexpectedAsyncResultAsyncState },
|
||||
{ AppVerifierErrorCode.SyncContextSendOrPostCalledAfterRequestCompleted, SR.AppVerifier_Errors_SyncContextSendOrPostCalledAfterRequestCompleted },
|
||||
{ AppVerifierErrorCode.SyncContextSendOrPostCalledBetweenNotifications, SR.AppVerifier_Errors_SyncContextSendOrPostCalledBetweenNotifications },
|
||||
{ AppVerifierErrorCode.SyncContextPostCalledInNestedNotification, SR.AppVerifier_Errors_SyncContextPostCalledInNestedNotification },
|
||||
{ AppVerifierErrorCode.RequestNotificationCompletedSynchronouslyWithNotificationContextPending, SR.AppVerifier_Errors_RequestNotificationCompletedSynchronouslyWithNotificationContextPending },
|
||||
{ AppVerifierErrorCode.NotificationContextHasChangedAfterSynchronouslyProcessingNotification, SR.AppVerifier_Errors_NotificationContextHasChangedAfterSynchronouslyProcessingNotification },
|
||||
{ AppVerifierErrorCode.PendingProcessRequestNotificationStatusAfterCompletingNestedNotification, SR.AppVerifier_Errors_PendingProcessRequestNotificationStatusAfterCompletingNestedNotification },
|
||||
};
|
||||
|
||||
// Provides an option for different wrappers to specify whether to collect the call stacks traces
|
||||
@@ -63,12 +68,13 @@
|
||||
|
||||
// The declarative order of these two fields is important; don't swap them!
|
||||
private static Action<AppVerifierException> DefaultAppVerifierBehavior = GetAppVerifierBehaviorFromRegistry();
|
||||
private static readonly bool IsAppVerifierEnabled = (DefaultAppVerifierBehavior != null);
|
||||
internal static readonly bool IsAppVerifierEnabled = (DefaultAppVerifierBehavior != null);
|
||||
private static long AppVerifierErrorCodeCollectCallStackMask;
|
||||
private static long AppVerifierErrorCodeEnableAssertMask;
|
||||
private static CallStackCollectionBitMasks AppVerifierCollectCallStackMask;
|
||||
|
||||
private delegate void AssertDelegate(bool condition, AppVerifierErrorCode errorCode);
|
||||
private delegate void AppendAdditionalInfoDelegate(StringBuilder errorString);
|
||||
|
||||
// Returns an AppVerifier handler (something that can record exceptions appropriately)
|
||||
// appropriate to what was set in the system registry. If the key we're looking for
|
||||
@@ -183,7 +189,7 @@
|
||||
bool captureBeginStack = (myBeginMask & (CallStackCollectionBitMasks)AppVerifierCollectCallStackMask) == myBeginMask;
|
||||
|
||||
InvocationInfo beginHandlerInvocationInfo = InvocationInfo.Capture(captureBeginStack);
|
||||
Uri requestUrl = null;
|
||||
string requestUrl = null;
|
||||
RequestNotification? currentNotification = null;
|
||||
bool isPostNotification = false;
|
||||
Type httpHandlerType = null;
|
||||
@@ -193,7 +199,7 @@
|
||||
HttpContext context = httpApplication.Context;
|
||||
if (context != null) {
|
||||
if (!context.HideRequestResponse && context.Request != null) {
|
||||
requestUrl = context.Request.Unvalidated.Url;
|
||||
requestUrl = TryGetRequestUrl(context);
|
||||
}
|
||||
|
||||
if (context.NotificationContext != null) {
|
||||
@@ -444,8 +450,9 @@
|
||||
}
|
||||
|
||||
// Gets a delegate that checks for application code trying to call into the SyncContext after
|
||||
// the request is already completed. The Action returned by this method could be null.
|
||||
public static Action GetSyncContextCheckDelegate(ISyncContext syncContext) {
|
||||
// the request or the request notification is already completed.
|
||||
// The Action returned by this method could be null.
|
||||
public static Action<bool> GetSyncContextCheckDelegate(ISyncContext syncContext) {
|
||||
if (!IsAppVerifierEnabled) {
|
||||
return null;
|
||||
}
|
||||
@@ -454,21 +461,22 @@
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an Action that determines whether SynchronizationContext.Send or Post was called after the underlying request finished.
|
||||
/// Returns an Action<bool> that determines whether SynchronizationContext.Send or Post was called after the underlying request
|
||||
/// or the request notification finished. The bool parameter controls whether to check if Post is attempted in nested notification.
|
||||
/// The instrumentation can be a performance hit, so this method should not be called if AppVerifier is not enabled.
|
||||
/// </summary>
|
||||
/// <param name="syncContext">The ISyncContext (HttpApplication, WebSocketPipeline, etc.) on which to perform the check.</param>
|
||||
/// <param name="errorHandler">The listener that can handle verification failures.</param>
|
||||
/// <returns>A callback which performs the verification.</returns>
|
||||
internal static Action GetSyncContextCheckDelegateImpl(ISyncContext syncContext, Action<AppVerifierException> errorHandler) {
|
||||
Uri requestUrl = null;
|
||||
internal static Action<bool> GetSyncContextCheckDelegateImpl(ISyncContext syncContext, Action<AppVerifierException> errorHandler) {
|
||||
string requestUrl = null;
|
||||
object originalThreadContextId = null;
|
||||
|
||||
// collect all of the diagnostic information upfront
|
||||
HttpContext originalHttpContext = (syncContext != null) ? syncContext.HttpContext : null;
|
||||
if (originalHttpContext != null) {
|
||||
if (!originalHttpContext.HideRequestResponse && originalHttpContext.Request != null) {
|
||||
requestUrl = originalHttpContext.Request.Unvalidated.Url;
|
||||
requestUrl = TryGetRequestUrl(originalHttpContext);
|
||||
}
|
||||
|
||||
// This will be used as a surrogate for the captured HttpContext so that we don't
|
||||
@@ -479,7 +487,113 @@
|
||||
}
|
||||
|
||||
// If the condition passed to this method evaluates to false, we will raise an error to whoever is listening.
|
||||
AssertDelegate assert = (condition, errorCode) => {
|
||||
AssertDelegate assert = GetAssertDelegateImpl(requestUrl, errorHandler, appendAdditionalInfoDelegate: null);
|
||||
|
||||
return (checkForReEntry) => {
|
||||
try {
|
||||
// Make sure that the ISyncContext is still associated with the same HttpContext that
|
||||
// we captured earlier.
|
||||
HttpContext currentHttpContext = (syncContext != null) ? syncContext.HttpContext : null;
|
||||
object currentThreadContextId = (currentHttpContext != null) ? currentHttpContext.ThreadContextId : null;
|
||||
assert(currentThreadContextId != null && ReferenceEquals(originalThreadContextId, currentThreadContextId), AppVerifierErrorCode.SyncContextSendOrPostCalledAfterRequestCompleted);
|
||||
|
||||
if (HttpRuntime.UsingIntegratedPipeline && !currentHttpContext.HasWebSocketRequestTransitionCompleted) {
|
||||
var notificationContext = (currentHttpContext != null) ? currentHttpContext.NotificationContext : null;
|
||||
assert(notificationContext != null, AppVerifierErrorCode.SyncContextSendOrPostCalledBetweenNotifications);
|
||||
|
||||
if (checkForReEntry && notificationContext != null) {
|
||||
assert(!notificationContext.IsReEntry, AppVerifierErrorCode.SyncContextPostCalledInNestedNotification);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (AppVerifierException) {
|
||||
// We want to ---- any exceptions thrown by our verification logic, as the failure
|
||||
// has already been recorded by the appropriate listener. Propagate the original
|
||||
// exception upward.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// This generic method invokes a delegate that was created by AppVerifier at an earlier time.
|
||||
// It is safe to call it even if the returned delegate is null (e.g. AppVerifier is off).
|
||||
// Here is the typical usage scenario:
|
||||
// var verifierCheck = AppVerifier.Get*CheckDelegate(...); // get the delegate which can capture some state
|
||||
// T result = <...> // the result of some code execution
|
||||
// AppVerifier.InvokeVerifierCheck(verifierCheckDelegate, result); // invoke the verification of the result
|
||||
internal static void InvokeVerifierCheck<T>(Action<T> verifierCheckDelegate, T result)
|
||||
{
|
||||
if (verifierCheckDelegate != null) {
|
||||
try {
|
||||
verifierCheckDelegate(result);
|
||||
}
|
||||
catch (AppVerifierException) {
|
||||
// We want to ---- any exceptions thrown by our verification logic, as the failure
|
||||
// has already been recorded by the appropriate listener.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a delegate that checks for inconsistencies after managed code finished processing one or more request notifications.
|
||||
// The Action returned by this method could be null.
|
||||
internal static Action<RequestNotificationStatus> GetRequestNotificationStatusCheckDelegate(HttpContext context, RequestNotification currentNotification, bool isPostNotification) {
|
||||
if (!IsAppVerifierEnabled) {
|
||||
return null;
|
||||
}
|
||||
return GetRequestNotificationStatusCheckDelegateImpl(context, currentNotification, isPostNotification, HandleAppVerifierException);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an Action<RequestNotificationStatus> that will check for inconsistencies after
|
||||
/// managed code has finished processing one or more notifications and about to return back to IIS.
|
||||
/// </summary>
|
||||
/// <returns>A callback which performs the verification.</returns>
|
||||
internal static Action<RequestNotificationStatus> GetRequestNotificationStatusCheckDelegateImpl(HttpContext context, RequestNotification currentNotification, bool isPostNotification, Action<AppVerifierException> errorHandler) {
|
||||
// collect all of the diagnostic information upfront
|
||||
NotificationContext originalNotificationContext = context.NotificationContext;
|
||||
bool isReentry = originalNotificationContext.IsReEntry;
|
||||
string requestUrl = null;
|
||||
if (!context.HideRequestResponse && context.Request != null) {
|
||||
requestUrl = TryGetRequestUrl(context);
|
||||
}
|
||||
|
||||
AppendAdditionalInfoDelegate appendCurrentNotificationInfo = (errorString) => {
|
||||
errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_NotificationInfo, currentNotification, isPostNotification, isReentry));
|
||||
};
|
||||
|
||||
AssertDelegate assert = GetAssertDelegateImpl(requestUrl, errorHandler, appendAdditionalInfoDelegate: appendCurrentNotificationInfo);
|
||||
|
||||
return (RequestNotificationStatus status) => {
|
||||
if (status == RequestNotificationStatus.Pending) {
|
||||
// We don't expect nested notifications to complete asynchronously
|
||||
assert(!isReentry, AppVerifierErrorCode.PendingProcessRequestNotificationStatusAfterCompletingNestedNotification);
|
||||
}
|
||||
else {
|
||||
// Completing synchronously with pending NotificationContext means a bug in either user code or the pipeline.
|
||||
// NotificationContext being null means we already completed asynchronously before completing synchronously.
|
||||
// Both cases indicate that we have some async operations we failed to account for.
|
||||
assert(context.NotificationContext != null && !context.NotificationContext.PendingAsyncCompletion,
|
||||
AppVerifierErrorCode.RequestNotificationCompletedSynchronouslyWithNotificationContextPending);
|
||||
|
||||
// Can't have a different NotificationContext after finishing the notification
|
||||
// Even if it was changed while processing nested notifications it should be restored back before we unwind
|
||||
assert(context.NotificationContext == originalNotificationContext,
|
||||
AppVerifierErrorCode.NotificationContextHasChangedAfterSynchronouslyProcessingNotification);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This method returns the default implementation of the assert code which takes care of
|
||||
/// evaluating the assert contition, handing assert and stack collection enabling masks,
|
||||
/// and creating an AppVerifierException with basic information
|
||||
/// </summary>
|
||||
/// <param name="requestUrl">The Url of the request.</param>
|
||||
/// <param name="errorHandler">The listener that can handle verification failures.</param>
|
||||
/// <param name="appendAdditionalInfoDelegate">The caller can provide this delegate to append additional information to the exception. Could be null.</param>
|
||||
/// <returns>A callback which performs the verification.</returns>
|
||||
private static AssertDelegate GetAssertDelegateImpl(string requestUrl, Action<AppVerifierException> errorHandler, AppendAdditionalInfoDelegate appendAdditionalInfoDelegate) {
|
||||
// If the condition passed to this method evaluates to false, we will raise an error to whoever is listening.
|
||||
return (condition, errorCode) => {
|
||||
long mask = 1L << (int)errorCode;
|
||||
// assert only if it was not masked out by a bit set
|
||||
bool enableAssert = (AppVerifierErrorCodeEnableAssertMask & mask) == mask;
|
||||
@@ -500,6 +614,13 @@
|
||||
errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_ErrorCode, (int)errorCode));
|
||||
errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_Description, GetLocalizedDescriptionStringForError(errorCode)));
|
||||
errorString.AppendLine(FormatErrorString(SR.AppVerifier_BasicInfo_ThreadInfo, assertInvocationInfo.ThreadId, assertInvocationInfo.Timestamp.ToLocalTime()));
|
||||
|
||||
// append additional info if needed
|
||||
if (appendAdditionalInfoDelegate != null) {
|
||||
appendAdditionalInfoDelegate(errorString);
|
||||
}
|
||||
|
||||
// append the stack trace
|
||||
errorString.AppendLine(assertInvocationInfo.StackTrace.ToString());
|
||||
|
||||
AppVerifierException ex = new AppVerifierException(errorCode, errorString.ToString());
|
||||
@@ -507,23 +628,9 @@
|
||||
throw ex;
|
||||
}
|
||||
};
|
||||
|
||||
return () => {
|
||||
try {
|
||||
// Make sure that the ISyncContext is still associated with the same HttpContext that
|
||||
// we captured earlier.
|
||||
HttpContext currentHttpContext = (syncContext != null) ? syncContext.HttpContext : null;
|
||||
object currentThreadContextId = (currentHttpContext != null) ? currentHttpContext.ThreadContextId : null;
|
||||
assert(currentThreadContextId != null && ReferenceEquals(originalThreadContextId, currentThreadContextId), AppVerifierErrorCode.SyncContextSendOrPostCalledAfterRequestCompleted);
|
||||
}
|
||||
catch (AppVerifierException) {
|
||||
// We want to ---- any exceptions thrown by our verification logic, as the failure
|
||||
// has already been recorded by the appropriate listener. Propagate the original
|
||||
// exception upward.
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// This is the default implementation of an AppVerifierException handler;
|
||||
// it just delegates to the configured behavior.
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive", Justification = "Want to keep these locals on the stack to assist with debugging.")]
|
||||
@@ -543,6 +650,15 @@
|
||||
GC.KeepAlive(ex);
|
||||
}
|
||||
|
||||
private static string TryGetRequestUrl(HttpContext context) {
|
||||
try {
|
||||
return context.Request.EnsureRawUrl();
|
||||
}
|
||||
catch (HttpException) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
internal static string PrettyPrintDelegate(Delegate del) {
|
||||
return PrettyPrintMemberInfo((del != null) ? del.Method : null);
|
||||
}
|
||||
|
@@ -27,7 +27,11 @@
|
||||
BeginHandlerReturnedAsyncResultMarkedCompletedSynchronouslyButAsyncCallbackNeverCalled,
|
||||
BeginHandlerReturnedUnexpectedAsyncResultInstance,
|
||||
BeginHandlerReturnedUnexpectedAsyncResultAsyncState,
|
||||
SyncContextSendOrPostCalledAfterRequestCompleted
|
||||
|
||||
SyncContextSendOrPostCalledAfterRequestCompleted,
|
||||
SyncContextSendOrPostCalledBetweenNotifications,
|
||||
SyncContextPostCalledInNestedNotification,
|
||||
RequestNotificationCompletedSynchronouslyWithNotificationContextPending,
|
||||
NotificationContextHasChangedAfterSynchronouslyProcessingNotification,
|
||||
PendingProcessRequestNotificationStatusAfterCompletingNestedNotification
|
||||
}
|
||||
}
|
||||
|
@@ -30,11 +30,15 @@ namespace System.Web.Util {
|
||||
TargetsAtLeastFramework45 = (version >= VersionUtil.Framework45);
|
||||
TargetsAtLeastFramework451 = (version >= VersionUtil.Framework451);
|
||||
TargetsAtLeastFramework452 = (version >= VersionUtil.Framework452);
|
||||
TargetsAtLeastFramework46 = (version >= VersionUtil.Framework46);
|
||||
TargetsAtLeastFramework461 = (version >= VersionUtil.Framework461);
|
||||
}
|
||||
|
||||
public bool TargetsAtLeastFramework45 { get; private set; }
|
||||
public bool TargetsAtLeastFramework451 { get; private set; }
|
||||
public bool TargetsAtLeastFramework452 { get; private set; }
|
||||
public bool TargetsAtLeastFramework46 { get; private set; }
|
||||
public bool TargetsAtLeastFramework461 { get; private set; }
|
||||
|
||||
public Version TargetFramework { get; private set; }
|
||||
|
||||
|
@@ -103,7 +103,7 @@ internal class HashCodeCombiner {
|
||||
|
||||
internal void AddCaseInsensitiveString(string s) {
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
|
||||
AddInt(StringUtil.GetNonRandomizedHashCode(s, ignoreCase:true));
|
||||
}
|
||||
|
||||
internal void AddDateTime(DateTime dt) {
|
||||
@@ -131,7 +131,7 @@ internal class HashCodeCombiner {
|
||||
}
|
||||
|
||||
private void AddFileContentHashKey(string fileContentHashKey) {
|
||||
AddInt(fileContentHashKey.GetHashCode());
|
||||
AddInt(StringUtil.GetNonRandomizedHashCode(fileContentHashKey));
|
||||
}
|
||||
|
||||
internal void AddFileContentHash(string fileName) {
|
||||
|
26
external/referencesource/System.Web/Util/HeapAllocHandle.cs
vendored
Normal file
26
external/referencesource/System.Web/Util/HeapAllocHandle.cs
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="HeapAllocHandle.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
internal class HeapAllocHandle : SafeHandleZeroOrMinusOneIsInvalid {
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources", Justification = @"This pointer is valid for the lifetime of the process; never needs to be released.")]
|
||||
private static readonly IntPtr ProcessHeap = UnsafeNativeMethods.GetProcessHeap();
|
||||
|
||||
// Called by P/Invoke when returning SafeHandles
|
||||
protected HeapAllocHandle()
|
||||
: base(ownsHandle: true) {
|
||||
}
|
||||
|
||||
// Do not provide a finalizer - SafeHandle's critical finalizer will call ReleaseHandle for you.
|
||||
protected override bool ReleaseHandle() {
|
||||
return UnsafeNativeMethods.HeapFree(ProcessHeap, 0, handle);
|
||||
}
|
||||
}
|
||||
}
|
@@ -633,8 +633,17 @@ namespace System.Web.Util {
|
||||
}
|
||||
|
||||
// nothing to expand?
|
||||
if (cSpaces == 0 && cUnsafe == 0)
|
||||
return bytes;
|
||||
if (cSpaces == 0 && cUnsafe == 0) {
|
||||
// DevDiv 912606: respect "offset" and "count"
|
||||
if (0 == offset && bytes.Length == count) {
|
||||
return bytes;
|
||||
}
|
||||
else {
|
||||
var subarray = new byte[count];
|
||||
Buffer.BlockCopy(bytes, offset, subarray, 0, count);
|
||||
return subarray;
|
||||
}
|
||||
}
|
||||
|
||||
// expand not 'safe' characters into %XX, spaces to +s
|
||||
byte[] expandedBytes = new byte[count + cUnsafe * 2];
|
||||
@@ -748,6 +757,37 @@ namespace System.Web.Util {
|
||||
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings",
|
||||
Justification = "Does not represent an entire URL, just a portion.")]
|
||||
protected internal virtual string UrlPathEncode(string value) {
|
||||
// DevDiv 995259: HttpUtility.UrlPathEncode should not encode IDN part of the url
|
||||
if (BinaryCompatibility.Current.TargetsAtLeastFramework46) {
|
||||
if (String.IsNullOrEmpty(value)) {
|
||||
return value;
|
||||
}
|
||||
|
||||
string schemeAndAuthority;
|
||||
string path;
|
||||
string queryAndFragment;
|
||||
bool isValidUrl = UriUtil.TrySplitUriForPathEncode(value, out schemeAndAuthority, out path, out queryAndFragment, checkScheme: false);
|
||||
|
||||
if (!isValidUrl) {
|
||||
// If the value is not a valid url, we treat it as a relative url.
|
||||
// We don't need to extract query string from the url since UrlPathEncode()
|
||||
// does not encode query string.
|
||||
schemeAndAuthority = null;
|
||||
path = value;
|
||||
queryAndFragment = null;
|
||||
}
|
||||
|
||||
return schemeAndAuthority + UrlPathEncodeImpl(path) + queryAndFragment;
|
||||
}
|
||||
else {
|
||||
return UrlPathEncodeImpl(value);
|
||||
}
|
||||
}
|
||||
|
||||
// This is the original UrlPathEncode(string)
|
||||
[SuppressMessage("Microsoft.Design", "CA1055:UriReturnValuesShouldNotBeStrings",
|
||||
Justification = "Does not represent an entire URL, just a portion.")]
|
||||
private string UrlPathEncodeImpl(string value) {
|
||||
if (String.IsNullOrEmpty(value)) {
|
||||
return value;
|
||||
}
|
||||
@@ -755,7 +795,7 @@ namespace System.Web.Util {
|
||||
// recurse in case there is a query string
|
||||
int i = value.IndexOf('?');
|
||||
if (i >= 0)
|
||||
return UrlPathEncode(value.Substring(0, i)) + value.Substring(i);
|
||||
return UrlPathEncodeImpl(value.Substring(0, i)) + value.Substring(i);
|
||||
|
||||
// encode DBCS characters and spaces only
|
||||
return HttpEncoderUtility.UrlEncodeSpaces(UrlEncodeNonAscii(value, Encoding.UTF8));
|
||||
|
83
external/referencesource/System.Web/Util/RegexUtil.cs
vendored
Normal file
83
external/referencesource/System.Web/Util/RegexUtil.cs
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace System.Web.Util {
|
||||
internal class RegexUtil {
|
||||
|
||||
// this method is for the regex match which accepts the pattern from developer
|
||||
// since asp.net doesn't have control of the regex pattern string and it is possible
|
||||
// to take more than 2 sec to match a string, give developer option to set timeout value
|
||||
public static bool IsMatch(string stringToMatch, string pattern, RegexOptions regOption, int? timeoutInMillsec) {
|
||||
int timeout = GetRegexTimeout(timeoutInMillsec);
|
||||
|
||||
if (timeout > 0 || timeoutInMillsec.HasValue) {
|
||||
return Regex.IsMatch(stringToMatch, pattern, regOption, TimeSpan.FromMilliseconds((double)timeout));
|
||||
} else {
|
||||
return Regex.IsMatch(stringToMatch, pattern, regOption);
|
||||
}
|
||||
}
|
||||
|
||||
public static Match Match(string stringToMatch, string pattern, RegexOptions regOption, int? timeoutInMillsec) {
|
||||
int timeout = GetRegexTimeout(timeoutInMillsec);
|
||||
|
||||
if (timeout > 0 || timeoutInMillsec.HasValue) {
|
||||
return Regex.Match(stringToMatch, pattern, regOption, TimeSpan.FromMilliseconds((double)timeout));
|
||||
} else {
|
||||
return Regex.Match(stringToMatch, pattern, regOption);
|
||||
}
|
||||
}
|
||||
|
||||
public static Regex CreateRegex(string pattern, RegexOptions option, int? timeoutInMillsec) {
|
||||
int timeout = GetRegexTimeout(timeoutInMillsec);
|
||||
|
||||
if (timeout > 0 || timeoutInMillsec.HasValue) {
|
||||
return new Regex(pattern, option, TimeSpan.FromMilliseconds((double)timeout));
|
||||
} else {
|
||||
return new Regex(pattern, option);
|
||||
}
|
||||
}
|
||||
|
||||
// This method is for the regex asp.net controls the regex pattern and it should NOT take longer than 2 secs to match the string
|
||||
// so no need for developer to specify a timeout value
|
||||
internal static Regex CreateRegex(string pattern, RegexOptions option) {
|
||||
return CreateRegex(pattern, option, null);
|
||||
}
|
||||
|
||||
private static bool? _isRegexTimeoutSetInAppDomain;
|
||||
private static bool IsRegexTimeoutSetInAppDomain {
|
||||
get {
|
||||
if (!_isRegexTimeoutSetInAppDomain.HasValue) {
|
||||
bool timeoutSetInAppDomain = false;
|
||||
try {
|
||||
timeoutSetInAppDomain = AppDomain.CurrentDomain.GetData("REGEX_DEFAULT_MATCH_TIMEOUT") != null;
|
||||
} catch {
|
||||
}
|
||||
_isRegexTimeoutSetInAppDomain = timeoutSetInAppDomain;
|
||||
}
|
||||
return _isRegexTimeoutSetInAppDomain.Value;
|
||||
}
|
||||
}
|
||||
|
||||
private static int GetRegexTimeout(int? timeoutInMillsec) {
|
||||
int timeout = -1;
|
||||
|
||||
// here is the logic for using timeout in regex
|
||||
// 1. if the caller sets a timeout value, then we use it(this may cause Regex throw ArgumentOutOfRangeException,
|
||||
// but developer will know what they need to do when seeing the exception)
|
||||
// 2. if there is global setting in AppDomain, we do nothing(leave it to Regex to handle the timeout)
|
||||
// 3. if the web app targets to 4.6.1+, then we set 2 secs timeout
|
||||
if (timeoutInMillsec.HasValue) {
|
||||
timeout = timeoutInMillsec.Value;
|
||||
} else {
|
||||
if (!IsRegexTimeoutSetInAppDomain && BinaryCompatibility.Current.TargetsAtLeastFramework461) {
|
||||
timeout = 2000;
|
||||
}
|
||||
}
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
}
|
@@ -215,6 +215,17 @@ namespace System.Web.Util {
|
||||
return iValue;
|
||||
}
|
||||
|
||||
internal static int? GetNullableIntValue(NameValueCollection config, string valueName) {
|
||||
int iValue;
|
||||
string sValue = config[valueName];
|
||||
|
||||
if (sValue == null || !Int32.TryParse(sValue, out iValue)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return iValue;
|
||||
}
|
||||
|
||||
#if !FEATURE_PAL //
|
||||
internal static void CheckSchemaVersion(ProviderBase provider, SqlConnection connection, string[] features, string version, ref int schemaVersionCheck) {
|
||||
if (connection == null) {
|
||||
|
@@ -14,6 +14,7 @@ namespace System.Web.Util {
|
||||
using System.Text;
|
||||
using System.Globalization;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Web.Hosting;
|
||||
|
||||
/*
|
||||
* Various string handling utilities
|
||||
@@ -202,7 +203,7 @@ internal static class StringUtil {
|
||||
|
||||
return 0 == string.Compare(s1, 0, s2, 0, s2.Length, StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
#if !MONO
|
||||
internal unsafe static void UnsafeStringCopy(string src, int srcIndex, char[] dest, int destIndex, int len) {
|
||||
// We do not verify the parameters in this function, as the callers are assumed
|
||||
// to have done so. This is important for users such as HttpWriter that already
|
||||
@@ -225,7 +226,7 @@ internal static class StringUtil {
|
||||
memcpyimpl(pbSrc, pbDest, cb);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
internal static bool StringArrayEquals(string[] a, string [] b) {
|
||||
if ((a == null) != (b == null)) {
|
||||
return false;
|
||||
@@ -274,7 +275,46 @@ internal static class StringUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
#if !MONO
|
||||
internal static int GetNonRandomizedHashCode(string s, bool ignoreCase = false) {
|
||||
// Preserve the default behavior when string hash randomization is off
|
||||
if (!AppSettings.UseRandomizedStringHashAlgorithm) {
|
||||
return ignoreCase ? StringComparer.InvariantCultureIgnoreCase.GetHashCode(s) : s.GetHashCode();
|
||||
}
|
||||
|
||||
if (ignoreCase) {
|
||||
s = s.ToLower(CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
// Use our stable hash algorithm implementation
|
||||
return GetStringHashCode(s);
|
||||
}
|
||||
|
||||
// Need StringComparer implementation. It's very expensive to port the actual BCL code here
|
||||
// Instead use the default AppDomain, because it doesn't have string hash randomization enabled.
|
||||
// Marshal the call to reuse the default StringComparer behavior.
|
||||
// PERF isn't optimal, so apply consideration!
|
||||
internal static int GetNonRandomizedStringComparerHashCode(string s) {
|
||||
// Preserve the default behavior when string hash randomization is off
|
||||
if (!AppSettings.UseRandomizedStringHashAlgorithm) {
|
||||
return StringComparer.InvariantCultureIgnoreCase.GetHashCode(s);
|
||||
}
|
||||
|
||||
ApplicationManager appManager = HostingEnvironment.GetApplicationManager();
|
||||
if (appManager != null) {
|
||||
// Cross AppDomain call may cause marshaling of IPrincipal to fail. So strip out the exectuion context
|
||||
int hashCode = 0;
|
||||
ExecutionContextUtil.RunInNullExecutionContext(delegate {
|
||||
hashCode = appManager.GetNonRandomizedStringComparerHashCode(s, ignoreCase:true);
|
||||
});
|
||||
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
// Fall back to non-compat result
|
||||
return GetStringHashCode(s.ToLower(CultureInfo.InvariantCulture));
|
||||
}
|
||||
#endif
|
||||
internal static int GetNullTerminatedByteArray(Encoding enc, string s, out byte[] bytes)
|
||||
{
|
||||
bytes = null;
|
||||
@@ -288,7 +328,9 @@ internal static class StringUtil {
|
||||
}
|
||||
|
||||
internal unsafe static void memcpyimpl(byte* src, byte* dest, int len) {
|
||||
#if !MONO
|
||||
Debug.Assert(len >= 0, "Negative length in memcpyimpl!");
|
||||
#endif
|
||||
|
||||
#if FEATURE_PAL
|
||||
// Portable naive implementation
|
||||
@@ -382,12 +424,12 @@ internal static class StringUtil {
|
||||
}
|
||||
}
|
||||
#else
|
||||
// <STRIP>This is Peter Sollich's faster memcpy implementation, from
|
||||
// COMString.cpp. For our strings, this beat the processor's
|
||||
// repeat & move single byte instruction, which memcpy expands into.
|
||||
// (You read that correctly.)
|
||||
// This is 3x faster than a simple while loop copying byte by byte,
|
||||
// for large copies.</STRIP>
|
||||
// <
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (len >= 16) {
|
||||
do {
|
||||
#if AMD64
|
||||
|
@@ -19,10 +19,11 @@ namespace System.Web.Util {
|
||||
private Task _completionTask; // the Task that will run when all in-flight operations have completed
|
||||
private Thread _currentThread; // the Thread that's running the current Task; all threads must see the same value for this field
|
||||
private Task _lastScheduledTask = CreateInitialTask(); // the last Task that was queued to this helper, used to hook future Tasks (not volatile since always accessed under lock)
|
||||
private Task _lastScheduledTaskAsync = CreateInitialTask(); // the last async Task that was queued to this helper
|
||||
private readonly object _lockObj = new object(); // synchronizes access to _lastScheduledTask
|
||||
private int _operationsInFlight; // operation counter
|
||||
private readonly ISyncContext _syncContext; // a context that wraps an operation with pre- and post-execution phases
|
||||
private readonly Action _appVerifierCallback; // for making sure that developers don't try calling us after the request has completed
|
||||
private readonly Action<bool> _appVerifierCallback; // for making sure that developers don't try calling us after the request has completed
|
||||
|
||||
public SynchronizationHelper(ISyncContext syncContext) {
|
||||
_syncContext = syncContext;
|
||||
@@ -56,9 +57,9 @@ namespace System.Web.Util {
|
||||
return newOperationCount;
|
||||
}
|
||||
|
||||
private void CheckForRequestCompletionIfRequired() {
|
||||
private void CheckForRequestStateIfRequired(bool checkForReEntry) {
|
||||
if (_appVerifierCallback != null) {
|
||||
_appVerifierCallback();
|
||||
_appVerifierCallback(checkForReEntry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,7 +99,7 @@ namespace System.Web.Util {
|
||||
}
|
||||
|
||||
public void QueueAsynchronous(Action action) {
|
||||
CheckForRequestCompletionIfRequired();
|
||||
CheckForRequestStateIfRequired(checkForReEntry: true);
|
||||
ChangeOperationCount(+1);
|
||||
|
||||
// This method only schedules work; it doesn't itself do any work. The lock is held for a very
|
||||
@@ -109,8 +110,31 @@ namespace System.Web.Util {
|
||||
}
|
||||
}
|
||||
|
||||
// QueueAsynchronousAsync and SafeWrapCallbackAsync guarantee:
|
||||
// 1. For funcs posted here, it's would first come, first complete.
|
||||
// 2. There is no overlapping execution.
|
||||
public void QueueAsynchronousAsync(Func<object, Task> func, object state) {
|
||||
CheckForRequestStateIfRequired(checkForReEntry: true);
|
||||
ChangeOperationCount(+1);
|
||||
|
||||
// This method only schedules work; it doesn't itself do any work. The lock is held for a very
|
||||
// short period of time.
|
||||
lock (_lockObj) {
|
||||
// 1. Note that we are chaining newTask with _lastScheduledTaskAsync, not _lastScheduledTask.
|
||||
// Chaining newTask with _lastScheduledTask would cause deadlock.
|
||||
// 2. Unwrap() is necessary to be called here. When chaining multiple tasks using the ContinueWith
|
||||
// method, your return type will be Task<T> whereas T is the return type of the delegate/method
|
||||
// passed to ContinueWith. As the return type of an async delegate is a Task, you will end up with
|
||||
// a Task<Task> and end up waiting for the async delegate to return you the Task which is done after
|
||||
// the first await.
|
||||
Task newTask = _lastScheduledTaskAsync.ContinueWith(
|
||||
async _ => { await SafeWrapCallbackAsync(func, state); }).Unwrap();
|
||||
_lastScheduledTaskAsync = newTask; // the newly-created task is now the last one
|
||||
}
|
||||
}
|
||||
|
||||
public void QueueSynchronous(Action action) {
|
||||
CheckForRequestCompletionIfRequired();
|
||||
CheckForRequestStateIfRequired(checkForReEntry: false);
|
||||
if (CurrentThread == Thread.CurrentThread) {
|
||||
// current thread already owns the context, so just execute inline to prevent deadlocks
|
||||
action();
|
||||
@@ -150,6 +174,35 @@ namespace System.Web.Util {
|
||||
}
|
||||
}
|
||||
|
||||
// This method does not run the func by itself. It simply queues the func into the existing
|
||||
// syncContext queue.
|
||||
private async Task SafeWrapCallbackAsync(Func<object, Task> func, object state) {
|
||||
try {
|
||||
TaskCompletionSource<Task> tcs = new TaskCompletionSource<Task>();
|
||||
QueueAsynchronous(() => {
|
||||
var t = func(state);
|
||||
t.ContinueWith((_) => {
|
||||
if (t.IsFaulted) {
|
||||
tcs.TrySetException(t.Exception.InnerExceptions);
|
||||
}
|
||||
else if (t.IsCanceled) {
|
||||
tcs.TrySetCanceled();
|
||||
}
|
||||
else {
|
||||
tcs.TrySetResult(t);
|
||||
}
|
||||
}, TaskContinuationOptions.ExecuteSynchronously);
|
||||
});
|
||||
await tcs.Task;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Error = ExceptionDispatchInfo.Capture(ex);
|
||||
}
|
||||
finally {
|
||||
ChangeOperationCount(-1);
|
||||
}
|
||||
}
|
||||
|
||||
// Sets the continuation that will asynchronously execute when the pending operation counter
|
||||
// hits zero. Returns true if asynchronous execution is expected, false if the operation
|
||||
// counter is already at zero and the caller should run the continuation inline.
|
||||
|
68
external/referencesource/System.Web/Util/TlsTokenBindingHandle.cs
vendored
Normal file
68
external/referencesource/System.Web/Util/TlsTokenBindingHandle.cs
vendored
Normal file
@@ -0,0 +1,68 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <copyright file="TlsTokenBindingHandle.cs" company="Microsoft">
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// </copyright>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace System.Web.Util {
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Web.Hosting;
|
||||
|
||||
internal sealed class TlsTokenBindingHandle : HeapAllocHandle {
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources", Justification = @"Pointer is valid while this SafeHandle is valid.")]
|
||||
private readonly IntPtr _providedTokenBlob;
|
||||
private readonly uint _providedTokenBlobSize;
|
||||
[SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources", Justification = @"Pointer is valid while this SafeHandle is valid.")]
|
||||
private readonly IntPtr _referredTokenBlob;
|
||||
private readonly uint _referredtokenBlobSize;
|
||||
|
||||
internal TlsTokenBindingHandle(IntPtr mgdContext) {
|
||||
int hr = UnsafeIISMethods.MgdGetTlsTokenBindingIdentifiers(
|
||||
mgdContext,
|
||||
ref handle,
|
||||
out _providedTokenBlob,
|
||||
out _providedTokenBlobSize,
|
||||
out _referredTokenBlob,
|
||||
out _referredtokenBlobSize);
|
||||
Misc.ThrowIfFailedHr(hr);
|
||||
}
|
||||
|
||||
public byte[] GetProvidedToken() {
|
||||
return GetTokenImpl(_providedTokenBlob, _providedTokenBlobSize);
|
||||
}
|
||||
|
||||
public byte[] GetReferredToken() {
|
||||
return GetTokenImpl(_referredTokenBlob, _referredtokenBlobSize);
|
||||
}
|
||||
|
||||
private byte[] GetTokenImpl(IntPtr blob, uint blobSize) {
|
||||
if (blob == IntPtr.Zero || blobSize == 0) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
byte[] retVal = new byte[blobSize];
|
||||
int length = retVal.Length; // checks for overflow
|
||||
bool refAdded = false;
|
||||
|
||||
RuntimeHelpers.PrepareConstrainedRegions();
|
||||
try
|
||||
{
|
||||
DangerousAddRef(ref refAdded);
|
||||
Marshal.Copy(blob, retVal, 0, length);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (refAdded)
|
||||
{
|
||||
DangerousRelease();
|
||||
}
|
||||
}
|
||||
|
||||
return retVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -165,7 +165,7 @@ namespace System.Web.Util {
|
||||
// For example, the "//" could be missing, or there could be "///" as in "file:///C:\foo.txt"
|
||||
// To retain the same string as originally given, find the authority in the original url and include
|
||||
// everything up to that.
|
||||
int authorityIndex = inputWithoutQueryFragment.IndexOf(authority, StringComparison.Ordinal);
|
||||
int authorityIndex = inputWithoutQueryFragment.IndexOf(authority, StringComparison.OrdinalIgnoreCase);
|
||||
if (authorityIndex != -1) {
|
||||
int schemeAndAuthorityLength = authorityIndex + authority.Length;
|
||||
schemeAndAuthority = inputWithoutQueryFragment.Substring(0, schemeAndAuthorityLength);
|
||||
|
@@ -15,12 +15,15 @@ namespace System.Web.Util {
|
||||
|
||||
internal static class VersionUtil {
|
||||
|
||||
public static readonly Version Framework00 = new Version(0, 0);
|
||||
public static readonly Version Framework20 = new Version(2, 0);
|
||||
public static readonly Version Framework35 = new Version(3, 5);
|
||||
public static readonly Version Framework40 = new Version(4, 0);
|
||||
public static readonly Version Framework45 = new Version(4, 5);
|
||||
public static readonly Version Framework451 = new Version(4, 5, 1);
|
||||
public static readonly Version Framework452 = new Version(4, 5, 2);
|
||||
public static readonly Version Framework46 = new Version(4, 6);
|
||||
public static readonly Version Framework461 = new Version(4, 6, 1);
|
||||
|
||||
// Convenience accessor for the "default" framework version; various configuration
|
||||
// switches can use this as a default value. This value must only be bumped during
|
||||
|
@@ -79,7 +79,12 @@ namespace System.Web.Util {
|
||||
|
||||
internal static string SystemWebVersion {
|
||||
get {
|
||||
return ThisAssembly.InformationalVersion;
|
||||
|
||||
// Previously this represented the File version of mscorlib.dll. Many other libraries in the framework and outside took dependencies on the first three parts of this version
|
||||
// remaining constant throughout 4.x. From 4.0 to 4.5.2 this was fine since the file version only incremented the last part. Starting with 4.6 we switched to a file versioning
|
||||
// scheme that matched the product version. In order to preserve compatibility with existing libraries, this needs to be hard-coded.
|
||||
|
||||
return "4.0.30319.42000";
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user