Do not fail with ISE if default change query contains quoted invalid regex
If a default query contains an invalid regex, e.g. "^[A", parsing the query fails and the request is rejected as '400 Bad Request' (the parsing fails because '[' is a syntax character in our Antlr syntax specification). If the invalid regex is quoted the parsing succeeded, but then creating the Automaton failed with an IllegalArgumentException which caused a '500 Internal Sever Error'. We now catch the IllegalArgumentException and wrap it into a QueryParseException so that the user gets a '400 Bad Request'. This is better than failing, but not ideal yet. Ideally we would ignore the QueryParseException for the default query and just have no match, but if we do that executing the query fails in Lucene which would again be an internal server error. Change-Id: Ic1d18919ca8a6a8d21156b7b3bf3b96aeb382624 Signed-off-by: Edwin Kempin <ekempin@google.com>
This commit is contained in:
@@ -703,7 +703,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> branch(String name) {
|
public Predicate<ChangeData> branch(String name) throws QueryParseException {
|
||||||
if (name.startsWith("^")) {
|
if (name.startsWith("^")) {
|
||||||
return ref("^" + RefNames.fullName(name.substring(1)));
|
return ref("^" + RefNames.fullName(name.substring(1)));
|
||||||
}
|
}
|
||||||
@@ -732,7 +732,7 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData, ChangeQueryBuil
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Operator
|
@Operator
|
||||||
public Predicate<ChangeData> ref(String ref) {
|
public Predicate<ChangeData> ref(String ref) throws QueryParseException {
|
||||||
if (ref.startsWith("^")) {
|
if (ref.startsWith("^")) {
|
||||||
return new RegexRefPredicate(ref);
|
return new RegexRefPredicate(ref);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
package com.google.gerrit.server.query.change;
|
package com.google.gerrit.server.query.change;
|
||||||
|
|
||||||
import com.google.gerrit.entities.Change;
|
import com.google.gerrit.entities.Change;
|
||||||
|
import com.google.gerrit.index.query.QueryParseException;
|
||||||
import com.google.gerrit.server.index.change.ChangeField;
|
import com.google.gerrit.server.index.change.ChangeField;
|
||||||
import dk.brics.automaton.RegExp;
|
import dk.brics.automaton.RegExp;
|
||||||
import dk.brics.automaton.RunAutomaton;
|
import dk.brics.automaton.RunAutomaton;
|
||||||
@@ -22,7 +23,7 @@ import dk.brics.automaton.RunAutomaton;
|
|||||||
public class RegexRefPredicate extends ChangeRegexPredicate {
|
public class RegexRefPredicate extends ChangeRegexPredicate {
|
||||||
protected final RunAutomaton pattern;
|
protected final RunAutomaton pattern;
|
||||||
|
|
||||||
public RegexRefPredicate(String re) {
|
public RegexRefPredicate(String re) throws QueryParseException {
|
||||||
super(ChangeField.REF, re);
|
super(ChangeField.REF, re);
|
||||||
|
|
||||||
if (re.startsWith("^")) {
|
if (re.startsWith("^")) {
|
||||||
@@ -33,7 +34,11 @@ public class RegexRefPredicate extends ChangeRegexPredicate {
|
|||||||
re = re.substring(0, re.length() - 1);
|
re = re.substring(0, re.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.pattern = new RunAutomaton(new RegExp(re).toAutomaton());
|
try {
|
||||||
|
this.pattern = new RunAutomaton(new RegExp(re).toAutomaton());
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new QueryParseException(String.format("invalid regular expression: %s", re), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ package com.google.gerrit.acceptance.api.change;
|
|||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
|
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.block;
|
||||||
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
|
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
|
||||||
|
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
|
||||||
import static java.util.stream.Collectors.toList;
|
import static java.util.stream.Collectors.toList;
|
||||||
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
import static javax.servlet.http.HttpServletResponse.SC_OK;
|
||||||
|
|
||||||
@@ -31,6 +32,7 @@ import com.google.gerrit.common.data.Permission;
|
|||||||
import com.google.gerrit.entities.Account;
|
import com.google.gerrit.entities.Account;
|
||||||
import com.google.gerrit.entities.Project;
|
import com.google.gerrit.entities.Project;
|
||||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||||
|
import com.google.gerrit.extensions.restapi.BadRequestException;
|
||||||
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
import com.google.gerrit.extensions.restapi.TopLevelResource;
|
||||||
import com.google.gerrit.server.restapi.change.QueryChanges;
|
import com.google.gerrit.server.restapi.change.QueryChanges;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
@@ -225,6 +227,26 @@ public class QueryChangeIT extends AbstractDaemonTest {
|
|||||||
assertThat(queryChanges.apply(TopLevelResource.INSTANCE).statusCode()).isEqualTo(SC_OK);
|
assertThat(queryChanges.apply(TopLevelResource.INSTANCE).statusCode()).isEqualTo(SC_OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultQueryCannotBeParsedDueToInvalidRegEx() throws Exception {
|
||||||
|
QueryChanges queryChanges = queryChangesProvider.get();
|
||||||
|
queryChanges.addQuery("^[A");
|
||||||
|
BadRequestException e =
|
||||||
|
assertThrows(
|
||||||
|
BadRequestException.class, () -> queryChanges.apply(TopLevelResource.INSTANCE));
|
||||||
|
assertThat(e).hasMessageThat().contains("no viable alternative at character '['");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultQueryWithInvalidQuotedRegEx() throws Exception {
|
||||||
|
QueryChanges queryChanges = queryChangesProvider.get();
|
||||||
|
queryChanges.addQuery("\"^[A\"");
|
||||||
|
BadRequestException e =
|
||||||
|
assertThrows(
|
||||||
|
BadRequestException.class, () -> queryChanges.apply(TopLevelResource.INSTANCE));
|
||||||
|
assertThat(e).hasMessageThat().isEqualTo("invalid regular expression: [A");
|
||||||
|
}
|
||||||
|
|
||||||
private static void assertNoChangeHasMoreChangesSet(List<ChangeInfo> results) {
|
private static void assertNoChangeHasMoreChangesSet(List<ChangeInfo> results) {
|
||||||
for (ChangeInfo info : results) {
|
for (ChangeInfo info : results) {
|
||||||
assertThat(info._moreChanges).isNull();
|
assertThat(info._moreChanges).isNull();
|
||||||
|
|||||||
Reference in New Issue
Block a user