diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fd6f885..3e82a0b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,6 @@ #### Код модулей - - 3 проверки на избыточное обращение внутри модуля через его имя или псевдоним ЭтотОбъект (к методу, свойству или реквизиту) - Проверка использования устаревшего "ЭтаФорма" в модуле формы - Проверка нарушения схемы работы с транзакциями связанной с фиксацией транзакции: @@ -46,6 +45,8 @@ 1. Mежду "НачатьТранзакцию()" и "Попытка" есть исполняемый код, который может вызвать исключение 2. Не найден оператор "Попытка" после вызова "НачатьТранзакцию()" - Отсутствует удаление временного файла после использования. +- Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить" + #### Запросы - В качестве правого операнда операции сравнения "ПОДОБНО" указано поле таблицы @@ -56,7 +57,6 @@ ### Новые быстрые исправления (Quick-fix) - - 3 исправления исправления для удаления избыточного обращения внутри модуля к самому себе - Замена в модуле формы устаревшего свойства "ЭтаФорма" на "ЭтотОбъект" - Конвертация функции в процедуру diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml index 6250fff5..9f0c599b 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl.ui/plugin.xml @@ -364,6 +364,9 @@ + + diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java index b562846e..e70d0f9e 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/Messages.java @@ -48,6 +48,10 @@ final class Messages public static String SelfReferenceFix_details; + public static String ServerExecutionSafeModeFix_description; + + public static String ServerExecutionSafeModeFix_details; + public static String UndefinedMethodFix_func_title; public static String UndefinedMethodFix_func_desc; public static String UndefinedMethodFix_proc_title; diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/ServerExecutionSafeModeFix.java b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/ServerExecutionSafeModeFix.java new file mode 100644 index 00000000..3dabc420 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/ServerExecutionSafeModeFix.java @@ -0,0 +1,76 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.ui.qfix; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.text.edits.InsertEdit; +import org.eclipse.text.edits.TextEdit; +import org.eclipse.xtext.EcoreUtil2; +import org.eclipse.xtext.nodemodel.INode; +import org.eclipse.xtext.nodemodel.util.NodeModelUtils; +import org.eclipse.xtext.resource.XtextResource; + +import com._1c.g5.v8.dt.bsl.model.ExecuteStatement; +import com._1c.g5.v8.dt.bsl.model.Statement; +import com._1c.g5.v8.dt.bsl.model.StaticFeatureAccess; +import com._1c.g5.v8.dt.common.StringUtils; +import com._1c.g5.v8.dt.metadata.mdclass.ScriptVariant; +import com.e1c.g5.v8.dt.bsl.check.qfix.IXtextBslModuleFixModel; +import com.e1c.g5.v8.dt.bsl.check.qfix.IXtextInteractiveBslModuleFixModel; +import com.e1c.g5.v8.dt.bsl.check.qfix.SingleVariantXtextBslModuleFix; +import com.e1c.g5.v8.dt.check.qfix.components.QuickFix; + +/** + * Quick fix for check com.e1c.v8codestyle.bsl.check:server-execution-safe-mode + * + * @author Maxim Galios + * + */ +@QuickFix(checkId = "server-execution-safe-mode", supplierId = "com.e1c.v8codestyle.bsl") +public class ServerExecutionSafeModeFix + extends SingleVariantXtextBslModuleFix +{ + private static final String SAFE_MODE_INVOCATION = "SetSafeMode(True);"; //$NON-NLS-1$ + private static final String SAFE_MODE_INVOCATION_RU = "УстановитьБезопасныйРежим(Истина);"; //$NON-NLS-1$ + + @Override + protected void configureFix(FixConfigurer configurer) + { + configurer.interactive(true) + .description(Messages.ServerExecutionSafeModeFix_description) + .details(Messages.ServerExecutionSafeModeFix_details); + } + + @Override + protected TextEdit fixIssue(XtextResource state, IXtextBslModuleFixModel model) throws BadLocationException + { + EObject element = model.getElement(); + if (!(element instanceof StaticFeatureAccess) && !(element instanceof ExecuteStatement)) + { + return null; + } + + String safeModeStatement = + model.getScriptVariant() == ScriptVariant.RUSSIAN ? SAFE_MODE_INVOCATION_RU : SAFE_MODE_INVOCATION; + + INode node = NodeModelUtils.findActualNodeFor( + element instanceof StaticFeatureAccess ? EcoreUtil2.getContainerOfType(element, Statement.class) : element); + + IXtextInteractiveBslModuleFixModel interactiveModel = (IXtextInteractiveBslModuleFixModel)model; + String indent = interactiveModel.getFormatString(element).orElse(StringUtils.EMPTY); + + String codeToInsert = safeModeStatement + model.getLineSeparator() + indent; + return new InsertEdit(node.getOffset(), codeToInsert); + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties index d27324ef..fc779b05 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages.properties @@ -25,6 +25,8 @@ OpenBslDocCommentViewFix_Details=Open documentation comment data structure view OpenBslDocCommentViewFix_Description=Open documentation comment structure view SelfReferenceFix_description=Remove excessive self reference SelfReferenceFix_details=Remove excessive self reference +ServerExecutionSafeModeFix_description = Enable safe mode +ServerExecutionSafeModeFix_details = Insert safe mode enable statement before "Execute" or "Eval" method call UndefinedMethodFix_func_title=Create function UndefinedMethodFix_func_desc=Create a new function in the module UndefinedMethodFix_proc_title=Create procedure diff --git a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties index 76bee16b..dff861b3 100644 --- a/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl.ui/src/com/e1c/v8codestyle/bsl/ui/qfix/messages_ru.properties @@ -33,6 +33,10 @@ SelfReferenceFix_description=Удалить избыточное обращен SelfReferenceFix_details=Удалить избыточное обращение внутри модуля через псевдоним "ЭтотОбъект" +ServerExecutionSafeModeFix_description = Включить безопасный режим + +ServerExecutionSafeModeFix_details = Добавить включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить" + UndefinedMethodFix_func_desc = Создать новую функцию в модуле UndefinedMethodFix_func_title = Создать функцию diff --git a/bundles/com.e1c.v8codestyle.bsl/markdown/ru/server-execution-safe-mode.md b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/server-execution-safe-mode.md new file mode 100644 index 00000000..a891ea33 --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/markdown/ru/server-execution-safe-mode.md @@ -0,0 +1,92 @@ +# Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить" + +Для исключения описанных уязвимостей, нужно в серверных процедурах и +функциях вызов методов Выполнить или Вычислить предварять включением безопасного режима. + +В режиме сервиса, включение безопасного режима должно учитывать разделение данных. + +## Неправильно + +```bsl +Выполнить(Алгоритм); +``` + +```bsl +Вычислить(Алгоритм); +``` + +## Правильно + +```bsl +УстановитьБезопасныйРежим(Истина); +Выполнить(Алгоритм); +``` + +```bsl +УстановитьБезопасныйРежим(Истина); +Вычислить(Алгоритм); +``` + +В режиме сервиса: + +```bsl +УстановитьБезопасныйРежим(Истина); + +Для каждого ИмяРазделителя Из РазделителиКонфигурации() Цикл + УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина); +КонецЦикла; + +Выполнить(Алгоритм); +``` + +```bsl +УстановитьБезопасныйРежим(Истина); + +Для каждого ИмяРазделителя Из РазделителиКонфигурации() Цикл + УстановитьБезопасныйРежимРазделенияДанных(ИмяРазделителя, Истина); +КонецЦикла; + +Вычислить(Алгоритм); +``` + +При использовании в конфигурации Библиотеки стандартных подсистем, следует использовать: + +```bsl +ОбщегоНазначения.ВыполнитьВБезопасномРежиме() +``` + +```bsl +ОбщегоНазначения.ВычислитьВБезопасномРежиме() +``` + +Вместо формирования строки вызова метода модуля и передачи ее в Выполнить: +```bsl +ОбщегоНазначения.ВыполнитьМетодКонфигурации() +``` + +```bsl +ОбщегоНазначения.ВыполнитьМетодОбъекта() +``` + +При использовании в конфигурации Библиотеки стандартных подсистем версии, меньшей чем 2.4.1, следует использовать: + + +```bsl +РаботаВБезопасномРежиме.ВыполнитьВБезопасномРежиме() +``` + +```bsl +РаботаВБезопасномРежиме.ВычислитьВБезопасномРежиме() +``` + +Вместо формирования строки вызова метода модуля и передачи ее в Выполнить: +```bsl +РаботаВБезопасномРежиме.ВыполнитьМетодКонфигурации() +``` + +```bsl +РаботаВБезопасномРежиме.ВыполнитьМетодОбъекта() +``` + +## См. +[Ограничения на использование Выполнить и Вычислить на сервере](https://its.1c.ru/db/v8std#content:770:hdoc:2) diff --git a/bundles/com.e1c.v8codestyle.bsl/markdown/server-execution-safe-mode.md b/bundles/com.e1c.v8codestyle.bsl/markdown/server-execution-safe-mode.md new file mode 100644 index 00000000..9113367e --- /dev/null +++ b/bundles/com.e1c.v8codestyle.bsl/markdown/server-execution-safe-mode.md @@ -0,0 +1,93 @@ +# Safe mode is not enabled before "Execute" or "Eval" call + +To avoid vulnerabilities, in server procedures and functions, +enable safe mode before calling the Execute or Eval methods. + +In service mode, data separation is to be considered upon +enabling safe mode. + +## Noncompliant Code Example + +```bsl +Execute(Algorithm); +``` + +```bsl +Eval(Algorithm); +``` + +## Compliant Solution + +```bsl +SetSafeMode(True); +Execute(Algorithm); +``` + +```bsl +SetSafeMode(True); +Eval(Algorithm); +``` + +In service mode: + +```bsl +SetSafeMode(True); + +For each SeparatorName in ConfigurationSeparators() Do + SetDataSeparationSafeMode(SeparatorName, True); +EndDo; + +Execute Algorithm; +``` + +```bsl +SetSafeMode(True); + +For each SeparatorName in ConfigurationSeparators() Do + SetDataSeparationSafeMode(SeparatorName, True); +EndDo; + +Eval(Algorithm); +``` + +If the Standard Subsystems Library is used in the configuration, use the following: + +```bsl +Common.ExecuteInSafeMode() +``` + +```bsl +Common.CalculateInSafeMode() +``` + +Instead of generating a string calling the module method and passing it to Execute: +```bsl +Common.ExecuteConfigurationMethod() +``` + +```bsl +Common.ExecuteObjectMethod() +``` + +If the Standard Subsystems Library version is earlier than 2.4.1, use the following: + + +```bsl +SafeModeManager.ExecuteInSafeMode() +``` + +```bsl +SafeModeManager.CalculateInSafeMode() +``` + +Instead of generating a string calling the module method and passing it to Execute: +```bsl +SafeModeManager.ExecuteConfigurationMethod() +``` + +```bsl +SafeModeManager.ExecuteObjectMethod() +``` + +## See +[Restrictions on the use of Run and Eval on the server](https://support.1ci.com/hc/en-us/articles/360011122479-Restrictions-on-the-use-of-Run-and-Eval-on-the-server) diff --git a/bundles/com.e1c.v8codestyle.bsl/plugin.xml b/bundles/com.e1c.v8codestyle.bsl/plugin.xml index e701d211..98a82f0a 100644 --- a/bundles/com.e1c.v8codestyle.bsl/plugin.xml +++ b/bundles/com.e1c.v8codestyle.bsl/plugin.xml @@ -258,6 +258,10 @@ + + EVAL = Set.of("Eval", "Вычислить"); //$NON-NLS-1$ //$NON-NLS-2$ + private static final Collection SAFE_MODE_INVOCATIONS = Set.of("УстановитьБезопасныйРежим", "SetSafeMode"); //$NON-NLS-1$ //$NON-NLS-2$ + + @Override + public String getCheckId() + { + return CHECK_ID; + } + + @Override + protected void configureCheck(CheckConfigurer builder) + { + builder.title(Messages.ServerExecutionSafeModeCheck_title) + .description(Messages.ServerExecutionSafeModeCheck_description) + .complexity(CheckComplexity.NORMAL) + .severity(IssueSeverity.MAJOR) + .issueType(IssueType.SECURITY) + .extension(new StandardCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID)) + .module() + .checkedObjectType(INVOCATION) + .checkedObjectType(EXECUTE_STATEMENT); + } + + @Override + protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters, + IProgressMonitor monitor) + { + EObject eObject = (EObject)object; + if (!isServerCall(eObject) || (!isExecute(eObject) && !isEval(eObject))) + { + return; + } + + if (!isSafeModeEnabledBeforeExecution(eObject, monitor)) + { + if (isExecute(eObject)) + { + resultAceptor.addIssue(Messages.ServerExecutionSafeModeCheck_execute_issue, eObject); + } + else if (isEval(eObject)) + { + resultAceptor.addIssue(Messages.ServerExecutionSafeModeCheck_eval_issue, + ((Invocation)eObject).getMethodAccess()); + } + } + } + + private boolean isServerCall(EObject eObject) + { + Environmental environmental = EcoreUtil2.getContainerOfType(eObject, Environmental.class); + Environments environments = environmental.environments(); + return environments.contains(Environment.SERVER); + } + + private boolean isSafeModeEnabledBeforeExecution(EObject eObject, IProgressMonitor monitor) + { + EObject container = eObject.eContainer(); + + while (container != null) + { + if (monitor.isCanceled()) + { + return true; + } + Optional isSafeModeEnabledForContainer = isSafeModeEnabledForContainer(container, eObject); + if (isSafeModeEnabledForContainer.isPresent()) + { + return isSafeModeEnabledForContainer.get(); + } + container = container.eContainer(); + } + return false; + } + + private Optional isSafeModeEnabledForContainer(EObject container, EObject eObject) + { + if (container instanceof IfStatement) + { + return isSafeModeEnabledForIfStatement((IfStatement)container, eObject); + } + else if (container instanceof LoopStatement) + { + return isSafeModeEnabledForLoopStatement((LoopStatement)container, eObject); + } + else if (container instanceof TryExceptStatement) + { + return isSafeModeEnabledForTryExceptStatement((TryExceptStatement)container, eObject); + } + else if (container instanceof Block) + { + return isSafeModeEnabledForBlock((Block)container, eObject); + } + + return Optional.empty(); + } + + private Optional isSafeModeEnabledForIfStatement(IfStatement ifStatement, EObject eObject) + { + List ifStatements = ifStatement.getIfPart().getStatements(); + Optional ifStatementSafeModeEnabled = isSafeModeEnabledInStatementList(ifStatements, eObject); + + if (ifStatementSafeModeEnabled.isPresent()) + { + return ifStatementSafeModeEnabled; + } + + List elseIfParts = ifStatement.getElsIfParts(); + for (Conditional part : elseIfParts) + { + List elseIfStatements = part.getStatements(); + Optional elseIfStatementSafeModeEnabled = + isSafeModeEnabledInStatementList(elseIfStatements, eObject); + + if (elseIfStatementSafeModeEnabled.isPresent()) + { + return elseIfStatementSafeModeEnabled; + } + } + + List elseStatements = ifStatement.getElseStatements(); + return isSafeModeEnabledInStatementList(elseStatements, eObject); + } + + private Optional isSafeModeEnabledForLoopStatement(LoopStatement loopStatement, EObject eObject) + { + List loopStatements = loopStatement.getStatements(); + return isSafeModeEnabledInStatementList(loopStatements, eObject); + } + + private Optional isSafeModeEnabledForTryExceptStatement(TryExceptStatement tryExceptStatement, + EObject eObject) + { + List tryStatements = tryExceptStatement.getTryStatements(); + Optional tryStatementSafeModeEnabled = isSafeModeEnabledInStatementList(tryStatements, eObject); + + if (tryStatementSafeModeEnabled.isPresent()) + { + return tryStatementSafeModeEnabled; + } + + List exceptStatements = tryExceptStatement.getExceptStatements(); + return isSafeModeEnabledInStatementList(exceptStatements, eObject); + } + + private Optional isSafeModeEnabledForBlock(Block block, EObject eObject) + { + List statements = block.allStatements(); + return isSafeModeEnabledInStatementList(statements, eObject); + } + + private Optional isSafeModeEnabledInStatementList(List statements, EObject eObject) + { + int executeIndex = findExecuteStatementIndex(statements, eObject); + if (executeIndex == -1) + { + return Optional.empty(); + } + + for (int i = executeIndex - 1; i >= 0; i--) + { + Statement statement = statements.get(i); + Optional safeModeEnabled = isSafeModeEnabled(statement); + if (safeModeEnabled.isPresent()) + { + return safeModeEnabled; + } + } + return Optional.empty(); + } + + private Optional isSafeModeEnabled(Statement statement) + { + if (statement instanceof SimpleStatement && isSafeModeMethod(statement)) + { + return Optional.of(isSafeModeEnabledStatement(statement)); + } + else if (statement instanceof IfStatement) + { + List> safeModeStatementResults = new ArrayList<>(); + IfStatement ifStatement = (IfStatement)statement; + + List ifStatements = ifStatement.getIfPart().getStatements(); + safeModeStatementResults.add(safeModeStatementResult(ifStatements)); + + List elseIfParts = ifStatement.getElsIfParts(); + for (Conditional part : elseIfParts) + { + List elseIfStatements = part.getStatements(); + safeModeStatementResults.add(safeModeStatementResult(elseIfStatements)); + } + + List elseStatements = ifStatement.getElseStatements(); + safeModeStatementResults.add(safeModeStatementResult(elseStatements)); + + return validateSafeModeStatements(safeModeStatementResults); + } + else if (statement instanceof LoopStatement) + { + LoopStatement loopStatement = (LoopStatement)statement; + List loopStatements = loopStatement.getStatements(); + return safeModeStatementResult(loopStatements); + } + else if (statement instanceof TryExceptStatement) + { + List> safeModeStatementResults = new ArrayList<>(); + TryExceptStatement tryExceptStatement = (TryExceptStatement)statement; + List tryStatements = tryExceptStatement.getTryStatements(); + safeModeStatementResults.add(safeModeStatementResult(tryStatements)); + + List exceptStatements = tryExceptStatement.getExceptStatements(); + safeModeStatementResults.add(safeModeStatementResult(exceptStatements)); + + return validateSafeModeStatements(safeModeStatementResults); + } + return Optional.empty(); + } + + private Optional safeModeStatementResult(List statements) + { + for (int i = statements.size() - 1; i >= 0; i--) + { + Statement statement = statements.get(i); + Optional res = isSafeModeEnabled(statement); + if (res.isPresent()) + { + return res; + } + } + return Optional.empty(); + } + + private Optional validateSafeModeStatements(List> safeModeStatements) + { + if (safeModeStatements.stream().allMatch(Optional::isEmpty)) + { + return Optional.empty(); + } + if (safeModeStatements.stream().filter(Optional::isPresent).anyMatch(s -> !s.get())) + { + return Optional.of(false); + } + if (safeModeStatements.stream().allMatch(s -> s.isPresent() && s.get())) + { + return Optional.of(true); + } + return Optional.empty(); + } + + private boolean isSafeModeMethod(Statement statement) + { + if (!(statement instanceof SimpleStatement)) + { + return false; + } + + SimpleStatement simpleStatement = (SimpleStatement)statement; + Expression leftExpression = simpleStatement.getLeft(); + if (!(leftExpression instanceof Invocation)) + { + return false; + } + + Invocation invocation = (Invocation)leftExpression; + String name = invocation.getMethodAccess().getName(); + List params = invocation.getParams(); + + return SAFE_MODE_INVOCATIONS.stream().anyMatch(st -> st.equalsIgnoreCase(name)) && params.size() == 1 + && params.get(0) instanceof BooleanLiteral; + } + + private int findExecuteStatementIndex(List statements, EObject eObject) + { + if (eObject instanceof ExecuteStatement) + { + int index = statements.indexOf(eObject); + if (index != -1) + { + return index; + } + } + + Statement statement = EcoreUtil2.getContainerOfType(eObject, Statement.class); + + while (statement != null) + { + int statementIndex = statements.indexOf(statement); + if (statementIndex != -1) + { + return statementIndex; + } + statement = EcoreUtil2.getContainerOfType(statement.eContainer(), Statement.class); + } + + return -1; + } + + private boolean isSafeModeEnabledStatement(Statement statement) + { + if (statement == null) + { + return false; + } + SimpleStatement simpleStatement = (SimpleStatement)statement; + Invocation invocation = (Invocation)simpleStatement.getLeft(); + + List params = invocation.getParams(); + return ((BooleanLiteral)params.get(0)).isIsTrue(); + } + + private boolean isExecute(EObject eObject) + { + return eObject instanceof ExecuteStatement; + } + + private boolean isEval(EObject eObject) + { + return eObject instanceof Invocation && EVAL.stream() + .anyMatch(statement -> statement.equalsIgnoreCase(((Invocation)eObject).getMethodAccess().getName())); + } +} diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties index 7c8e19f9..0d46e2f5 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages.properties @@ -273,6 +273,14 @@ SelfReferenceCheck_Title=Excessive self reference SelfReferenceCheck_Issue=Excessive usage of self reference (when referencing method, property or attribute) +ServerExecutionSafeModeCheck_description = Safe mode is not enabled when calling "Execute" or "Eval' + +ServerExecutionSafeModeCheck_eval_issue = Safe mode is not enabled when calling "Eval" + +ServerExecutionSafeModeCheck_execute_issue = Safe mode is not enabled when calling "Execute" + +ServerExecutionSafeModeCheck_title = Safe mode is not enabled when calling "Execute" or "Eval" + StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Maximum structure constructor keys StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Structure constructor has more than {0} keys diff --git a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties index ccacac0a..a5232c87 100644 --- a/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties +++ b/bundles/com.e1c.v8codestyle.bsl/src/com/e1c/v8codestyle/bsl/check/messages_ru.properties @@ -278,6 +278,14 @@ SelfReferenceCheck_Title=Избыточное использование псе SelfReferenceCheck_Issue=Избыточное обращение внутри модуля через псевдоним "ЭтотОбъект" (к методу, свойству или реквизиту) +ServerExecutionSafeModeCheck_description = Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить" + +ServerExecutionSafeModeCheck_eval_issue = Отсутствует включение безопасного режима перед вызовом метода "Вычислить" + +ServerExecutionSafeModeCheck_execute_issue = Отсутствует включение безопасного режима перед вызовом метода "Выполнить" + +ServerExecutionSafeModeCheck_title = Отсутствует включение безопасного режима перед вызовом метода "Выполнить" или "Вычислить" + StructureCtorTooManyKeysCheck_Maximum_structure_constructor_keys = Максимальное количество ключей структуры в конструкторе StructureCtorTooManyKeysCheck_Structure_constructor_has_more_than__0__keys = Конструктор структуры содержит более чем {0} ключей diff --git a/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/ServerExecutionSafeModeCheckTest.java b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/ServerExecutionSafeModeCheckTest.java new file mode 100644 index 00000000..d834a122 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/src/com/e1c/v8codestyle/bsl/check/itests/ServerExecutionSafeModeCheckTest.java @@ -0,0 +1,118 @@ +/******************************************************************************* + * Copyright (C) 2022, 1C-Soft LLC and others. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + * + * Contributors: + * 1C-Soft LLC - initial API and implementation + *******************************************************************************/ +package com.e1c.v8codestyle.bsl.check.itests; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.util.List; +import java.util.stream.Collectors; + +import org.eclipse.core.runtime.Path; +import org.junit.Test; + +import com._1c.g5.v8.dt.validation.marker.IExtraInfoKeys; +import com._1c.g5.v8.dt.validation.marker.Marker; +import com.e1c.v8codestyle.bsl.check.ServerExecutionSafeModeCheck; + +/** + * The test for class {@link ServerExecutionSafeModeCheck}. + * + * @author Maxim Galios + * + */ +public class ServerExecutionSafeModeCheckTest + extends AbstractSingleModuleTestBase +{ + + private static final String PROJECT_NAME = "ServerExecutionSafeModeCheck"; + + private static final String COMMON_MODULE_SERVER_CALL_FILE_NAME = + "/src/CommonModules/CommonModuleServerCall/Module.bsl"; + + private static final String COMMON_MODULE_FILE_NAME = "/src/CommonModules/CommonModule/Module.bsl"; + + private static final String FORM_MODULE_FILE_NAME = "/src/CommonForms/Form/Module.bsl"; + + public ServerExecutionSafeModeCheckTest() + { + super(ServerExecutionSafeModeCheck.class); + } + + @Override + protected String getTestConfigurationName() + { + return PROJECT_NAME; + } + + /** + * Test that warning is not shown without Server in Environment + * + * @throws Exception + */ + @Test + public void testCommonModule() throws Exception + { + List markers = getMarkers(COMMON_MODULE_FILE_NAME); + assertEquals(0, markers.size()); + } + + /** + * Test safe mode is enabled before Execute/Выполнить and Eval/Вычислить in common module + * + * @throws Exception + */ + @Test + public void testCommonModuleServerCall() throws Exception + { + List markers = getMarkers(COMMON_MODULE_SERVER_CALL_FILE_NAME); + assertEquals(6, markers.size()); + + assertEquals("4", markers.get(0).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("5", markers.get(1).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("11", markers.get(2).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("26", markers.get(3).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("29", markers.get(4).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("30", markers.get(5).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + } + + /** + * Test safe mode is enabled before Execute/Выполнить and Eval/Вычислить in form module + * + * @throws Exception + */ + @Test + public void testFormModule() throws Exception + { + List markers = getMarkers(FORM_MODULE_FILE_NAME); + assertEquals(4, markers.size()); + + assertEquals("4", markers.get(0).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("5", markers.get(1).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("14", markers.get(2).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + assertEquals("15", markers.get(3).getExtraInfo().get(IExtraInfoKeys.TEXT_EXTRA_INFO_LINE_KEY)); + } + + private List getMarkers(String moduleFileName) + { + String moduleId = Path.ROOT.append(getTestConfigurationName()).append(moduleFileName).toString(); + List markers = List.of(markerManager.getMarkers(getProject().getWorkspaceProject(), moduleId)); + + String checkId = getCheckId(); + + assertNotNull(checkId); + return markers.stream() + .filter(marker -> checkId.equals(getCheckIdFromMarker(marker, getProject()))) + .collect(Collectors.toList()); + } +} diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.project b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.project new file mode 100644 index 00000000..c132e650 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.project @@ -0,0 +1,18 @@ + + + ServerExecutionSafeModeCheck + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + + org.eclipse.xtext.ui.shared.xtextNature + com._1c.g5.v8.dt.core.V8ConfigurationNature + + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.autosort.prefs b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.autosort.prefs new file mode 100644 index 00000000..23b06250 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.autosort.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +topObjects=true diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.bsl.prefs b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.bsl.prefs new file mode 100644 index 00000000..ac5ba525 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.bsl.prefs @@ -0,0 +1,3 @@ +addModuleStrictTypesAnnotation=false +createModuleStructure=false +eclipse.preferences.version=1 diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.prefs b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.prefs new file mode 100644 index 00000000..9e9b57e5 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/com.e1c.v8codestyle.prefs @@ -0,0 +1,3 @@ +commonChecks=true +eclipse.preferences.version=1 +standardChecks=true diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/org.eclipse.core.resources.prefs b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 00000000..99f26c02 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/DT-INF/PROJECT.PMF b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/DT-INF/PROJECT.PMF new file mode 100644 index 00000000..e2a20317 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/DT-INF/PROJECT.PMF @@ -0,0 +1,2 @@ +Manifest-Version: 1.0 +Runtime-Version: 8.3.21 diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Form.form b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Form.form new file mode 100644 index 00000000..5e856847 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Form.form @@ -0,0 +1,26 @@ + + + + FormCommandBar + -1 + true + true + + true + + Left + true + + true + true + Vertical + true + true + true + true + true + + + + + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Form.mdo b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Form.mdo new file mode 100644 index 00000000..1ae3e2f5 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Form.mdo @@ -0,0 +1,10 @@ + + + Form + + en + Form + + PersonalComputer + MobileDevice + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Module.bsl b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Module.bsl new file mode 100644 index 00000000..6dc469a5 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonForms/Form/Module.bsl @@ -0,0 +1,19 @@ +&НаСервере +Процедура Тест1() + Код = "Рез = 1 + 1"; + Выполнить(Код); + а = Вычислить(Код); + УстановитьБезопасныйРежим(Истина); + Выполнить(Код); + а = Вычислить(Код); +КонецПроцедуры + +&AtServer +Функция Тест2() + Код = "Рез = 1 + 1"; + Execute(Код); + а = Eval(Код); + SetSafeMode(True); + Execute(Код); + а = Eval(Код); +КонецФункции \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModule/CommonModule.mdo b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModule/CommonModule.mdo new file mode 100644 index 00000000..a7715d65 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModule/CommonModule.mdo @@ -0,0 +1,10 @@ + + + CommonModule + + en + Common module + + true + true + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModule/Module.bsl b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModule/Module.bsl new file mode 100644 index 00000000..223ab0c5 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModule/Module.bsl @@ -0,0 +1,5 @@ +Функция Тест() + Код = "Рез = 1 + 1"; + Выполнить(Код); + а = 1 + Вычислить(Код); +КонецФункции \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModuleServerCall/CommonModuleServerCall.mdo b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModuleServerCall/CommonModuleServerCall.mdo new file mode 100644 index 00000000..296a737f --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModuleServerCall/CommonModuleServerCall.mdo @@ -0,0 +1,10 @@ + + + CommonModuleServerCall + + en + Common module + + true + true + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModuleServerCall/Module.bsl b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModuleServerCall/Module.bsl new file mode 100644 index 00000000..61351864 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/CommonModules/CommonModuleServerCall/Module.bsl @@ -0,0 +1,42 @@ +Функция Тест() + Код = "Рез = 1 + 1"; + УстановитьБезопасныйРежим(Ложь); + Выполнить(Код); + a = Вычислить(Код); + + Попытка + SetSafeMode(True); + Выполнить(Код); + Исключение + а = 1 + Вычислить(Код); + SetSafeMode(True); + КонецПопытки; + + Выполнить(Код); + а = а + Вычислить(Код); + + Если 1 > 0 Тогда + Для Счетчик = 1 По 5 Цикл + а = 1 + Вычислить(Код); + КонецЦикла; + ИначеЕсли 1 = 0 Тогда + Выполнить(Код); + Иначе + SetSafeMode(False); + а = 1 + Вычислить(Код); + КонецЕсли; + + Выполнить(Код); + а = а + Вычислить(Код); + + Если 1 > 0 Тогда + Для Счетчик = 1 По 5 Цикл + УстановитьБезопасныйРежим(Истина); + КонецЦикла; + Иначе + УстановитьБезопасныйРежим(Истина); + КонецЕсли; + + Execute(Код); + а = 1 + Eval(Код); +КонецФункции \ No newline at end of file diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/CommandInterface.cmi b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/CommandInterface.cmi new file mode 100644 index 00000000..0cf6de8a --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/CommandInterface.cmi @@ -0,0 +1,2 @@ + + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/Configuration.mdo b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/Configuration.mdo new file mode 100644 index 00000000..ef3fa206 --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/Configuration.mdo @@ -0,0 +1,44 @@ + + + ServerExecutionSafeModeCheck + + en + Server execution safe mode check + + + + + + + + + 8.3.21 + ManagedApplication + PersonalComputer + + + true + + + OSBackup + true + + + Language.English + Managed + NotAutoFree + DontUse + DontUse + 8.3.21 + + English + + en + English + + en + + CommonModule.CommonModule + CommonModule.CommonModuleServerCall + CommonForm.Form + diff --git a/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/MainSectionCommandInterface.cmi b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/MainSectionCommandInterface.cmi new file mode 100644 index 00000000..0cf6de8a --- /dev/null +++ b/tests/com.e1c.v8codestyle.bsl.itests/workspace/ServerExecutionSafeModeCheck/src/Configuration/MainSectionCommandInterface.cmi @@ -0,0 +1,2 @@ + +