From 1fa82d8470a94bf164c9c53a4d200956edebb35f Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Wed, 13 Jun 2018 11:17:42 +0200 Subject: [PATCH] SONAR-10867 Add a rule in Xoo to report security hotspots --- .../main/java/org/sonar/xoo/XooPlugin.java | 4 + .../org/sonar/xoo/rule/HotspotSensor.java | 73 +++++++++++++++++++ .../sonar/xoo/rule/XooRulesDefinition.java | 8 ++ .../sonar/xoo/rule/XooSonarWayProfile.java | 1 + .../java/org/sonar/xoo/XooPluginTest.java | 8 ++ .../xoo/rule/XooRulesDefinitionTest.java | 2 +- 6 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HotspotSensor.java diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java index 82162851aa8..50907147b20 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/XooPlugin.java @@ -42,6 +42,7 @@ import org.sonar.xoo.rule.ChecksSensor; import org.sonar.xoo.rule.CreateIssueByInternalKeySensor; import org.sonar.xoo.rule.CustomMessageSensor; import org.sonar.xoo.rule.HasTagSensor; +import org.sonar.xoo.rule.HotspotSensor; import org.sonar.xoo.rule.MultilineIssuesSensor; import org.sonar.xoo.rule.NoSonarSensor; import org.sonar.xoo.rule.OneBlockerIssuePerFileSensor; @@ -170,6 +171,9 @@ public class XooPlugin implements Plugin { OneExternalIssueWithDetailsPerLineSensor.class, SignificantCodeSensor.class); } + if (context.getSonarQubeVersion().isGreaterThanOrEqual(Version.create(7, 3))) { + context.addExtension(HotspotSensor.class); + } } } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HotspotSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HotspotSensor.java new file mode 100644 index 00000000000..dd573dbbee5 --- /dev/null +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/HotspotSensor.java @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2018 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.xoo.rule; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import org.sonar.api.batch.fs.FileSystem; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.issue.NewIssue; +import org.sonar.api.rule.RuleKey; + +/** + * Generate issues on all the occurrences of tag Hotspot in xoo sources. + */ +public class HotspotSensor extends AbstractXooRuleSensor { + + public static final String RULE_KEY = "Hotspot"; + public static final String TAG = "HOTSPOT"; + + public HotspotSensor(FileSystem fs, ActiveRules activeRules) { + super(fs, activeRules); + } + + @Override + protected String getRuleKey() { + return RULE_KEY; + } + + @Override + protected void processFile(InputFile inputFile, SensorContext context, RuleKey ruleKey, String languageKey) { + try { + int[] lineCounter = {1}; + try (InputStreamReader isr = new InputStreamReader(inputFile.inputStream(), inputFile.charset()); + BufferedReader reader = new BufferedReader(isr)) { + reader.lines().forEachOrdered(lineStr -> { + int startIndex = -1; + while ((startIndex = lineStr.indexOf(TAG, startIndex + 1)) != -1) { + NewIssue newIssue = context.newIssue(); + newIssue + .forRule(ruleKey) + .at(newIssue.newLocation() + .on(inputFile) + .at(inputFile.newRange(lineCounter[0], startIndex, lineCounter[0], startIndex + TAG.length()))) + .save(); + } + lineCounter[0]++; + }); + } + } catch (IOException e) { + throw new IllegalStateException("Fail to process " + inputFile, e); + } + } +} diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java index 5b072445cf4..303000225cb 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooRulesDefinition.java @@ -151,6 +151,14 @@ public class XooRulesDefinition implements RulesDefinition { .setName("Template of rule") .setHtmlDescription("Template to be overridden by custom rules"); + NewRule hotspot = repo.createRule(HotspotSensor.RULE_KEY) + .setName("Find security hotspots") + .setType(RuleType.SECURITY_HOTSPOT) + .setActivatedByDefault(false) + .setHtmlDescription("Search for Security Hotspots in Xoo files"); + hotspot + .setDebtRemediationFunction(hotspot.debtRemediationFunctions().constantPerIssue("2min")); + repo.done(); } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooSonarWayProfile.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooSonarWayProfile.java index b578c2c8974..c8e87180985 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooSonarWayProfile.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/XooSonarWayProfile.java @@ -35,6 +35,7 @@ public class XooSonarWayProfile extends ProfileDefinition { profile.activateRule(Rule.create(XooRulesDefinition.XOO_REPOSITORY, HasTagSensor.RULE_KEY), RulePriority.MAJOR); profile.activateRule(Rule.create(XooRulesDefinition.XOO_REPOSITORY, OneIssuePerLineSensor.RULE_KEY), RulePriority.INFO); profile.activateRule(Rule.create(XooRulesDefinition.XOO_REPOSITORY, OneIssuePerFileSensor.RULE_KEY), RulePriority.CRITICAL); + profile.activateRule(Rule.create(XooRulesDefinition.XOO_REPOSITORY, HotspotSensor.RULE_KEY), RulePriority.CRITICAL); return profile; } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java index 3efce09bee8..79aef631214 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/XooPluginTest.java @@ -57,4 +57,12 @@ public class XooPluginTest { new XooPlugin().define(context); assertThat(context.getExtensions()).hasSize(52).contains(OneExternalIssuePerLineSensor.class); } + + @Test + public void provide_extensions_for_7_3() { + SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.parse("7.3"), SonarQubeSide.SCANNER); + Plugin.Context context = new PluginContextImpl.Builder().setSonarRuntime(runtime).build(); + new XooPlugin().define(context); + assertThat(context.getExtensions()).hasSize(53).contains(OneExternalIssuePerLineSensor.class); + } } diff --git a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java index 48d04ccc20e..9658ab8e3a4 100644 --- a/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java +++ b/plugins/sonar-xoo-plugin/src/test/java/org/sonar/xoo/rule/XooRulesDefinitionTest.java @@ -42,7 +42,7 @@ public class XooRulesDefinitionTest { assertThat(repo).isNotNull(); assertThat(repo.name()).isEqualTo("Xoo"); assertThat(repo.language()).isEqualTo("xoo"); - assertThat(repo.rules()).hasSize(18); + assertThat(repo.rules()).hasSize(19); RulesDefinition.Rule rule = repo.rule(OneIssuePerLineSensor.RULE_KEY); assertThat(rule.name()).isNotEmpty(); -- 2.39.5