Resove taint tracking issues from asMultimap

Signed-off-by: Jonathan Leitschuh <Jonathan.Leitschuh@gmail.com>
This commit is contained in:
Jonathan Leitschuh
2021-10-18 14:21:35 -04:00
parent 5a2bdc9a0f
commit db2892b9ea
4 changed files with 98 additions and 5 deletions

View File

@@ -0,0 +1,70 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import ratpack.core.handling.Context;
import ratpack.core.form.Form;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.List;
import java.util.function.Predicate;
public class CollectionPassingTest {
void sink(Object o) {}
String taint() {
return null;
}
void test_1(Context ctx) {
// Given
ctx
.getRequest()
.getBody()
.map(data -> ctx.parse(data, Form.form()))
.then(form -> {
// When
Map<String, Object> pojoMap = new HashMap<>();
merge(form.asMultimap().asMap(), pojoMap);
// Then
sink(pojoMap.get("value")); //$hasTaintFlow
pojoMap.forEach((key, value) -> {
sink(value); //$hasTaintFlow
List<Object> values = (List<Object>) value;
sink(values.get(0)); //$hasTaintFlow
});
});
}
void test_2() {
// Given
Map<String, Collection<String>> taintedMap = new HashMap<>();
taintedMap.put("value", ImmutableList.of(taint()));
Map<String, Object> pojoMap = new HashMap<>();
// When
merge(taintedMap, pojoMap);
// Then
sink(pojoMap.get("value")); //$hasTaintFlow
pojoMap.forEach((key, value) -> {
sink(value); //$hasTaintFlow
List<Object> values = (List<Object>) value;
sink(values.get(0)); //$hasTaintFlow
});
}
private static void merge(Map<String, Collection<String>> params, Map<String, Object> defaults) {
for(Map.Entry<String, Collection<String>> entry : params.entrySet()) {
String name = entry.getKey();
Collection<String> values = entry.getValue();
defaults.put(name, extractSingleValueIfPossible(values));
}
}
private static Object extractSingleValueIfPossible(Collection<String> values) {
return values.size() == 1 ? values.iterator().next() : ImmutableList.copyOf(values);
}
}

View File

@@ -31,9 +31,15 @@ class IntegrationTest {
static class Pojo {
String value;
List<String> values;
String getValue() {
return value;
}
List<String> getValues() {
return values;
}
}
private final ObjectMapper objectMapper = new ObjectMapper();
@@ -112,6 +118,24 @@ class IntegrationTest {
});
}
void test6(Context ctx) {
bindQuery(ctx, Pojo.class)
.then(pojo -> {
sink(pojo.getValue()); //$hasTaintFlow
sink(pojo.getValues()); //$hasTaintFlow
});
}
public <T> Promise<T> bindQuery(Context ctx, Class<T> type) {
return bindQuery(ctx, type, Action.noop());
}
public <T> Promise<T> bindQuery(Context ctx, Class<T> type, Action<? super ImmutableMap.Builder<String, Object>> defaults) {
return Promise.sync(() ->
bind(ctx, toObjectNode(ctx.getRequest().getQueryParams(), defaults, name -> false), type)
);
}
private <T> Promise<T> bindJson(Context ctx, Class<T> type) {
return ctx.getRequest().getBody()
.map(data -> {
@@ -215,4 +239,4 @@ class IntegrationTest {
// empty
}
}
}
}

View File

@@ -316,6 +316,5 @@ class Resource {
.then(value -> {
sink(value); // no tainted flow
});
}
}
}
}