Skip to content

Commit 064d897

Browse files
authored
Merge pull request github#5046 from MathiasVP/model-more-pure-functions
C++: Model more pure functions
2 parents c9537f2 + 339c4c6 commit 064d897

File tree

1 file changed

+52
-14
lines changed
  • cpp/ql/src/semmle/code/cpp/models/implementations

1 file changed

+52
-14
lines changed

cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
88
SideEffectFunction {
99
PureStrFunction() {
1010
hasGlobalOrStdName([
11-
"atof", "atoi", "atol", "atoll", "strcasestr", "strchnul", "strchr", "strchrnul", "strstr",
12-
"strpbrk", "strcmp", "strcspn", "strncmp", "strrchr", "strspn", "strtod", "strtof",
13-
"strtol", "strtoll", "strtoq", "strtoul"
11+
atoi(), "strcasestr", "strchnul", "strchr", "strchrnul", "strstr", "strpbrk", "strrchr",
12+
"strspn", strtol(), strrev(), strcmp(), strlwr(), strupr()
1413
])
1514
}
1615

@@ -24,11 +23,16 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
2423

2524
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
2625
exists(ParameterIndex i |
27-
input.isParameter(i) and
28-
exists(getParameter(i))
29-
or
30-
input.isParameterDeref(i) and
31-
getParameter(i).getUnspecifiedType() instanceof PointerType
26+
(
27+
input.isParameter(i) and
28+
exists(getParameter(i))
29+
or
30+
input.isParameterDeref(i) and
31+
getParameter(i).getUnspecifiedType() instanceof PointerType
32+
) and
33+
// Functions that end with _l also take a locale argument (always as the last argument),
34+
// and we don't want taint from those arguments.
35+
(not this.getName().matches("%\\_l") or exists(getParameter(i + 1)))
3236
) and
3337
(
3438
output.isReturnValueDeref() and
@@ -60,6 +64,31 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
6064
}
6165
}
6266

67+
private string atoi() { result = ["atof", "atoi", "atol", "atoll"] }
68+
69+
private string strtol() { result = ["strtod", "strtof", "strtol", "strtoll", "strtoq", "strtoul"] }
70+
71+
private string strlwr() {
72+
result = ["_strlwr", "_wcslwr", "_mbslwr", "_strlwr_l", "_wcslwr_l", "_mbslwr_l"]
73+
}
74+
75+
private string strupr() {
76+
result = ["_strupr", "_wcsupr", "_mbsupr", "_strupr_l", "_wcsupr_l", "_mbsupr_l"]
77+
}
78+
79+
private string strrev() { result = ["_strrev", "_wcsrev", "_mbsrev", "_mbsrev_l"] }
80+
81+
private string strcmp() {
82+
// NOTE: `strcoll` doesn't satisfy _all_ the definitions of purity: its behavior depends on
83+
// `LC_COLLATE` (which is set by `setlocale`). Not sure this behavior worth including in the model, so
84+
// for now we interpret the function as being pure.
85+
result =
86+
[
87+
"strcmp", "strcspn", "strncmp", "strcoll", "strverscmp", "_mbsnbcmp", "_mbsnbcmp_l",
88+
"_stricmp"
89+
]
90+
}
91+
6392
/** String standard `strlen` function, and related functions for computing string lengths. */
6493
private class StrLenFunction extends AliasFunction, ArrayFunction, SideEffectFunction {
6594
StrLenFunction() {
@@ -114,19 +143,28 @@ private class PureFunction extends TaintFunction, SideEffectFunction {
114143
/** Pure raw-memory functions. */
115144
private class PureMemFunction extends AliasFunction, ArrayFunction, TaintFunction,
116145
SideEffectFunction {
117-
PureMemFunction() { hasGlobalOrStdName(["memchr", "memrchr", "rawmemchr", "memcmp", "memmem"]) }
146+
PureMemFunction() {
147+
hasGlobalOrStdName([
148+
"memchr", "__builtin_memchr", "memrchr", "rawmemchr", "memcmp", "__builtin_memcmp", "memmem"
149+
]) or
150+
this.hasGlobalName("memfrob")
151+
}
118152

119153
override predicate hasArrayInput(int bufParam) {
120154
getParameter(bufParam).getUnspecifiedType() instanceof PointerType
121155
}
122156

123157
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
124158
exists(ParameterIndex i |
125-
input.isParameter(i) and
126-
exists(getParameter(i))
127-
or
128-
input.isParameterDeref(i) and
129-
getParameter(i).getUnspecifiedType() instanceof PointerType
159+
(
160+
input.isParameter(i) and
161+
exists(getParameter(i))
162+
or
163+
input.isParameterDeref(i) and
164+
getParameter(i).getUnspecifiedType() instanceof PointerType
165+
) and
166+
// `memfrob` should not have taint from the size argument.
167+
(not this.hasGlobalName("memfrob") or i = 0)
130168
) and
131169
(
132170
output.isReturnValueDeref() and

0 commit comments

Comments
 (0)