Skip to content

Commit 3a27442

Browse files
committed
Convert fluent method models to csv and generalise to the three different variants of StrBuilder.
1 parent 851317e commit 3a27442

File tree

4 files changed

+300
-0
lines changed

4 files changed

+300
-0
lines changed

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

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,92 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
427427
}
428428
}
429429

430+
private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
431+
override predicate row(string row) {
432+
row =
433+
[
434+
"org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
435+
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
436+
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
437+
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
438+
"org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
439+
"org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
440+
"org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
441+
"org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
442+
"org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
443+
"org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
444+
"org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
445+
"org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
446+
"org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
447+
"org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
448+
"org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
449+
"org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
450+
"org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
451+
"org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
452+
"org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
453+
"org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
454+
"org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
455+
"org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
456+
"org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
457+
"org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
458+
"org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
459+
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
460+
"org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
461+
"org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
462+
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
463+
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
464+
"org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
465+
"org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
466+
"org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
467+
"org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
468+
"org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
469+
"org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
470+
"org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
471+
"org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
472+
"org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
473+
"org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
474+
"org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
475+
"org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
476+
"org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
477+
"org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
478+
"org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
479+
"org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
480+
"org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
481+
"org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
482+
"org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
483+
"org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
484+
"org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
485+
"org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
486+
"org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
487+
"org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
488+
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
489+
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
490+
"org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
491+
"org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
492+
"org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
493+
"org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
494+
"org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
495+
"org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
496+
"org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
497+
"org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
498+
"org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
499+
"org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
500+
"org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
501+
"org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
502+
"org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
503+
"org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
504+
"org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
505+
"org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
506+
"org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
507+
"org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
508+
"org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
509+
"org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
510+
"org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
511+
"org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
512+
]
513+
}
514+
}
515+
430516
/**
431517
* An Apache Commons-Lang StrBuilder method that returns `this`.
432518
*/

java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTest.java

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,68 @@ void test() throws Exception {
142142
StrBuilder fluentBackflowTest2 = new StrBuilder();
143143
fluentBackflowTest2.append("Harmless").append(taint());
144144
sink(fluentBackflowTest2.toString()); // $hasTaintFlow
145+
146+
// Test all fluent methods are passing taint through to their result:
147+
StrBuilder fluentAllMethodsTest = new StrBuilder(taint());
148+
sink(fluentAllMethodsTest // $hasTaintFlow
149+
.append("text")
150+
.appendAll("text")
151+
.appendFixedWidthPadLeft("text", 4, ' ')
152+
.appendFixedWidthPadRight("text", 4, ' ')
153+
.appendln("text")
154+
.appendNewLine()
155+
.appendNull()
156+
.appendPadding(0, ' ')
157+
.appendSeparator(',')
158+
.appendWithSeparators(new String[] { }, ",")
159+
.delete(0, 0)
160+
.deleteAll(' ')
161+
.deleteCharAt(0)
162+
.deleteFirst("delme")
163+
.ensureCapacity(100)
164+
.insert(1, "insertme")
165+
.minimizeCapacity()
166+
.replace(0, 0, "replacement")
167+
.replaceAll("find", "replace")
168+
.replaceFirst("find", "replace")
169+
.reverse()
170+
.setCharAt(0, 'a')
171+
.setLength(500)
172+
.setNewLineText("newline")
173+
.setNullText("NULL")
174+
.trim());
175+
176+
// Test all fluent methods are passing taint back to their qualifier:
177+
StrBuilder fluentAllMethodsTest2 = new StrBuilder();
178+
fluentAllMethodsTest2
179+
.append("text")
180+
.appendAll("text")
181+
.appendFixedWidthPadLeft("text", 4, ' ')
182+
.appendFixedWidthPadRight("text", 4, ' ')
183+
.appendln("text")
184+
.appendNewLine()
185+
.appendNull()
186+
.appendPadding(0, ' ')
187+
.appendSeparator(',')
188+
.appendWithSeparators(new String[] { }, ",")
189+
.delete(0, 0)
190+
.deleteAll(' ')
191+
.deleteCharAt(0)
192+
.deleteFirst("delme")
193+
.ensureCapacity(100)
194+
.insert(1, "insertme")
195+
.minimizeCapacity()
196+
.replace(0, 0, "replacement")
197+
.replaceAll("find", "replace")
198+
.replaceFirst("find", "replace")
199+
.reverse()
200+
.setCharAt(0, 'a')
201+
.setLength(500)
202+
.setNewLineText("newline")
203+
.setNullText("NULL")
204+
.trim()
205+
.append(taint());
206+
sink(fluentAllMethodsTest2); // $hasTaintFlow
145207
}
146208

147209
}

java/ql/test/library-tests/frameworks/apache-commons-lang3/StrBuilderTextTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,82 @@ void test() throws Exception {
128128
StrBuilder sb72 = new StrBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $hasTaintFlow
129129
StrBuilder sb73 = new StrBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $hasTaintFlow
130130
StrBuilder sb74 = new StrBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $hasTaintFlow
131+
132+
// Tests for fluent methods (those returning `this`):
133+
134+
StrBuilder fluentTest = new StrBuilder();
135+
sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $hasTaintFlow
136+
137+
StrBuilder fluentBackflowTest = new StrBuilder();
138+
fluentBackflowTest.append("Harmless").append(taint()).append("Also harmless");
139+
sink(fluentBackflowTest.toString()); // $hasTaintFlow
140+
141+
// Test the case where the fluent method contributing taint is at the end of a statement:
142+
StrBuilder fluentBackflowTest2 = new StrBuilder();
143+
fluentBackflowTest2.append("Harmless").append(taint());
144+
sink(fluentBackflowTest2.toString()); // $hasTaintFlow
145+
146+
// Test all fluent methods are passing taint through to their result:
147+
StrBuilder fluentAllMethodsTest = new StrBuilder(taint());
148+
sink(fluentAllMethodsTest // $hasTaintFlow
149+
.append("text")
150+
.appendAll("text")
151+
.appendFixedWidthPadLeft("text", 4, ' ')
152+
.appendFixedWidthPadRight("text", 4, ' ')
153+
.appendln("text")
154+
.appendNewLine()
155+
.appendNull()
156+
.appendPadding(0, ' ')
157+
.appendSeparator(',')
158+
.appendWithSeparators(new String[] { }, ",")
159+
.delete(0, 0)
160+
.deleteAll(' ')
161+
.deleteCharAt(0)
162+
.deleteFirst("delme")
163+
.ensureCapacity(100)
164+
.insert(1, "insertme")
165+
.minimizeCapacity()
166+
.replace(0, 0, "replacement")
167+
.replaceAll("find", "replace")
168+
.replaceFirst("find", "replace")
169+
.reverse()
170+
.setCharAt(0, 'a')
171+
.setLength(500)
172+
.setNewLineText("newline")
173+
.setNullText("NULL")
174+
.trim());
175+
176+
// Test all fluent methods are passing taint back to their qualifier:
177+
StrBuilder fluentAllMethodsTest2 = new StrBuilder();
178+
fluentAllMethodsTest2
179+
.append("text")
180+
.appendAll("text")
181+
.appendFixedWidthPadLeft("text", 4, ' ')
182+
.appendFixedWidthPadRight("text", 4, ' ')
183+
.appendln("text")
184+
.appendNewLine()
185+
.appendNull()
186+
.appendPadding(0, ' ')
187+
.appendSeparator(',')
188+
.appendWithSeparators(new String[] { }, ",")
189+
.delete(0, 0)
190+
.deleteAll(' ')
191+
.deleteCharAt(0)
192+
.deleteFirst("delme")
193+
.ensureCapacity(100)
194+
.insert(1, "insertme")
195+
.minimizeCapacity()
196+
.replace(0, 0, "replacement")
197+
.replaceAll("find", "replace")
198+
.replaceFirst("find", "replace")
199+
.reverse()
200+
.setCharAt(0, 'a')
201+
.setLength(500)
202+
.setNewLineText("newline")
203+
.setNullText("NULL")
204+
.trim()
205+
.append(taint());
206+
sink(fluentAllMethodsTest2); // $hasTaintFlow
131207
}
132208

133209
}

java/ql/test/library-tests/frameworks/apache-commons-lang3/TextStringBuilderTest.java

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,82 @@ void test() throws Exception {
129129
TextStringBuilder sb72 = new TextStringBuilder(); sb72.append(taint()); sink(sb72.toCharArray(0, 0)); // $hasTaintFlow
130130
TextStringBuilder sb73 = new TextStringBuilder(); sb73.append(taint()); sink(sb73.toStringBuffer()); // $hasTaintFlow
131131
TextStringBuilder sb74 = new TextStringBuilder(); sb74.append(taint()); sink(sb74.toStringBuilder()); // $hasTaintFlow
132+
133+
// Tests for fluent methods (those returning `this`):
134+
135+
TextStringBuilder fluentTest = new TextStringBuilder();
136+
sink(fluentTest.append("Harmless").append(taint()).append("Also harmless").toString()); // $hasTaintFlow
137+
138+
TextStringBuilder fluentBackflowTest = new TextStringBuilder();
139+
fluentBackflowTest.append("Harmless").append(taint()).append("Also harmless");
140+
sink(fluentBackflowTest.toString()); // $hasTaintFlow
141+
142+
// Test the case where the fluent method contributing taint is at the end of a statement:
143+
TextStringBuilder fluentBackflowTest2 = new TextStringBuilder();
144+
fluentBackflowTest2.append("Harmless").append(taint());
145+
sink(fluentBackflowTest2.toString()); // $hasTaintFlow
146+
147+
// Test all fluent methods are passing taint through to their result:
148+
TextStringBuilder fluentAllMethodsTest = new TextStringBuilder(taint());
149+
sink(fluentAllMethodsTest // $hasTaintFlow
150+
.append("text")
151+
.appendAll("text")
152+
.appendFixedWidthPadLeft("text", 4, ' ')
153+
.appendFixedWidthPadRight("text", 4, ' ')
154+
.appendln("text")
155+
.appendNewLine()
156+
.appendNull()
157+
.appendPadding(0, ' ')
158+
.appendSeparator(',')
159+
.appendWithSeparators(new String[] { }, ",")
160+
.delete(0, 0)
161+
.deleteAll(' ')
162+
.deleteCharAt(0)
163+
.deleteFirst("delme")
164+
.ensureCapacity(100)
165+
.insert(1, "insertme")
166+
.minimizeCapacity()
167+
.replace(0, 0, "replacement")
168+
.replaceAll("find", "replace")
169+
.replaceFirst("find", "replace")
170+
.reverse()
171+
.setCharAt(0, 'a')
172+
.setLength(500)
173+
.setNewLineText("newline")
174+
.setNullText("NULL")
175+
.trim());
176+
177+
// Test all fluent methods are passing taint back to their qualifier:
178+
TextStringBuilder fluentAllMethodsTest2 = new TextStringBuilder();
179+
fluentAllMethodsTest2
180+
.append("text")
181+
.appendAll("text")
182+
.appendFixedWidthPadLeft("text", 4, ' ')
183+
.appendFixedWidthPadRight("text", 4, ' ')
184+
.appendln("text")
185+
.appendNewLine()
186+
.appendNull()
187+
.appendPadding(0, ' ')
188+
.appendSeparator(',')
189+
.appendWithSeparators(new String[] { }, ",")
190+
.delete(0, 0)
191+
.deleteAll(' ')
192+
.deleteCharAt(0)
193+
.deleteFirst("delme")
194+
.ensureCapacity(100)
195+
.insert(1, "insertme")
196+
.minimizeCapacity()
197+
.replace(0, 0, "replacement")
198+
.replaceAll("find", "replace")
199+
.replaceFirst("find", "replace")
200+
.reverse()
201+
.setCharAt(0, 'a')
202+
.setLength(500)
203+
.setNewLineText("newline")
204+
.setNullText("NULL")
205+
.trim()
206+
.append(taint());
207+
sink(fluentAllMethodsTest2); // $hasTaintFlow
132208
}
133209

134210
}

0 commit comments

Comments
 (0)