File: System\Xaml\MS\Impl\XamlAppContextSwitches.cs
Web Access
Project: src\wpf\src\Microsoft.DotNet.Wpf\src\System.Xaml\System.Xaml.csproj (System.Xaml)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
#nullable disable
 
using System;
 
namespace System.Xaml.MS.Impl
{
    /// <summary>
    /// AppContext switches for the System.Xaml assembly.
    ///
    /// System.Xaml does not have LocalAppContext / LocalAppContext.GetCachedSwitchValue
    /// infrastructure (those live in PresentationCore and above), so this class reads
    /// switches directly via <see cref="AppContext.TryGetSwitch"/>.
    ///
    /// The cache fields are written without synchronization; this is benign because
    /// both racing threads compute the same deterministic value and int writes are
    /// atomic on all .NET platforms.
    /// </summary>
    internal static class XamlAppContextSwitches
    {
        #region DisableMarkupExtensionDepthGuard
 
        /// <summary>
        /// Switch: Switch.System.Xaml.DisableMarkupExtensionDepthGuard
        ///   Default (false): The markup-extension nesting depth cap is enforced,
        ///                    preventing stack overflow from deeply nested {Binding ...}
        ///                    constructs in attacker-supplied XAML (CWE-674 / CWE-770).
        ///   Set to true:     The depth cap is skipped, restoring previous behavior.
        /// </summary>
        internal const string DisableMarkupExtensionDepthGuardSwitchName =
            "Switch.System.Xaml.DisableMarkupExtensionDepthGuard";
 
        private static int _disableMarkupExtensionDepthGuard; // 0 = not read, 1 = true, -1 = false
 
        internal static bool DisableMarkupExtensionDepthGuard
        {
            get
            {
                if (_disableMarkupExtensionDepthGuard == 0)
                {
                    bool switchValue = false;
                    try
                    {
                        AppContext.TryGetSwitch(DisableMarkupExtensionDepthGuardSwitchName, out switchValue);
                    }
                    catch (Exception)
                    {
                        // If AppContext is not available, default to the protected behavior.
                    }
 
                    _disableMarkupExtensionDepthGuard = switchValue ? 1 : -1;
                }
 
                return _disableMarkupExtensionDepthGuard > 0;
            }
        }
 
        #endregion
    }
}