Add tests for Spring validation.Errors

This commit is contained in:
Sauyon Lee
2021-06-29 05:38:07 -07:00
parent b76f761e56
commit 52b24118b3
5 changed files with 131 additions and 72 deletions

View File

@@ -1,72 +0,0 @@
import org.springframework.validation.Errors;
class ValidationErrorsTest {
String taint() { return "tainted"; }
Errors taintErrs() { return null; }
Errors errors() { return null; }
void sink(Object o) {}
void test() {
Errors es0 = errors();
es0.addAllErrors(taintErrs());
sink(es0); // $hasTaintFlow
sink(taintErrs().getAllErrors()); // $hasTaintFlow
sink(taintErrs().getFieldError()); // $hasTaintFlow
sink(taintErrs().getFieldError("field")); // $hasTaintFlow
sink(taintErrs().getGlobalError()); // $hasTaintFlow
sink(taintErrs().getGlobalErrors()); // $hasTaintFlow
Errors es1 = errors();
es1.reject(taint());
sink(es1); // $hasTaintFlow
Errors es2 = errors();
es2.reject(taint(), null, "");
sink(es2); // $hasTaintFlow
Errors es3 = errors();
es3.reject(taint(), new Object[]{}, "");
sink(es3); // $hasTaintFlow
Errors es4 = errors();
es4.reject("", new Object[]{taint()}, "");
sink(es4); // $hasTaintFlow
Errors es5 = errors();
es5.reject("", new Object[]{}, taint());
sink(es5); // $hasTaintFlow
Errors es6 = errors();
es6.reject(taint(), "");
sink(es6); // $hasTaintFlow
Errors es7 = errors();
es7.reject("", taint());
sink(es7); // $hasTaintFlow
Errors es8 = errors();
es8.rejectValue("", taint(), new Object[]{}, "");
sink(es8); // $hasTaintFlow
Errors es9 = errors();
es9.rejectValue("", "", new Object[]{taint()}, "");
sink(es9); // $hasTaintFlow
Errors es10 = errors();
es10.rejectValue("", "", new Object[]{}, taint());
sink(es10); // $hasTaintFlow
Errors es11 = errors();
es11.rejectValue("", taint(), "");
sink(es11); // $hasTaintFlow
Errors es12 = errors();
es12.rejectValue("", "", taint());
sink(es12); // $hasTaintFlow
}
}

View File

@@ -0,0 +1,78 @@
import org.springframework.validation.Errors;
class ValidationErrorsTest {
Object source() { return null; }
Errors sourceErrs() { return (Errors)source(); }
Errors errors() { return null; }
void sink(Object o) {}
void test() {
Errors es0 = errors();
es0.addAllErrors(sourceErrs());
sink(es0); // $hasTaintFlow
sink(sourceErrs().getAllErrors()); // $hasTaintFlow
sink(sourceErrs().getFieldError()); // $hasTaintFlow
sink(sourceErrs().getFieldError("field")); // $hasTaintFlow
sink(sourceErrs().getGlobalError()); // $hasTaintFlow
sink(sourceErrs().getGlobalErrors()); // $hasTaintFlow
Errors es1 = errors();
es1.reject((String)source());
sink(es1); // $hasTaintFlow
Errors es2 = errors();
es2.reject((String)source(), null, "");
sink(es2); // $hasTaintFlow
Errors es3 = errors();
es3.reject((String)source(), null, "");
sink(es3); // $hasTaintFlow
{
Errors es4 = errors();
Object[] in = { (String)source() };
es4.reject("", in, "");
sink(in); // $hasTaintFlow
}
{
Errors es5 = errors();
es5.reject("", null, (String)source());
sink(es5); // $hasTaintFlow
}
Errors es6 = errors();
es6.reject((String)source(), "");
sink(es6); // $hasTaintFlow
Errors es7 = errors();
es7.reject("", (String)source());
sink(es7); // $hasTaintFlow
Errors es8 = errors();
es8.rejectValue("", (String)source(), null, "");
sink(es8); // $hasTaintFlow
Errors es9 = errors();
Object[] in = {source()};
es9.rejectValue("", "", in, "");
sink(es9); // $hasTaintFlow
Errors es10 = errors();
es10.rejectValue("", "", null, (String)source());
sink(es10); // $hasTaintFlow
Errors es11 = errors();
es11.rejectValue("", (String)source(), "");
sink(es11); // $hasTaintFlow
Errors es12 = errors();
es12.rejectValue("", "", (String)source());
sink(es12); // $hasTaintFlow
}
}

View File

@@ -0,0 +1 @@
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8

View File

@@ -0,0 +1,52 @@
import java
import semmle.code.java.dataflow.DataFlow
import semmle.code.java.dataflow.TaintTracking
import TestUtilities.InlineExpectationsTest
class ValueFlowConf extends DataFlow::Configuration {
ValueFlowConf() { this = "qltest:valueFlowConf" }
override predicate isSource(DataFlow::Node n) {
n.asExpr().(MethodAccess).getMethod().hasName("source")
}
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
}
}
class TaintFlowConf extends TaintTracking::Configuration {
TaintFlowConf() { this = "qltest:taintFlowConf" }
override predicate isSource(DataFlow::Node n) {
n.asExpr().(MethodAccess).getMethod().hasName("source")
}
override predicate isSink(DataFlow::Node n) {
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
}
}
class HasFlowTest extends InlineExpectationsTest {
HasFlowTest() { this = "HasFlowTest" }
override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
override predicate hasActualResult(Location location, string element, string tag, string value) {
tag = "hasValueFlow" and
exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) |
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
or
tag = "hasTaintFlow" and
exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf |
conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink)
|
sink.getLocation() = location and
element = sink.toString() and
value = ""
)
}
}