При автоматизации проверок безопасности подсистем 1С часто возникает задача: убедиться, что все запросы либо используют конструкцию РАЗРЕШЕННЫЕ, либо выполняются в привилегированном режиме. Попытки решить эту задачу с помощью регулярных выражений (RegExp) часто приводят к трудностям из-за сложности синтаксиса языка запросов. Давайте разберем, почему этот путь может быть ошибочным и как правильно подойти к задаче.
Первая проблема — вы пытаетесь решить задачу с помощью регулярных выражений. Вторая проблема — у вас уже две проблемы. В контексте анализа запросов 1С это высказывание актуально как никогда по нескольким причинам:
VBScript.RegExp, используемый в 1С, не поддерживает полноценные «lookbehind» (просмотр назад), что затрудняет проверку условий типа «выбрать, если перед этим нет того-то».ВЫБРАТЬ, может ошибочно принять его за часть текстовой строки или комментария.ВЫБРАТЬ (например, ПЕРВЫЕ, РАЗЛИЧНЫЕ, РАЗРЕШЕННЫЕ) может быть произвольным, что делает паттерн поиска крайне громоздким и ненадежным.Вместо того чтобы вручную «парсить» текст регулярками, воспользуемся штатным инструментом платформы — СхемаЗапроса. Этот объект специально создан для разбора структуры запроса. Он понимает пакетные запросы, объединения и вложенные подзапросы, автоматически игнорируя комментарии и строковые литералы.
Рассмотрим, как реализовать этот подход по шагам:
ВЫБРАТЬ.СхемаЗапроса.СхемаЗапроса имеет свойство Разрешенные (булево), которое прямо указывает на наличие конструкции РАЗРЕШЕННЫЕ в запросе.Пример программного разбора:
// Предположим, у нас есть строка с текстом запроса
ТекстЗапроса = "ВЫБРАТЬ РАЗРЕШЕННЫЕ Ссылка ИЗ Справочник.Номенклатура";
Схема = Новый СхемаЗапроса;
Схема.УстановитьТекстЗапроса(ТекстЗапроса);
// Проверяем наличие РАЗРЕШЕННЫЕ
Если Не Схема.Разрешенные Тогда
// Запрос не содержит РАЗРЕШЕННЫЕ, нужно проверить наличие привилегированного режима
Сообщить("Нарушение безопасности: запрос без РАЗРЕШЕННЫЕ");
КонецЕсли;
Многие программисты опасаются, что СхемаЗапроса работает слишком медленно для обработки всей конфигурации. Однако на практике общее время анализа даже большой конфигурации увеличивается на считанные секунды, что вполне допустимо для автоматических тестов или инструментов статического анализа.
Чтобы ускорить процесс, мы рекомендуем использовать двухуровневый подход:
ВЫБРАТЬ в файле модуля. Если слова нет, модуль пропускается.СхемаЗапроса только к тем фрагментам текста, которые прошли первичную проверку.Если вам нужно выводить пользователю номер строки, в которой найдено нарушение, не обязательно усложнять алгоритм. Можно воспользоваться простой функцией для расчета:
Позиция = Найти(ТекстМодуля, "ВЫБРАТЬ");
НомерСтроки = СтрЧислоСтрок(Лев(ТекстМодуля, Позиция));
Важно помнить:
Если ваш тест выдает ошибку, но вы уверены в безопасности запроса (например, он исполняется в процедуре с установленным привилегированным режимом), используйте специальные комментарии-теги (например, // @ignore:AccessCheck) для игнорирования таких участков кода. Это позволит избежать ложных срабатываний и поддерживать тест в чистоте.
В заключение, использование специализированных объектов платформы — это профессиональный подход. Не пытайтесь изобрести собственный парсер языка запросов на регулярных выражениях, так как СхемаЗапроса дает гораздо более надежный и предсказуемый результат при минимальных затратах времени на разработку.