1
0
mirror of https://github.com/1C-Company/v8-code-style.git synced 2026-05-19 02:20:43 +02:00

add RestrictionExecuteExternalCodeCheck and test

This commit is contained in:
IvanSergeev
2026-04-10 15:41:57 +04:00
parent d7fb9c9936
commit f4c472c0f1
22 changed files with 456 additions and 0 deletions
@@ -0,0 +1,26 @@
# Restriction execute external code check.
When using the Standard Subsystem Library in a configuration, you should use the library's component
connection methods and completely avoid direct use of platform-specific mechanisms for connecting
external components, such as:
AttachAddIn
BeginInstallAddIn
InstallAddIn
BeginAttachIngAddin
LoadAddIn
New OpenSSLSecureConnection
Should use the methods from the Standard Subsystems Library.
## Noncompliant Code Example
New OpenSSLSecureConnection;
## Compliant Solution
CommonClienServer.NewSecureConnection;
## See
- [Restriction execute external code check](https://its.1c.ru/db/v8std#content:669:hdoc)
@@ -0,0 +1,27 @@
# Ограничение на выполнение «внешнего» кода
При использовании в конфигурации Библиотеки стандартных
подсистем, следует использовать методы подключения компонент
библиотеки и полностью исключить непосредственное использование
платформенных механизмов подключения внешних компонент, таких как:
ПодключитьВнешнююКомпоненту
НачатьУстановкуВнешнейКомпоненты
УстановитьВнешнююКомпоненту
НачатьПодключениеВнешнейКомпоненты
ЗагрузитьВнешнююКомпоненту
Новый ЗащищенноеСоединениеOpenSSL;
## Неправильно
Новый ЗащищенноеСоединениеOpenSSL;
## Правильно
ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение();
## См.
- [Ограничение на выполнение «внешнего» кода](https://its.1c.ru/db/v8std#content:669:hdoc)
@@ -212,6 +212,10 @@
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.RegionEmptyCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.RestrictionExecuteExternalCodeCheck">
</check>
<check
category="com.e1c.v8codestyle.bsl"
class="com.e1c.v8codestyle.internal.bsl.ExecutableExtensionFactory:com.e1c.v8codestyle.bsl.check.SelfAssignCheck">
@@ -175,6 +175,12 @@ final class Messages
public static String RedundantExportCheck_Unused_export_method__0;
public static String RestrictionExecuteExternalCodeCheck_Description;
public static String RestrictionExecuteExternalCodeCheck_Issue;
public static String RestrictionExecuteExternalCodeCheck_Title;
public static String ExportMethodInCommandFormModuleCheck_CheckClientMethodForm;
public static String ExportMethodInCommandFormModuleCheck_CheckServerMethodForm;
@@ -0,0 +1,132 @@
/*******************************************************************************
* Copyright (C) 2026, 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;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.INVOCATION;
import static com._1c.g5.v8.dt.bsl.model.BslPackage.Literals.SIMPLE_STATEMENT;
import java.util.Set;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
import com._1c.g5.v8.dt.bsl.model.FeatureAccess;
import com._1c.g5.v8.dt.bsl.model.Invocation;
import com._1c.g5.v8.dt.bsl.model.OperatorStyleCreator;
import com._1c.g5.v8.dt.bsl.model.SimpleStatement;
import com._1c.g5.v8.dt.core.platform.IConfigurationProvider;
import com._1c.g5.v8.dt.core.platform.IV8ProjectManager;
import com._1c.g5.v8.dt.metadata.mdclass.Configuration;
import com._1c.g5.v8.dt.metadata.mdclass.Subsystem;
import com.e1c.g5.v8.dt.check.CheckComplexity;
import com.e1c.g5.v8.dt.check.ICheckParameters;
import com.e1c.g5.v8.dt.check.components.ModuleTopObjectNameFilterExtension;
import com.e1c.g5.v8.dt.check.settings.IssueSeverity;
import com.e1c.g5.v8.dt.check.settings.IssueType;
import com.e1c.v8codestyle.check.CommonSenseCheckExtension;
import com.e1c.v8codestyle.internal.bsl.BslPlugin;
import com.google.inject.Inject;
/**
* Restriction execute external code check.
*
* @author Ivan Sergeev
*/
public class RestrictionExecuteExternalCodeCheck
extends AbstractModuleStructureCheck
{
private static final String CHECK_ID = "restriction-execute-external-code"; //$NON-NLS-1$
private static final Set<String> IMMUTABLE_MAP_COMPONENT = Set.of("подключитьвнешнююкомпоненту", "attachaddin", //$NON-NLS-1$//$NON-NLS-2$
"начатьустановкувнешнейкомпоненты", "begininstalladdin", "установитьвнешнююкомпоненту", "installaddin", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
"начатьподключениевнешнейкомпоненты", "beginattachingaddin", "загрузитьвнешнююкомпоненту", "loadaddin"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
private final IConfigurationProvider configurationProvider;
@Inject
public RestrictionExecuteExternalCodeCheck(IV8ProjectManager v8ProjectManager,
IConfigurationProvider configurationProvider)
{
super();
this.configurationProvider = configurationProvider;
}
@Override
public String getCheckId()
{
return CHECK_ID;
}
@Override
protected void configureCheck(CheckConfigurer builder)
{
builder.title(Messages.RestrictionExecuteExternalCodeCheck_Title)
.description(Messages.RestrictionExecuteExternalCodeCheck_Description)
.complexity(CheckComplexity.NORMAL)
.severity(IssueSeverity.MINOR)
.issueType(IssueType.SECURITY)
.extension(new ModuleTopObjectNameFilterExtension())
.extension(new CommonSenseCheckExtension(getCheckId(), BslPlugin.PLUGIN_ID))
.module()
.checkedObjectType(SIMPLE_STATEMENT)
.checkedObjectType(INVOCATION);
}
@Override
protected void check(Object object, ResultAcceptor resultAceptor, ICheckParameters parameters,
IProgressMonitor monitor)
{
EObject eObject = (EObject)object;
Configuration configuration = configurationProvider.getConfiguration(eObject);
EList<Subsystem> subSystems = configuration.getSubsystems();
if (findSSL(subSystems))
{
if (object instanceof SimpleStatement statement)
{
if (statement.getRight() instanceof OperatorStyleCreator right)
{
String nameObj = NodeModelUtils.findActualNodeFor(right).getText();
if (nameObj.toLowerCase().contains("защищенноесоединениеopenssl") //$NON-NLS-1$
|| nameObj.toLowerCase().contains("opensslsecureconnection")) //$NON-NLS-1$
{
resultAceptor.addIssue(Messages.RestrictionExecuteExternalCodeCheck_Issue, right);
}
}
}
if (object instanceof Invocation invocation)
{
FeatureAccess featureAccess = invocation.getMethodAccess();
String name = featureAccess.getName();
if (IMMUTABLE_MAP_COMPONENT.contains(name.toLowerCase()))
{
resultAceptor.addIssue(Messages.RestrictionExecuteExternalCodeCheck_Issue, invocation);
}
}
}
}
private boolean findSSL(EList<Subsystem> subSystems)
{
for (Subsystem subsystem : subSystems)
{
String name = subsystem.getName();
if (name.equalsIgnoreCase("СтандартныеПодсистемы") || name.equalsIgnoreCase("StandardSubsystems")) //$NON-NLS-1$ //$NON-NLS-2$
{
return true;
}
}
return false;
}
}
@@ -482,6 +482,12 @@ RollbackTransactionCheck_Transactions_is_broken = Rollback transaction is incorr
RollbackTransactionCheck_Transactions_is_broken_des = Rollback transaction must be in a try-catch, there should be no executable code between exception and rollback transaction, there is no begin transaction for rollback transaction, there is no commit transaction for begin transaction.
RestrictionExecuteExternalCodeCheck_Description = Restriction on execution of "external" code check
RestrictionExecuteExternalCodeCheck_Issue = Need to use the constructor from SSL(Standard Subsystems Library)
RestrictionExecuteExternalCodeCheck_Title = Restriction on execution of "external" code check
SelfAssignCheck_Title = Self assign
SelfAssignCheck_Description = Checks that variable self assign
@@ -470,6 +470,12 @@ RollbackTransactionCheck_Transactions_is_broken = Нарушена схема р
RollbackTransactionCheck_Transactions_is_broken_des = Вызов "ОтменитьТранзакцию()" находится вне конструкции "Попытка... Исключение". Отсутствует вызов "НачатьТранзакцию()", хотя вызываются "ОтменитьТранзакцию()". Для вызова "НачатьТранзакцию()" отсутствует парный вызов "ЗафиксироватьТранзакцию()". Между "Исключение" и "ОтменитьТранзакцию()" есть исполняемый код, который может вызвать исключение.
RestrictionExecuteExternalCodeCheck_Description = Проверка на ограничение на выполнение «внешнего» кода
RestrictionExecuteExternalCodeCheck_Issue = Нужно использовать конструктор из БСП(Библиотека Стандартных Подсистем)
RestrictionExecuteExternalCodeCheck_Title = Проверка на ограничение на выполнение «внешнего» кода
MethodSemicolonExtraCheck_Description = Лишняя точка с запятой
MethodSemicolonExtraCheck_Title = Лишняя точка с запятой
@@ -0,0 +1,5 @@
Процедура Тест1(Параметры)
УстановитьВнешнююКомпоненту(<Местоположение>);
КонецПроцедуры
@@ -0,0 +1,5 @@
Процедура Тест1(Параметры)
ОбщегоНазначения.ПодключитьКомпонентуИзМакета(<Местоположение>);
КонецПроцедуры
@@ -0,0 +1,5 @@
Процедура Тест1(Параметры)
Тест = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение();
КонецПроцедуры
@@ -0,0 +1,5 @@
Процедура Тест1(Параметры)
HTTPСоединение = Новый HTTPСоединение(,,,,,, Новый ЗащищенноеСоединениеOpenSSL);
КонецПроцедуры
@@ -0,0 +1,5 @@
Процедура Тест1(Параметры)
Тест = Новый ЗащищенноеСоединениеOpenSSL;
КонецПроцедуры
@@ -0,0 +1,123 @@
/*******************************************************************************
* Copyright (C) 2026, 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.assertTrue;
import java.util.List;
import org.junit.Test;
import com._1c.g5.v8.dt.validation.marker.Marker;
import com._1c.g5.v8.dt.validation.marker.StandardExtraInfo;
import com.e1c.v8codestyle.bsl.check.RestrictionExecuteExternalCodeCheck;
/**
* Tests for {@link RestrictionExecuteExternalCodeCheck} check.
*
* @author Ivan Sergeev
*/
public class RestrictionExecuteExternalCodeCheckTest
extends AbstractSingleModuleTestBase
{
private static final String PROJECT_NAME = "ExecuteExternalCodeCheckTest";
public RestrictionExecuteExternalCodeCheckTest()
{
super(RestrictionExecuteExternalCodeCheck.class);
}
@Override
protected String getTestConfigurationName()
{
return PROJECT_NAME;
}
/**
* Test invocation not use SSL.
*
* @throws Exception the exception
*/
@Test
public void testInvocationNotUseSSL() throws Exception
{
updateModule(FOLDER_RESOURCE + "new-unsafe-openssl.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals(Integer.valueOf(3), marker.getExtraInfo().get(StandardExtraInfo.TEXT_LINE));
}
/**
* Test invocation not use SSL in parametr.
*
* @throws Exception the exception
*/
@Test
public void testInvocationNotUseSSLinParametr() throws Exception
{
updateModule(FOLDER_RESOURCE + "new-unsafe-openssl-parametr.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals(Integer.valueOf(3), marker.getExtraInfo().get(StandardExtraInfo.TEXT_LINE));
}
/**
* Test invocation use SSL.
*
* @throws Exception the exception
*/
@Test
public void testInvocationUseSSL() throws Exception
{
updateModule(FOLDER_RESOURCE + "new-safe-openssl.bsl");
List<Marker> markers = getModuleMarkers();
assertTrue(markers.isEmpty());
}
/**
* External call not use ssl.
*
* @throws Exception the exception
*/
@Test
public void testExternalCallNotUseSSL() throws Exception
{
updateModule(FOLDER_RESOURCE + "external-call-not-use-ssl.bsl");
List<Marker> markers = getModuleMarkers();
assertEquals(1, markers.size());
Marker marker = markers.get(0);
assertEquals(Integer.valueOf(3), marker.getExtraInfo().get(StandardExtraInfo.TEXT_LINE));
}
/**
* External call use ssl.
*
* @throws Exception the exception
*/
@Test
public void testExternalCallUseSSL() throws Exception
{
updateModule(FOLDER_RESOURCE + "external-call-no-ssl.bsl");
List<Marker> markers = getModuleMarkers();
assertTrue(markers.isEmpty());
}
}
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>StructureModule</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.xtext.ui.shared.xtextBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.xtext.ui.shared.xtextNature</nature>
<nature>com._1c.g5.v8.dt.core.V8ConfigurationNature</nature>
</natures>
</projectDescription>
@@ -0,0 +1,2 @@
eclipse.preferences.version=1
encoding/<project>=UTF-8
@@ -0,0 +1,2 @@
Manifest-Version: 1.0
Runtime-Version: 8.3.19
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:CommonModule xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="6cbbf814-18db-453c-92ed-054a8f310cdc">
<name>CommonModule</name>
<synonym>
<key>en</key>
<value>Common module</value>
</synonym>
<server>true</server>
<clientManagedApplication>true</clientManagedApplication>
<externalConnection>true</externalConnection>
<clientOrdinaryApplication>true</clientOrdinaryApplication>
</mdclass:CommonModule>
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Configuration xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="da3da622-85c7-4a68-9cb7-0ee5aa7448e7">
<name>StructureModule</name>
<synonym>
<key>en</key>
<value>Structure module</value>
</synonym>
<containedObjects classId="9cd510cd-abfc-11d4-9434-004095e12fc7" objectId="11fab9f4-1ac8-4b90-974c-148dd1f1ee29"/>
<containedObjects classId="9fcd25a0-4822-11d4-9414-008048da11f9" objectId="23524e35-34a7-4bc8-94d1-c314704aad64"/>
<containedObjects classId="e3687481-0a87-462c-a166-9f34594f9bba" objectId="bf5898bf-f470-4416-bbdf-78425a7ed95d"/>
<containedObjects classId="9de14907-ec23-4a07-96f0-85521cb6b53b" objectId="b1d7c42c-2468-422c-aae9-22ca0f17d470"/>
<containedObjects classId="51f2d5d8-ea4d-4064-8892-82951750031e" objectId="95b2fb6a-d0b0-4bba-933f-f25846ff134c"/>
<containedObjects classId="e68182ea-4237-4383-967f-90c1e3370bc7" objectId="212dac74-8939-4083-bd96-464aef7f5c0a"/>
<containedObjects classId="fb282519-d103-4dd3-bc12-cb271d631dfc" objectId="536422e3-5396-4bae-99a5-bdb058bfc993"/>
<configurationExtensionCompatibilityMode>8.3.20</configurationExtensionCompatibilityMode>
<defaultRunMode>ManagedApplication</defaultRunMode>
<usePurposes>PersonalComputer</usePurposes>
<usedMobileApplicationFunctionalities>
<functionality>
<use>true</use>
</functionality>
<functionality>
<functionality>OSBackup</functionality>
<use>true</use>
</functionality>
</usedMobileApplicationFunctionalities>
<defaultLanguage>Language.English</defaultLanguage>
<dataLockControlMode>Managed</dataLockControlMode>
<objectAutonumerationMode>NotAutoFree</objectAutonumerationMode>
<modalityUseMode>DontUse</modalityUseMode>
<synchronousPlatformExtensionAndAddInCallUseMode>DontUse</synchronousPlatformExtensionAndAddInCallUseMode>
<compatibilityMode>8.3.20</compatibilityMode>
<languages uuid="52ec6aa9-b177-434c-b409-1c456749c996">
<name>English</name>
<synonym>
<key>en</key>
<value>English</value>
</synonym>
<languageCode>en</languageCode>
</languages>
<commonModules>CommonModule.CommonModule</commonModules>
<subsystems>Subsystem.StandardSubsystems</subsystems>
</mdclass:Configuration>
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<cmi:CommandInterface xmlns:cmi="http://g5.1c.ru/v8/dt/cmi"/>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<mdclass:Subsystem xmlns:mdclass="http://g5.1c.ru/v8/dt/metadata/mdclass" uuid="9b610df6-99ac-4c41-b752-4f2fe0370fbb">
<name>StandardSubsystems</name>
<synonym>
<key>en</key>
<value>Standard Subsystem</value>
</synonym>
<synonym>
<key>de</key>
<value>Standard Subsystem</value>
</synonym>
<synonym>
<key>ru</key>
<value>Стандартная Подсистема</value>
</synonym>
<includeHelpInContents>true</includeHelpInContents>
<includeInCommandInterface>true</includeInCommandInterface>
</mdclass:Subsystem>