Skip to content

Commit 3565ba5

Browse files
authored
Merge pull request github#5209 from smowton/smowton/feature/commons-misc-text
Java: add models for miscellaneous text-processing utilities from Commons Lang
2 parents d17246c + 71cd329 commit 3565ba5

File tree

22 files changed

+1477
-3
lines changed

22 files changed

+1477
-3
lines changed
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
lgtm,codescanning
2+
* Added models for the Apache Commons Lang (and Commons Text) classes WordUtils, StrTokenizer, StrLookup and StrSubstitutor. This may result in extra results for a wide array of queries where any of these text-processing classes are used.

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ private import internal.DataFlowPrivate
7070
*/
7171
private module Frameworks {
7272
private import semmle.code.java.frameworks.ApacheHttp
73+
private import semmle.code.java.frameworks.apache.Lang
7374
}
7475

7576
private predicate sourceModelCsv(string row) {
@@ -409,21 +410,27 @@ private predicate outputNeedsReference(string c) {
409410
private predicate sourceElementRef(Top ref, string output, string kind) {
410411
exists(Element e |
411412
sourceElement(e, output, kind) and
412-
if outputNeedsReference(getLast(output)) then ref.(Call).getCallee() = e else ref = e
413+
if outputNeedsReference(getLast(output))
414+
then ref.(Call).getCallee().getSourceDeclaration() = e
415+
else ref = e
413416
)
414417
}
415418

416419
private predicate sinkElementRef(Top ref, string input, string kind) {
417420
exists(Element e |
418421
sinkElement(e, input, kind) and
419-
if inputNeedsReference(getLast(input)) then ref.(Call).getCallee() = e else ref = e
422+
if inputNeedsReference(getLast(input))
423+
then ref.(Call).getCallee().getSourceDeclaration() = e
424+
else ref = e
420425
)
421426
}
422427

423428
private predicate summaryElementRef(Top ref, string input, string output, string kind) {
424429
exists(Element e |
425430
summaryElement(e, input, output, kind) and
426-
if inputNeedsReference(getLast(input)) then ref.(Call).getCallee() = e else ref = e
431+
if inputNeedsReference(getLast(input))
432+
then ref.(Call).getCallee().getSourceDeclaration() = e
433+
else ref = e
427434
)
428435
}
429436

java/ql/src/semmle/code/java/frameworks/apache/Lang.qll

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java
44
private import semmle.code.java.dataflow.FlowSteps
5+
private import semmle.code.java.dataflow.ExternalFlow
56

67
/**
78
* The class `org.apache.commons.lang.RandomStringUtils` or `org.apache.commons.lang3.RandomStringUtils`.
@@ -211,3 +212,167 @@ private class ApacheStrBuilderTaintWriter extends ApacheStrBuilderCallable, Tain
211212
toArg = 2
212213
}
213214
}
215+
216+
/**
217+
* Taint-propagating models for `WordUtils`.
218+
*/
219+
private class ApacheWordUtilsModel extends SummaryModelCsv {
220+
override predicate row(string row) {
221+
row =
222+
[
223+
"org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
224+
"org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
225+
"org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
226+
"org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument;ReturnValue;taint",
227+
"org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
228+
"org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument;ReturnValue;taint",
229+
"org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument;ReturnValue;taint",
230+
"org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
231+
"org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument;ReturnValue;taint",
232+
"org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
233+
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument;ReturnValue;taint",
234+
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
235+
"org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
236+
"org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
237+
"org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
238+
"org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument;ReturnValue;taint",
239+
"org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
240+
"org.apache.commons.text;WordUtils;false;swapCase;;;Argument;ReturnValue;taint",
241+
"org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument;ReturnValue;taint",
242+
"org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
243+
"org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
244+
"org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
245+
"org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument;ReturnValue;taint",
246+
"org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
247+
"org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument;ReturnValue;taint",
248+
"org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
249+
]
250+
}
251+
}
252+
253+
/**
254+
* Taint-propagating models for `StrTokenizer`.
255+
*/
256+
private class ApacheStrTokenizerModel extends SummaryModelCsv {
257+
override predicate row(string row) {
258+
row =
259+
[
260+
"org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];ReturnValue;taint",
261+
"org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
262+
"org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
263+
"org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument;ReturnValue;taint",
264+
"org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument;Argument[-1];taint",
265+
"org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
266+
"org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
267+
"org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
268+
"org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
269+
"org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
270+
"org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
271+
"org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
272+
"org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument;ReturnValue;taint",
273+
"org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument;ReturnValue;taint",
274+
"org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];ReturnValue;taint",
275+
"org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
276+
"org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
277+
"org.apache.commons.text;StrTokenizer;false;reset;;;Argument;ReturnValue;taint",
278+
"org.apache.commons.text;StrTokenizer;false;reset;;;Argument;Argument[-1];taint",
279+
"org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
280+
"org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
281+
"org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
282+
"org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
283+
"org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
284+
"org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
285+
"org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
286+
"org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument;ReturnValue;taint",
287+
"org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument;ReturnValue;taint",
288+
"org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];ReturnValue;taint",
289+
"org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
290+
"org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
291+
"org.apache.commons.text;StringTokenizer;false;reset;;;Argument;ReturnValue;taint",
292+
"org.apache.commons.text;StringTokenizer;false;reset;;;Argument;Argument[-1];taint",
293+
"org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
294+
"org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
295+
"org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
296+
"org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
297+
"org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
298+
"org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
299+
"org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
300+
"org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument;ReturnValue;taint",
301+
"org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument;ReturnValue;taint"
302+
]
303+
}
304+
}
305+
306+
/**
307+
* Taint-propagating models for `StrLookup`.
308+
*/
309+
private class ApacheStrLookupModel extends SummaryModelCsv {
310+
override predicate row(string row) {
311+
row =
312+
[
313+
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
314+
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;Argument;ReturnValue;taint",
315+
"org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
316+
"org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;Argument;ReturnValue;taint"
317+
]
318+
}
319+
}
320+
321+
/**
322+
* Taint-propagating models for `StrSubstitutor`.
323+
*/
324+
private class ApacheStrSubstitutorModel extends SummaryModelCsv {
325+
override predicate row(string row) {
326+
row =
327+
[
328+
"org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];ReturnValue;taint",
329+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
330+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument;ReturnValue;taint",
331+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument;ReturnValue;taint",
332+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
333+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument;ReturnValue;taint",
334+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
335+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument;ReturnValue;taint",
336+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument;ReturnValue;taint",
337+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument;ReturnValue;taint",
338+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
339+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
340+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
341+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument;ReturnValue;taint",
342+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
343+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[1];ReturnValue;taint",
344+
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument;ReturnValue;taint",
345+
"org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument;Argument[-1];taint",
346+
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument;taint",
347+
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument;taint",
348+
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
349+
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument;taint",
350+
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
351+
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
352+
"org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];ReturnValue;taint",
353+
"org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
354+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument;ReturnValue;taint",
355+
"org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument;ReturnValue;taint",
356+
"org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
357+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument;ReturnValue;taint",
358+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
359+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument;ReturnValue;taint",
360+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument;ReturnValue;taint",
361+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
362+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
363+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument;ReturnValue;taint",
364+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
365+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[1];ReturnValue;taint",
366+
"org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument;ReturnValue;taint",
367+
"org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument;ReturnValue;taint",
368+
"org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
369+
"org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument;Argument[-1];taint",
370+
"org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument;taint",
371+
"org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
372+
"org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument;taint",
373+
"org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
374+
"org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument;taint",
375+
"org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
376+
]
377+
}
378+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import org.apache.commons.lang3.text.StrLookup;
2+
import java.util.HashMap;
3+
import java.util.Map;
4+
5+
class StrLookupTest {
6+
String taint() { return "tainted"; }
7+
8+
void sink(Object o) {}
9+
10+
void test() throws Exception {
11+
Map<String, String> map = new HashMap<String, String>();
12+
map.put("key", taint());
13+
StrLookup<String> lookup = StrLookup.mapLookup(map);
14+
sink(lookup.lookup("key")); // $hasTaintFlow=y
15+
}
16+
17+
}

0 commit comments

Comments
 (0)