Как получить содержащееся пространство имен вызываемого метода с помощью Roslyn, если этот метод не имеет информации о символах?

У меня есть приложение, которое позволяет пользователям писать код c-sharp, который сохраняется как библиотека классов для последующего вызова.

Было установлено новое требование, согласно которому некоторые пространства имен (и методы, которые они содержат, а также любые переменные или методы с их типами возврата) больше не разрешены. Поэтому мне нужно проанализировать код и предупредить пользователя о любых запрещенных пространствах имен в их коде, чтобы они могли их удалить.

Используя Roslyn, я могу получить доступ к InvocationExpressionSyntax узлам для вызовов методов. Затем я получаю информацию о символе, вызывая var mySymbol = mySemanticModel.GetSymbolInfo(myInvocationExpressionSyntaxNode).Symbol.

Затем вызов mySymbol.ContainingType.ToDisplayString() возвращает тип пространства имен вызова.

Однако не все вызываемые методы имеют символьную информацию в Roslyn. Например, System.Math.Sqrt() имеет символьную информацию, поэтому я могу получить содержащее пространство имен System.Math. С другой стороны, System.Net.WebRequest.Create() или System.Diagnostics.Process.Start() нет. Как мне получить System.Net.WebRequest или System.Dignostics.Process с этих узлов? Я ясно вижу их с помощью QuickWatch.

Например, сам узел System.Diagnostics.Process.Start() в QuickWatch показывает следующее значение: InvocationExpressionSyntax InvocationExpression System.Diagnostics.Process.Start("CMD.exe","")

И выражение узла имеет это значение: MemberAccessExpressionSyntax SimpleMemberAccessExpression System.Diagnostics.Process.Start

Очевидно, что пространство имен присутствует в самом значении. Но оба символа из SymbolInfo и Type из TypeInfo равны нулю.

Изменить

Что касается моей компиляции, инструменты C # Roslyn настроены следующим образом (предполагается, что мы также поддерживаем VB, поэтому свойства связаны):

       private class CSharpRoslynTools : IRoslynTools
        {
            public CompilationUnitSyntax SyntaxTreeRoot { get; }
            public SemanticModel SemanticModel { get; }

            public CSharpRoslynTools(string code)
            {
                var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
                var syntaxTree = CSharpSyntaxTree.ParseText(code);
                var compilation = CSharpCompilation.Create(
                    "MyCompilation",
                    syntaxTrees: new[] { syntaxTree },
                    references: new[]
                    {
                        mscorlib
                    });
                this.SemanticModel = compilation.GetSemanticModel(syntaxTree);
                this.SyntaxTreeRoot = (CompilationUnitSyntax)syntaxTree.GetRoot();
            }
        }

Одна вещь, которую я действительно понял, это то, что System Diagnostics не является частью mscorlib. Может быть, поэтому отсутствует символьная информация?

Честно говоря, я считаю это пустой тратой времени, потому что сценарии были разработаны для запуска в настольном приложении WinForms, которому на данный момент уже 15 лет. Но затем они решили, что это настольное приложение необходимо перенести в Citrix Cloud для определенных клиентов. И в результате мы должны заблокировать все, что может получить доступ к файловой системе, если это не администратор, вошедший в приложение. Таким образом, у нас есть гигантская потенциальная дыра в безопасности с этими скриптами. Однако шанс того, что кто-то получит доступ к приложению и воспользуется любым из этого, невелик.

Я настаивал на создании черного списка, что было бы достаточно легко сделать с помощью простого строкового поиска кода. Им нужен белый список, который требует полного анализа символов.


person GrantA    schedule 07.05.2021    source источник


Ответы (1)


Однако не все вызываемые методы имеют символьную информацию в Roslyn.

Это, вероятно, указывает на то, что что-то пошло не так с тем, как вы получили свою компиляцию, и вам следует попытаться исследовать это напрямую. Не пытайтесь справиться с этим ниже по течению. (Программное обеспечение: мусор на входе, мусор на выходе!)

С другой стороны, System.Net.WebRequest.Create () или System.Diagnostics.Process.Start () - нет. Как мне получить System.Net.WebRequest или System.Dignostics.Process с этих узлов? Я ясно вижу их с помощью QuickWatch.

Имейте в виду, что с точки зрения только синтаксиса System.Net.WebRequest.Create () может быть:

  • Метод Create для типа WebRequest, который находится в System.Net
  • Метод Create для типа WebRequest, который является вложенным классом типа Net, в пространстве имен System.
  • Метод Create для типа WebRequest, который находится в MyApp.System.Net.WebRequest, потому что нам, конечно, не требуются полные имена пространств имен, и если вы решите создать пространство имен System внутри своего MyApp, это потенциально может сработать!

Одна вещь, которую я действительно понял, это то, что System Diagnostics не является частью mscorlib. Может быть, поэтому отсутствует символьная информация?

Ага; мы будем ссылаться только на сборки, которые вы нам даете. Вы должны знать свой контекст, и если другие ссылки включены в то, на что может ссылаться этот код, то вы должны включить их в свое производство компиляции.

Я настаивал на создании черного списка, что было бы достаточно легко сделать с помощью простого строкового поиска кода. Им нужен белый список, который требует полного анализа символов.

С точки зрения безопасности они могут быть правы - очень сложно заблокировать поиск по строке. См. Некоторые мысли на странице https://stackoverflow.com/a/66555319/972216 о том, насколько это сложно.

person Jason Malinowski    schedule 07.05.2021
comment
Я обновил вопрос, чтобы показать, как я создаю компилятор. - person GrantA; 08.05.2021
comment
Обновлено с дополнительной информацией. - person Jason Malinowski; 11.05.2021