Skip to content

Commit 94a0420

Browse files
committed
Updated getResultExpr to getResultNode. Added strlcat. Added tests.
1 parent 4919c4a commit 94a0420

File tree

6 files changed

+815
-9
lines changed

6 files changed

+815
-9
lines changed

cpp/ql/lib/semmle/code/cpp/commons/StringConcatenation.qll

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,16 @@
55
import cpp
66
import semmle.code.cpp.models.implementations.Strcat
77
import semmle.code.cpp.models.interfaces.FormattingFunction
8+
import semmle.code.cpp.dataflow.new.DataFlow
89

910
class StringConcatenation extends Call {
1011
StringConcatenation() {
11-
// printf-like functions, i.e., concat through formating
12+
// sprintf-like functions, i.e., concat through formating
1213
exists(FormattingFunctionCall fc | this = fc)
1314
or
14-
// strcat variants
15-
exists(StrcatFunction f | this.getTarget() = f)
15+
this.getTarget() instanceof StrcatFunction
16+
or
17+
this.getTarget() instanceof StrlcatFunction
1618
or
1719
// operator+ concat
1820
exists(Call call, Operator op |
@@ -35,7 +37,9 @@ class StringConcatenation extends Call {
3537
Expr getAnOperand() {
3638
// The result is an argument of 'this' (a call)
3739
result = this.getAnArgument() and
38-
not result instanceof Call and // addresses odd behavior with overloaded operators
40+
// addresses odd behavior with overloaded operators
41+
// i.e., "call to operator+" appearing as an operand
42+
not result instanceof Call and
3943
// Limit the result type to string
4044
(
4145
result.getUnderlyingType().stripType().getName() = "char"
@@ -69,11 +73,26 @@ class StringConcatenation extends Call {
6973
}
7074

7175
/**
72-
* Gets the expression representing the concatenation result.
76+
* Gets the data flow node representing the concatenation result.
7377
*/
74-
Expr getResultExpr() {
75-
if this instanceof FormattingFunctionCall
76-
then result = this.(FormattingFunctionCall).getOutputArgument(_)
77-
else result = this.(Call)
78+
DataFlow::Node getResultNode() {
79+
if this.getTarget() instanceof StrcatFunction
80+
then
81+
result.asDefiningArgument() =
82+
this.getArgument(this.getTarget().(StrcatFunction).getParamDest())
83+
or
84+
// Hardcoding it is also the return
85+
[result.asExpr(), result.asIndirectExpr()] = this.(Call)
86+
else
87+
if this.getTarget() instanceof StrlcatFunction
88+
then (
89+
[result.asExpr(), result.asIndirectExpr()] =
90+
this.getArgument(this.getTarget().(StrlcatFunction).getParamDest())
91+
) else
92+
if this instanceof FormattingFunctionCall
93+
then
94+
[result.asExpr(), result.asIndirectExpr()] =
95+
this.(FormattingFunctionCall).getOutputArgument(_)
96+
else [result.asExpr(), result.asIndirectExpr()] = this.(Call)
7897
}
7998
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// #include <iostream>
2+
// #include <string>
3+
// #include <stdio.h>
4+
// #include <string.h>
5+
// #include <sstream>
6+
#include "stl.h"
7+
8+
int sprintf(char *s, const char *format, ...);
9+
char *strcat(char * s1, const char * s2);
10+
11+
using namespace std;
12+
13+
14+
void test1(){
15+
string str1 = "Hello";
16+
string str2 = "World";
17+
string str3 = "!";
18+
string str4 = "Concatenation";
19+
string str5 = "is";
20+
string str6 = "fun";
21+
22+
// Using the + operator
23+
string result1 = str1 + " " + str2 + str3;
24+
25+
// Using the append() function
26+
//----TODO: currently not modeled----
27+
// string result2 = str4.append(" ") + str5.append(" ") + str6;
28+
29+
// Using the insert() function
30+
//----TODO: currently not modeled----
31+
// string result3 = str1.insert(5, " ") + str2.insert(5, "! ");
32+
33+
// Using the replace() function
34+
//----TODO: currently not modeled----
35+
// string result4 = str1.replace(0, 5, "Hi") + str2.replace(0, 5, "There");
36+
37+
// Using the push_back() function
38+
//----TODO: currently not modeled----
39+
// string result5;
40+
// for (char c : str1) {
41+
// result5.push_back(c);
42+
// }
43+
44+
// Using the stream operator
45+
string result6;
46+
std::stringstream ss;
47+
ss << str1 << " " << str2 << str3;
48+
}
49+
50+
51+
void test2(char* ucstr) {
52+
char str1[20] = "Hello";
53+
char str2[20] = "World";
54+
char result[40];
55+
char *result2;
56+
57+
// Using sprintf
58+
sprintf(result, "%s %s %s", str1, str2, ucstr);
59+
60+
// Using strcat
61+
strcat(str1, ucstr);
62+
}

0 commit comments

Comments
 (0)