]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8436 escape param "tags" of WS api/rules/tags
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Tue, 29 Nov 2016 09:57:18 +0000 (10:57 +0100)
committerSimon Brandhof <simon.brandhof@sonarsource.com>
Wed, 30 Nov 2016 12:37:36 +0000 (13:37 +0100)
server/sonar-server/src/main/java/org/sonar/server/rule/index/RuleIndex.java
server/sonar-server/src/test/java/org/sonar/server/rule/RuleServiceMediumTest.java

index 20405f59bf17c1fb0bee61d7c7407ec7fa74e8d1..9fcc1101827ebae89adaf9c78660ddc71bdb3c15 100644 (file)
@@ -33,6 +33,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.regex.Pattern;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 import org.apache.commons.lang.StringUtils;
@@ -105,6 +106,7 @@ public class RuleIndex extends BaseIndex {
   public static final String FACET_STATUSES = "statuses";
   public static final String FACET_TYPES = "types";
   public static final String FACET_OLD_DEFAULT = "true";
+  private static Pattern SPECIAL_REGEX_CHARS = Pattern.compile("[{}()\\[\\].+*?^$\\\\|]");
 
   public static final List<String> ALL_STATUSES_EXCEPT_REMOVED = ImmutableList.copyOf(
     Collections2.filter(Collections2.transform(Arrays.asList(RuleStatus.values()), RuleStatusToString.INSTANCE), NotRemoved.INSTANCE));
@@ -180,8 +182,7 @@ public class RuleIndex extends BaseIndex {
     qb.should(simpleQueryStringQuery(query.getQueryText())
       .field(FIELD_RULE_NAME + "." + SEARCH_WORDS_SUFFIX, 20f)
       .field(FIELD_RULE_HTML_DESCRIPTION, 3f)
-      .defaultOperator(SimpleQueryStringBuilder.Operator.AND)
-      ).boost(20f);
+      .defaultOperator(SimpleQueryStringBuilder.Operator.AND)).boost(20f);
 
     // Match and partial Match queries
     // Search by key uses the "sortable" sub-field as it requires to be case-insensitive (lower-case filtering)
@@ -477,7 +478,7 @@ public class RuleIndex extends BaseIndex {
       .size(size)
       .minDocCount(1);
     if (query != null) {
-      termsAggregation.include(".*" + query + ".*");
+      termsAggregation.include(".*" + escapeSpecialRegexChars(query) + ".*");
     }
     SearchRequestBuilder request = getClient()
       .prepareSearch(INDEX)
@@ -495,6 +496,10 @@ public class RuleIndex extends BaseIndex {
     return terms;
   }
 
+  private static String escapeSpecialRegexChars(String str) {
+    return SPECIAL_REGEX_CHARS.matcher(str).replaceAll("\\\\$0");
+  }
+
   private enum ToRuleKey implements Function<String, RuleKey> {
     INSTANCE;
 
index d56d5aff5b712a8d5b5a07eaae029a303f0614f5..80440da8f90102356092aff4ba70b0be869bb51c 100644 (file)
@@ -82,17 +82,32 @@ public class RuleServiceMediumTest {
 
   @Test
   public void listTags_returns_tags_filtered_by_name() {
-    insertRule(RuleKey.of("javascript", "S001"), newHashSet("tag1"), newHashSet("sys1", "sys2"));
+    insertRule(RuleKey.of("javascript", "S001"), newHashSet("tag1", "misra++"), newHashSet("sys1", "sys2"));
     insertRule(RuleKey.of("java", "S001"), newHashSet("tag2"), newHashSet());
 
     assertThat(service.listTags("missing", 10)).isEmpty();
+    assertThat(service.listTags("", 10)).containsOnly("tag1", "misra++", "tag2", "sys1", "sys2");
     assertThat(service.listTags("tag", 10)).containsOnly("tag1", "tag2");
     assertThat(service.listTags("sys", 10)).containsOnly("sys1", "sys2");
+    assertThat(service.listTags("misra", 10)).containsOnly("misra++");
+    assertThat(service.listTags("misra+", 10)).containsOnly("misra++");
+    assertThat(service.listTags("++", 10)).containsOnly("misra++");
 
     // LIMITATION: case sensitive
     assertThat(service.listTags("TAG", 10)).isEmpty();
     assertThat(service.listTags("TAg", 10)).isEmpty();
     assertThat(service.listTags("MISSing", 10)).isEmpty();
+
+    assertThat(service.listTags("misra-", 10)).isEmpty();
+  }
+
+  @Test
+  public void listTags_returns_empty_results_if_filter_contains_regexp_special_characters() {
+    insertRule(RuleKey.of("javascript", "S001"), newHashSet("misra++"), newHashSet("sys1", "sys2"));
+
+    assertThat(service.listTags("mis[", 10)).isEmpty();
+    assertThat(service.listTags("mis\\d", 10)).isEmpty();
+    assertThat(service.listTags(".*", 10)).isEmpty();
   }
 
   @Test