Skip to content

Commit 4919c4a

Browse files
committed
Added StringConcatenation.qll
1 parent fefc02d commit 4919c4a

File tree

1 file changed

+79
-0
lines changed

1 file changed

+79
-0
lines changed
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/**
2+
* A library for detecting general string concatenations.
3+
*/
4+
5+
import cpp
6+
import semmle.code.cpp.models.implementations.Strcat
7+
import semmle.code.cpp.models.interfaces.FormattingFunction
8+
9+
class StringConcatenation extends Call {
10+
StringConcatenation() {
11+
// printf-like functions, i.e., concat through formating
12+
exists(FormattingFunctionCall fc | this = fc)
13+
or
14+
// strcat variants
15+
exists(StrcatFunction f | this.getTarget() = f)
16+
or
17+
// operator+ concat
18+
exists(Call call, Operator op |
19+
call.getTarget() = op and
20+
op.hasQualifiedName(["std", "bsl"], "operator+") and
21+
op.getType().(UserType).hasQualifiedName(["std", "bsl"], "basic_string") and
22+
this = call
23+
)
24+
or
25+
// string stream concat (operator<<)
26+
this.getTarget().hasQualifiedName(["std", "bsl"], "operator<<")
27+
}
28+
29+
/**
30+
* Gets the operands of this concatenation (one of the string operands being
31+
* concatenated).
32+
* Will not return out param for sprintf-like functions, but will consider the format string
33+
* to be part of the operands.
34+
*/
35+
Expr getAnOperand() {
36+
// The result is an argument of 'this' (a call)
37+
result = this.getAnArgument() and
38+
not result instanceof Call and // addresses odd behavior with overloaded operators
39+
// Limit the result type to string
40+
(
41+
result.getUnderlyingType().stripType().getName() = "char"
42+
or
43+
result.getUnderlyingType().getName() = "string"
44+
or
45+
result
46+
.getType()
47+
.getUnspecifiedType()
48+
.(UserType)
49+
.hasQualifiedName(["std", "bsl"], "basic_string")
50+
) and
51+
// when 'this' is a `FormattingFunctionCall` the result must be the format string argument
52+
// or one of the formatting arguments
53+
(
54+
this instanceof FormattingFunctionCall
55+
implies
56+
(
57+
result = this.(FormattingFunctionCall).getFormat()
58+
or
59+
exists(int n |
60+
result = this.getArgument(n) and
61+
n >=
62+
this.(FormattingFunctionCall)
63+
.getTarget()
64+
.(FormattingFunction)
65+
.getFirstFormatArgumentIndex()
66+
)
67+
)
68+
)
69+
}
70+
71+
/**
72+
* Gets the expression representing the concatenation result.
73+
*/
74+
Expr getResultExpr() {
75+
if this instanceof FormattingFunctionCall
76+
then result = this.(FormattingFunctionCall).getOutputArgument(_)
77+
else result = this.(Call)
78+
}
79+
}

0 commit comments

Comments
 (0)