Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,42 @@ default String getParameter(String name) {
@SuppressWarnings("JdkObsolete")
default String[] getParameterValues(String name) {
try {
int maxQueryStringLength = 64 * 1024;
int maxQueryParameterCount = 1024;
ArrayList<String> result = new ArrayList<>();
String queryString = getQueryString();
if (queryString != null) {
String[] pairs = queryString.split("&");
for (String pair : pairs) {
if (queryString.length() > maxQueryStringLength) {
throw new IllegalArgumentException(
"Query string too long: "
+ queryString.length()
+ " characters (max "
+ maxQueryStringLength
+ ")");
}
int start = 0;
int parameterCount = 0;
for (int end = queryString.indexOf('&'); start <= queryString.length(); ) {
parameterCount++;
if (parameterCount > maxQueryParameterCount) {
throw new IllegalArgumentException(
"Too many query parameters: "
+ parameterCount
+ " (max "
+ maxQueryParameterCount
+ ")");
}
String pair =
end == -1 ? queryString.substring(start) : queryString.substring(start, end);
int idx = pair.indexOf("=");
if (idx != -1 && URLDecoder.decode(pair.substring(0, idx), "UTF-8").equals(name)) {
result.add(URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
}
if (end == -1) {
break;
}
start = end + 1;
end = queryString.indexOf('&', start);
}
}
if (result.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ public void handleRequest(PrometheusHttpExchange exchange) throws IOException {
}
}
}
} catch (IllegalArgumentException e) {
PrometheusHttpResponse response = exchange.getResponse();
response.setHeader("Content-Type", "text/plain; charset=utf-8");
byte[] message = "Invalid query parameters".getBytes(StandardCharsets.UTF_8);
try (OutputStream outputStream = response.sendHeadersAndGetBody(400, message.length)) {
outputStream.write(message);
Comment thread
github-advanced-security[bot] marked this conversation as resolved.
Fixed
}
} catch (IOException e) {
exchange.handleException(e);
} catch (RuntimeException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,36 @@ void testMultipleMetricNameFilters() throws IOException {
assertThat(body).doesNotContain("metric_three");
}

@Test
void testRejectsTooManyQueryParameters() throws IOException {
StringBuilder queryString = new StringBuilder("name[]=test_counter");
for (int i = 0; i < 1024; i++) {
queryString.append("&name[]=metric_").append(i);
}

TestHttpExchange exchange = new TestHttpExchange("GET", queryString.toString());
handler.handleRequest(exchange);

assertThat(exchange.getResponseCode()).isEqualTo(400);
assertThat(exchange.getResponseHeaders().get("Content-Type"))
.isEqualTo("text/plain; charset=utf-8");
assertThat(exchange.getResponseBody()).isEqualTo("Invalid query parameters");
}

@Test
void testRejectsTooLongQueryString() throws IOException {
StringBuilder queryString = new StringBuilder("name[]=");
for (int i = 0; i < 64 * 1024; i++) {
queryString.append("a");
}

TestHttpExchange exchange = new TestHttpExchange("GET", queryString.toString());
handler.handleRequest(exchange);

assertThat(exchange.getResponseCode()).isEqualTo(400);
assertThat(exchange.getResponseBody()).isEqualTo("Invalid query parameters");
}

/** Test implementation of PrometheusHttpExchange for testing. */
private static class TestHttpExchange implements PrometheusHttpExchange {
private final TestHttpRequest request;
Expand Down Expand Up @@ -216,7 +246,7 @@ public Map<String, String> getResponseHeaders() {
}

public String getResponseBody() {
return rawResponseBody.toString(StandardCharsets.UTF_8);
return new String(rawResponseBody.toByteArray(), StandardCharsets.UTF_8);
}

public boolean isGzipCompressed() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.function.Predicate;
import javax.annotation.Nullable;

Expand All @@ -26,10 +27,10 @@ private MetricNameFilter(
Collection<String> nameIsNotEqualTo,
Collection<String> nameStartsWith,
Collection<String> nameDoesNotStartWith) {
this.nameIsEqualTo = unmodifiableCollection(new ArrayList<>(nameIsEqualTo));
this.nameIsNotEqualTo = unmodifiableCollection(new ArrayList<>(nameIsNotEqualTo));
this.nameStartsWith = unmodifiableCollection(new ArrayList<>(nameStartsWith));
this.nameDoesNotStartWith = unmodifiableCollection(new ArrayList<>(nameDoesNotStartWith));
this.nameIsEqualTo = unmodifiableCollection(new LinkedHashSet<>(nameIsEqualTo));
this.nameIsNotEqualTo = unmodifiableCollection(new LinkedHashSet<>(nameIsNotEqualTo));
this.nameStartsWith = unmodifiableCollection(new LinkedHashSet<>(nameStartsWith));
this.nameDoesNotStartWith = unmodifiableCollection(new LinkedHashSet<>(nameDoesNotStartWith));
}

@Override
Expand All @@ -44,6 +45,9 @@ private boolean matchesNameEqualTo(String metricName) {
if (nameIsEqualTo.isEmpty()) {
return true;
}
if (nameIsEqualTo.contains(metricName)) {
return true;
}
for (String name : nameIsEqualTo) {
// The following ignores suffixes like _total.
// "request_count" and "request_count_total" both match a metric named "request_count".
Expand All @@ -58,6 +62,9 @@ private boolean matchesNameNotEqualTo(String metricName) {
if (nameIsNotEqualTo.isEmpty()) {
return false;
}
if (nameIsNotEqualTo.contains(metricName)) {
return true;
}
for (String name : nameIsNotEqualTo) {
// The following ignores suffixes like _total.
// "request_count" and "request_count_total" both match a metric named "request_count".
Expand Down