надежно загружать свободный чертеж XAML - PullRequest
0 голосов
/ 29 апреля 2020
Приложение

A C# Windows хотело бы загружать векторные рисунки, которые хранятся в свободных файлах XAML, без разрешения произвольного выполнения кода.

Я уже загружаю такие рисунки из ресурсов в связанных сборках, над которыми я иметь контроль. Тем не менее, я хотел бы также поддерживать загрузку свободных файлов XAML. Я полагаю, вы можете использовать контроль доступа XAML, чтобы ограничить объекты, которые могут быть созданы в таком XAML? В идеале я бы ограничил загрузчик созданием только тех примитивов рисования, которые находятся в файлах, о которых мы знаем. Это нормально, что он отклонил бы файл с новыми примитивами рисования, которые мы не включили в белый список.

Это стандартная вещь, уже поддерживаемая API? Потому что я не смог его найти. Иначе у кого-нибудь есть пример или начало примера? Это для бесплатного проекта с открытым исходным кодом, и любая помощь в начале работы, вероятно, значительно сократила бы исследования, которые мне нужно сделать.

1 Ответ

0 голосов
/ 30 апреля 2020

Следующее, кажется, делает довольно приличную работу с указанием белых списков c типов в нагрузке XAML:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Windows.Controls;
using System.Windows.Media;
using System.Xaml;
using System.Xml;

namespace TestXamlLoading
{
    internal class SchemaContext : XamlSchemaContext
    {
        // map from XAML element name to required namespace (currently always the same)
        private static readonly Dictionary<string, string> AllowedTypes = new Dictionary<string, string>();

        static SchemaContext()
        {
            // questionable: <Image> is used in some drawing XAML, should review it
            foreach (string name in new[]
            {
                "Canvas", "Compound", "Ellipse", "GradientStop", "GradientStopCollection", "Group", "Line",
                "LinearGradientBrush", "MatrixTransform", "Path", "PathGeometry", "Polygon",
                "RadialGradientBrush", "Rectangle", "RotateTransform", "ScaleTransform", "SkewTransform", "TextBlock",
                "TransformGroup", "TranslateTransform"
            })
            {
                AllowedTypes[name] = "http://schemas.microsoft.com/winfx/2006/xaml/presentation";
            }
        }

        public SchemaContext(IEnumerable<Assembly> referenceAssemblies, XamlSchemaContextSettings settings) : base(
            referenceAssemblies, settings)
        {
            // no code
        }

        protected override XamlType GetXamlType(string xamlNamespace, string name, params XamlType[] typeArguments)
        {
            if (!AllowedTypes.TryGetValue(name, out string requiredNamespace) || xamlNamespace != requiredNamespace)
            {
                throw new Exception($"disallowed instantiation of '{xamlNamespace}' '{name}' from XAML");
            }

            return base.GetXamlType(xamlNamespace, name, typeArguments);
        }
    }

    internal class Program
    {
        [STAThreadAttribute]
        private static void Main(string[] args)
        {
            bool shouldFail = TestLoad("..\\..\\..\\badfile.xaml");
            Debug.Assert(!shouldFail);
            bool shouldSucceed = TestLoad("..\\..\\..\\goodfile.xaml");
            Debug.Assert(shouldSucceed);
        }

        private static bool TestLoad(string path)
        {
            Stream inputStream = new FileStream(path, FileMode.Open);
            XmlReader xmlReader = new XmlTextReader(inputStream);
            Assembly[] referenceAssemblies =
            {
                // these are two separate assemblies which contain all the types we allow
                Assembly.GetAssembly(typeof(Canvas)),
                Assembly.GetAssembly(typeof(TransformGroup))
            };
            XamlSchemaContextSettings settings = new XamlSchemaContextSettings();
            XamlSchemaContext schemaContext = new SchemaContext(referenceAssemblies, settings);
            try
            {
                XamlReader reader = new XamlXmlReader(xmlReader, schemaContext);
                Canvas canvas = (Canvas) System.Windows.Markup.XamlReader.Load(reader);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
                return false;
            }

            return true;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...