Skip to content

Commit 3a33985

Browse files
authored
Merge pull request github#5895 from github/sauyon/java/spring
Add models for some Spring pseudo-collections
2 parents 04244b3 + d7bfc2e commit 3a33985

File tree

26 files changed

+1831
-0
lines changed

26 files changed

+1831
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
lgtm,codescanning
2+
* Additional flow steps in the `org.springframework.ui`, and `org.springframework.cache` packages of
3+
the Spring framework have been modelled. This may result in additional results for security
4+
queries on projects using this framework.

java/ql/src/semmle/code/java/dataflow/ExternalFlow.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,10 @@ private module Frameworks {
8585
private import semmle.code.java.frameworks.jackson.JacksonSerializability
8686
private import semmle.code.java.frameworks.JaxWS
8787
private import semmle.code.java.frameworks.Optional
88+
private import semmle.code.java.frameworks.spring.SpringCache
8889
private import semmle.code.java.frameworks.spring.SpringHttp
8990
private import semmle.code.java.frameworks.spring.SpringUtil
91+
private import semmle.code.java.frameworks.spring.SpringUi
9092
private import semmle.code.java.frameworks.spring.SpringValidation
9193
private import semmle.code.java.frameworks.spring.SpringWebClient
9294
private import semmle.code.java.frameworks.spring.SpringBeans

java/ql/src/semmle/code/java/frameworks/spring/Spring.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import semmle.code.java.frameworks.spring.SpringBean
88
import semmle.code.java.frameworks.spring.SpringBeanFile
99
import semmle.code.java.frameworks.spring.SpringBeans
1010
import semmle.code.java.frameworks.spring.SpringBeanRefType
11+
import semmle.code.java.frameworks.spring.SpringCache
1112
import semmle.code.java.frameworks.spring.SpringComponentScan
1213
import semmle.code.java.frameworks.spring.SpringConstructorArg
1314
import semmle.code.java.frameworks.spring.SpringController
@@ -33,6 +34,7 @@ import semmle.code.java.frameworks.spring.SpringQualifier
3334
import semmle.code.java.frameworks.spring.SpringRef
3435
import semmle.code.java.frameworks.spring.SpringReplacedMethod
3536
import semmle.code.java.frameworks.spring.SpringSet
37+
import semmle.code.java.frameworks.spring.SpringUi
3638
import semmle.code.java.frameworks.spring.SpringUtil
3739
import semmle.code.java.frameworks.spring.SpringValidation
3840
import semmle.code.java.frameworks.spring.SpringValue
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/**
2+
* Provides models for the `org.springframework.cache` package.
3+
*/
4+
5+
import java
6+
private import semmle.code.java.dataflow.ExternalFlow
7+
8+
private class FlowSummaries extends SummaryModelCsv {
9+
override predicate row(string row) {
10+
row =
11+
[
12+
"org.springframework.cache;Cache$ValueRetrievalException;false;ValueRetrievalException;;;Argument[0];MapKey of Argument[-1];value",
13+
"org.springframework.cache;Cache$ValueRetrievalException;false;getKey;;;MapKey of Argument[-1];ReturnValue;value",
14+
"org.springframework.cache;Cache$ValueWrapper;true;get;;;MapValue of Argument[-1];ReturnValue;value",
15+
"org.springframework.cache;Cache;true;get;(Object);;MapValue of Argument[-1];MapValue of ReturnValue;value",
16+
"org.springframework.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[-1];ReturnValue;value",
17+
"org.springframework.cache;Cache;true;get;(Object,Class);;MapValue of Argument[-1];ReturnValue;value",
18+
"org.springframework.cache;Cache;true;getNativeCache;;;MapKey of Argument[-1];MapKey of ReturnValue;value",
19+
"org.springframework.cache;Cache;true;getNativeCache;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
20+
"org.springframework.cache;Cache;true;put;;;Argument[0];MapKey of Argument[-1];value",
21+
"org.springframework.cache;Cache;true;put;;;Argument[1];MapValue of Argument[-1];value",
22+
"org.springframework.cache;Cache;true;putIfAbsent;;;Argument[0];MapKey of Argument[-1];value",
23+
"org.springframework.cache;Cache;true;putIfAbsent;;;Argument[1];MapValue of Argument[-1];value",
24+
"org.springframework.cache;Cache;true;putIfAbsent;;;MapValue of Argument[-1];MapValue of ReturnValue;value"
25+
]
26+
}
27+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Provides models for the `org.springframework.ui` package.
3+
*/
4+
5+
import java
6+
private import semmle.code.java.dataflow.ExternalFlow
7+
8+
private class FlowSummaries extends SummaryModelCsv {
9+
override predicate row(string row) {
10+
row =
11+
[
12+
"org.springframework.ui;Model;true;addAllAttributes;;;Argument[-1];ReturnValue;value",
13+
"org.springframework.ui;Model;true;addAllAttributes;(Collection);;Element of Argument[0];MapValue of Argument[-1];value",
14+
"org.springframework.ui;Model;true;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
15+
"org.springframework.ui;Model;true;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
16+
"org.springframework.ui;Model;true;addAttribute;;;Argument[-1];ReturnValue;value",
17+
"org.springframework.ui;Model;true;addAttribute;(Object);;Argument[0];MapValue of Argument[-1];value",
18+
"org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[0];MapKey of Argument[-1];value",
19+
"org.springframework.ui;Model;true;addAttribute;(String,Object);;Argument[1];MapValue of Argument[-1];value",
20+
"org.springframework.ui;Model;true;asMap;;;MapKey of Argument[-1];MapKey of ReturnValue;value",
21+
"org.springframework.ui;Model;true;asMap;;;MapValue of Argument[-1];MapValue of ReturnValue;value",
22+
"org.springframework.ui;Model;true;getAttribute;;;MapValue of Argument[-1];ReturnValue;value",
23+
"org.springframework.ui;Model;true;mergeAttributes;;;Argument[-1];ReturnValue;value",
24+
"org.springframework.ui;Model;true;mergeAttributes;;;MapKey of Argument[0];MapKey of Argument[-1];value",
25+
"org.springframework.ui;Model;true;mergeAttributes;;;MapValue of Argument[0];MapValue of Argument[-1];value",
26+
"org.springframework.ui;ModelMap;false;ModelMap;(Object);;Argument[0];MapValue of Argument[-1];value",
27+
"org.springframework.ui;ModelMap;false;ModelMap;(String,Object);;Argument[0];MapKey of Argument[-1];value",
28+
"org.springframework.ui;ModelMap;false;ModelMap;(String,Object);;Argument[1];MapValue of Argument[-1];value",
29+
"org.springframework.ui;ModelMap;false;addAllAttributes;;;Argument[-1];ReturnValue;value",
30+
"org.springframework.ui;ModelMap;false;addAllAttributes;(Collection);;Element of Argument[0];MapValue of Argument[-1];value",
31+
"org.springframework.ui;ModelMap;false;addAllAttributes;(Map);;MapKey of Argument[0];MapKey of Argument[-1];value",
32+
"org.springframework.ui;ModelMap;false;addAllAttributes;(Map);;MapValue of Argument[0];MapValue of Argument[-1];value",
33+
"org.springframework.ui;ModelMap;false;addAttribute;;;Argument[-1];ReturnValue;value",
34+
"org.springframework.ui;ModelMap;false;addAttribute;(Object);;Argument[0];MapValue of Argument[-1];value",
35+
"org.springframework.ui;ModelMap;false;addAttribute;(String,Object);;Argument[0];MapKey of Argument[-1];value",
36+
"org.springframework.ui;ModelMap;false;addAttribute;(String,Object);;Argument[1];MapValue of Argument[-1];value",
37+
"org.springframework.ui;ModelMap;false;getAttribute;;;MapValue of Argument[-1];ReturnValue;value",
38+
"org.springframework.ui;ModelMap;false;mergeAttributes;;;Argument[-1];ReturnValue;value",
39+
"org.springframework.ui;ModelMap;false;mergeAttributes;;;MapKey of Argument[0];MapKey of Argument[-1];value",
40+
"org.springframework.ui;ModelMap;false;mergeAttributes;;;MapValue of Argument[0];MapValue of Argument[-1];value",
41+
"org.springframework.ui;ConcurrentModel;false;ConcurrentModel;(Object);;Argument[0];MapValue of Argument[-1];value",
42+
"org.springframework.ui;ConcurrentModel;false;ConcurrentModel;(String,Object);;Argument[0];MapKey of Argument[-1];value",
43+
"org.springframework.ui;ConcurrentModel;false;ConcurrentModel;(String,Object);;Argument[1];MapValue of Argument[-1];value"
44+
]
45+
}
46+
}
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
package generatedtest;
2+
3+
import java.util.Map;
4+
import java.util.HashMap;
5+
import java.util.concurrent.Callable;
6+
import org.springframework.cache.Cache;
7+
8+
9+
// Test case generated by GenerateFlowTestCase.ql
10+
public class Test {
11+
12+
public class ValueWrapper extends HashMap<Object,Object> implements Cache.ValueWrapper {
13+
ValueWrapper(Object element) {
14+
super();
15+
this.put(null, element);
16+
}
17+
18+
public Object get() { return this.get(null); }
19+
}
20+
21+
public class DummyCache implements Cache {
22+
DummyCache(Object key, Object value) {
23+
this.put(key, value);
24+
}
25+
26+
public void clear() {}
27+
public void evict(Object key) {}
28+
public boolean evictIfPresent(Object key) { return false; }
29+
public Cache.ValueWrapper get(Object key) { return null; }
30+
public <T> T get(Object key, Callable<T> valueLoader) { return null; }
31+
public <T> T get(Object key, Class<T> type) { return null; }
32+
public String getName() { return null; }
33+
public Object getNativeCache() { return null; }
34+
//public default boolean invalidate() { return false; }
35+
public void put(Object key, Object value) {}
36+
//default Cache.ValueWrapper putIfAbsent(Object key, Object value) { return null; }
37+
}
38+
39+
Object getMapKey(Cache.ValueRetrievalException container) { return container.getKey(); }
40+
Object getMapKey(Cache container) { return ((Map)container.getNativeCache()).keySet().iterator().next(); }
41+
Object getMapValue(Cache container) { return container.get(null, (Class)null); }
42+
Object getMapValue(Cache.ValueWrapper container) { return container.get(); }
43+
Object source() { return null; }
44+
void sink(Object o) { }
45+
46+
public void test() {
47+
48+
{
49+
// "org.springframework.cache;Cache$ValueRetrievalException;false;ValueRetrievalException;;;Argument[0];MapKey of Argument[-1];value"
50+
Cache.ValueRetrievalException out = null;
51+
Object in = source();
52+
out = new Cache.ValueRetrievalException(in, null, null);
53+
sink(getMapKey(out)); // $hasValueFlow
54+
}
55+
{
56+
// "org.springframework.cache;Cache$ValueRetrievalException;false;getKey;;;MapKey of Argument[-1];ReturnValue;value"
57+
Object out = null;
58+
Cache.ValueRetrievalException in = new Cache.ValueRetrievalException(source(), null, null);
59+
out = in.getKey();
60+
sink(out); // $hasValueFlow
61+
}
62+
{
63+
// "org.springframework.cache;Cache$ValueWrapper;true;get;;;MapValue of Argument[-1];ReturnValue;value"
64+
Object out = null;
65+
Cache.ValueWrapper in = new ValueWrapper(source());
66+
out = in.get();
67+
sink(out); // $hasValueFlow
68+
}
69+
{
70+
// "org.springframework.cache;Cache;true;get;(Object);;MapValue of Argument[-1];MapValue of ReturnValue;value"
71+
Cache.ValueWrapper out = null;
72+
Cache in = new DummyCache(null, source());
73+
out = in.get(null);
74+
sink(getMapValue(out)); // $hasValueFlow
75+
}
76+
{
77+
// "org.springframework.cache;Cache;true;get;(Object,Callable);;MapValue of Argument[-1];ReturnValue;value"
78+
Object out = null;
79+
Cache in = new DummyCache(null, source());
80+
out = in.get(null, (Callable)null);
81+
sink(out); // $hasValueFlow
82+
}
83+
{
84+
// "org.springframework.cache;Cache;true;get;(Object,Class);;MapValue of Argument[-1];ReturnValue;value"
85+
Object out = null;
86+
Cache in = new DummyCache(null, source());
87+
out = in.get(null, (Class)null);
88+
sink(out); // $hasValueFlow
89+
}
90+
{
91+
// "org.springframework.cache;Cache;true;getNativeCache;;;MapKey of Argument[-1];MapKey of ReturnValue;value"
92+
Object out = null;
93+
Cache in = new DummyCache(source(), null);
94+
out = in.getNativeCache();
95+
sink(getMapKey((Cache)out)); // $hasValueFlow
96+
}
97+
{
98+
// "org.springframework.cache;Cache;true;getNativeCache;;;MapValue of Argument[-1];MapValue of ReturnValue;value"
99+
Object out = null;
100+
Cache in = new DummyCache(null, source());
101+
out = in.getNativeCache();
102+
sink(getMapValue((Cache)out)); // $hasValueFlow
103+
}
104+
{
105+
// "org.springframework.cache;Cache;true;put;;;Argument[0];MapKey of Argument[-1];value"
106+
Cache out = null;
107+
Object in = source();
108+
out.put(in, null);
109+
sink(getMapKey(out)); // $hasValueFlow
110+
}
111+
{
112+
// "org.springframework.cache;Cache;true;put;;;Argument[1];MapValue of Argument[-1];value"
113+
Cache out = null;
114+
Object in = source();
115+
out.put(null, in);
116+
sink(getMapValue(out)); // $hasValueFlow
117+
}
118+
{
119+
// "org.springframework.cache;Cache;true;putIfAbsent;;;Argument[0];MapKey of Argument[-1];value"
120+
Cache out = null;
121+
Object in = source();
122+
out.putIfAbsent(in, null);
123+
sink(getMapKey(out)); // $hasValueFlow
124+
}
125+
{
126+
// "org.springframework.cache;Cache;true;putIfAbsent;;;Argument[1];MapValue of Argument[-1];value"
127+
Cache out = null;
128+
Object in = source();
129+
out.putIfAbsent(null, in);
130+
sink(getMapValue(out)); // $hasValueFlow
131+
}
132+
{
133+
// "org.springframework.cache;Cache;true;putIfAbsent;;;MapValue of Argument[-1];MapValue of ReturnValue;value"
134+
Cache.ValueWrapper out = null;
135+
Cache in = new DummyCache(null, source());
136+
out = in.putIfAbsent(null, null);
137+
sink(getMapValue(out)); // $hasValueFlow
138+
}
139+
140+
}
141+
142+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/springframework-5.3.8

java/ql/test/library-tests/frameworks/spring/cache/test.expected

Whitespace-only changes.
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import java
2+
import semmle.code.java.dataflow.DataFlow
3+
import semmle.code.java.dataflow.TaintTracking
4+
import TestUtilities.InlineExpectationsTest
5+
6+
class ValueFlowConf extends DataFlow::Configuration {
7+
ValueFlowConf() { this = "qltest:valueFlowConf" }
8+
9+
override predicate isSource(DataFlow::Node n) {
10+
n.asExpr().(MethodAccess).getMethod().hasName("source")
11+
}
12+
13+
override predicate isSink(DataFlow::Node n) {
14+
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
15+
}
16+
}
17+
18+
class TaintFlowConf extends TaintTracking::Configuration {
19+
TaintFlowConf() { this = "qltest:taintFlowConf" }
20+
21+
override predicate isSource(DataFlow::Node n) {
22+
n.asExpr().(MethodAccess).getMethod().hasName("source")
23+
}
24+
25+
override predicate isSink(DataFlow::Node n) {
26+
n.asExpr().(Argument).getCall().getCallee().hasName("sink")
27+
}
28+
}
29+
30+
class HasFlowTest extends InlineExpectationsTest {
31+
HasFlowTest() { this = "HasFlowTest" }
32+
33+
override string getARelevantTag() { result = ["hasValueFlow", "hasTaintFlow"] }
34+
35+
override predicate hasActualResult(Location location, string element, string tag, string value) {
36+
tag = "hasValueFlow" and
37+
exists(DataFlow::Node src, DataFlow::Node sink, ValueFlowConf conf | conf.hasFlow(src, sink) |
38+
sink.getLocation() = location and
39+
element = sink.toString() and
40+
value = ""
41+
)
42+
or
43+
tag = "hasTaintFlow" and
44+
exists(DataFlow::Node src, DataFlow::Node sink, TaintFlowConf conf |
45+
conf.hasFlow(src, sink) and not any(ValueFlowConf c).hasFlow(src, sink)
46+
|
47+
sink.getLocation() = location and
48+
element = sink.toString() and
49+
value = ""
50+
)
51+
}
52+
}

0 commit comments

Comments
 (0)