aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZipeng WU <zipeng.wu@sonarsource.com>2020-12-11 11:53:25 +0100
committersonartech <sonartech@sonarsource.com>2020-12-14 20:07:14 +0000
commit4e07979ccca556d5f05a1be05b88f0bd85ff3f66 (patch)
tree1777a263c3791d7c9758305f4b92d9eb8ef1ab58
parent4b21e80ea3374259f9ee8531421348cec14cd41c (diff)
downloadsonarqube-4e07979ccca556d5f05a1be05b88f0bd85ff3f66.tar.gz
sonarqube-4e07979ccca556d5f05a1be05b88f0bd85ff3f66.zip
Refactor regex that can lead to a stack overflow for large inputs
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleParamType.java26
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RuleParamTypeTest.java6
2 files changed, 25 insertions, 7 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleParamType.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleParamType.java
index dd9c4d8409c..563369008ca 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleParamType.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RuleParamType.java
@@ -19,6 +19,7 @@
*/
package org.sonar.api.server.rule;
+import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
@@ -40,7 +41,6 @@ public final class RuleParamType {
public static final RuleParamType INTEGER = new RuleParamType("INTEGER");
public static final RuleParamType FLOAT = new RuleParamType("FLOAT");
- private static final String CSV_SPLIT_REGEX = ",(?=([^\"]*\"[^\"]*\")*[^\"]*$)";
private static final String VALUES_PARAM = "values";
private static final String MULTIPLE_PARAM = "multiple";
private static final String PARAMETER_SEPARATOR = "=";
@@ -110,7 +110,6 @@ public final class RuleParamType {
return new RuleParamType(type, true, acceptedValues);
}
- // TODO validate format
public static RuleParamType parse(String s) {
// deprecated formats
if ("i".equals(s) || "i{}".equals(s)) {
@@ -131,7 +130,7 @@ public final class RuleParamType {
String format = StringUtils.substringBefore(s, OPTION_SEPARATOR);
String values = null;
boolean multiple = false;
- String[] options = s.split(CSV_SPLIT_REGEX);
+ String[] options = csvFormatSplit(s);
for (String option : options) {
String opt = StringEscapeUtils.unescapeCsv(option);
if (opt.startsWith(VALUES_PARAM + PARAMETER_SEPARATOR)) {
@@ -143,7 +142,26 @@ public final class RuleParamType {
if (values == null || StringUtils.isBlank(values)) {
return new RuleParamType(format);
}
- return new RuleParamType(format, multiple, values.split(CSV_SPLIT_REGEX));
+ return new RuleParamType(format, multiple, csvFormatSplit(values));
+ }
+
+ private static String[] csvFormatSplit(String input) {
+ List<String> result = new ArrayList<>();
+ boolean betweenQuote = false;
+ int startIndex = 0;
+ for (int i = 0; i < input.length(); i++) {
+ char c = input.charAt(i);
+ if (c == '"') {
+ betweenQuote = !betweenQuote;
+ } else if (!betweenQuote && c == ',') {
+ result.add(input.substring(startIndex, i));
+ startIndex = i + 1;
+ }
+ }
+ if (startIndex < input.length()) {
+ result.add(input.substring(startIndex));
+ }
+ return result.toArray(new String[0]);
}
@Override
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RuleParamTypeTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RuleParamTypeTest.java
index e45d7011e0e..99069e38cae 100644
--- a/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RuleParamTypeTest.java
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/server/rule/RuleParamTypeTest.java
@@ -68,13 +68,13 @@ public class RuleParamTypeTest {
assertThat(selectList.multiple()).isFalse();
assertThat(selectList.toString()).isEqualTo("SINGLE_SELECT_LIST,values=\"foo,bar,\"");
- RuleParamType.parse("SINGLE_SELECT_LIST,values=\"foo,bar\",multiple=false");
+ selectList = RuleParamType.parse("SINGLE_SELECT_LIST,values=\"foo,bar\",multiple=false");
assertThat(selectList.type()).isEqualTo("SINGLE_SELECT_LIST");
assertThat(selectList.values()).containsOnly("foo", "bar");
assertThat(selectList.multiple()).isFalse();
assertThat(selectList.toString()).isEqualTo("SINGLE_SELECT_LIST,values=\"foo,bar,\"");
- RuleParamType.parse("SINGLE_SELECT_LIST,\"values=foo,bar\",\"multiple=false\"");
+ selectList = RuleParamType.parse("SINGLE_SELECT_LIST,\"values=foo,bar\",multiple=false");
assertThat(selectList.type()).isEqualTo("SINGLE_SELECT_LIST");
assertThat(selectList.values()).containsOnly("foo", "bar");
assertThat(selectList.multiple()).isFalse();
@@ -96,7 +96,7 @@ public class RuleParamTypeTest {
assertThat(selectList.multiple()).isTrue();
assertThat(selectList.toString()).isEqualTo("SINGLE_SELECT_LIST,multiple=true,values=\"foo,bar,\"");
- RuleParamType.parse("SINGLE_SELECT_LIST,\"values=foo,bar\",\"multiple=true\"");
+ selectList = RuleParamType.parse("SINGLE_SELECT_LIST,\"values=foo,bar\",multiple=true");
assertThat(selectList.type()).isEqualTo("SINGLE_SELECT_LIST");
assertThat(selectList.values()).containsOnly("foo", "bar");
assertThat(selectList.multiple()).isTrue();