Skip to content

Commit 1266684

Browse files
committed
C++: Fix conflation in 'Pure' models.
1 parent 503f018 commit 1266684

File tree

1 file changed

+32
-10
lines changed
  • cpp/ql/lib/semmle/code/cpp/models/implementations

1 file changed

+32
-10
lines changed

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

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import semmle.code.cpp.models.interfaces.ArrayFunction
22
import semmle.code.cpp.models.interfaces.Taint
3+
import semmle.code.cpp.models.interfaces.DataFlow
34
import semmle.code.cpp.models.interfaces.Alias
45
import semmle.code.cpp.models.interfaces.SideEffect
56

@@ -8,7 +9,7 @@ import semmle.code.cpp.models.interfaces.SideEffect
89
* guaranteed to be side-effect free.
910
*/
1011
private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction,
11-
SideEffectFunction
12+
SideEffectFunction, DataFlowFunction
1213
{
1314
PureStrFunction() {
1415
this.hasGlobalOrStdOrBslName([
@@ -26,22 +27,43 @@ private class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunctio
2627
}
2728

2829
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
29-
exists(ParameterIndex i |
30+
exists(ParameterIndex i | exists(this.getParameter(i)) |
31+
// For these functions we add taint flow according to the following rules:
32+
// 1. If the parameter is of a pointer type then there is taint from the
33+
// indirection of the parameter. Otherwise, there is taint from the
34+
// parameter.
35+
// 2. If the return value is of a pointer type then there is taint to the
36+
// indirection of the return. Otherwise, there is taint to the return.
3037
(
31-
input.isParameter(i) and
32-
exists(this.getParameter(i))
33-
or
34-
input.isParameterDeref(i) and
35-
this.getParameter(i).getUnspecifiedType() instanceof PointerType
38+
if this.getParameter(i).getUnspecifiedType() instanceof PointerType
39+
then input.isParameterDeref(i)
40+
else input.isParameter(i)
3641
) and
3742
// Functions that end with _l also take a locale argument (always as the last argument),
3843
// and we don't want taint from those arguments.
3944
(not this.getName().matches("%\\_l") or exists(this.getParameter(i + 1)))
4045
) and
4146
(
42-
output.isReturnValueDeref() and
43-
this.getUnspecifiedType() instanceof PointerType
44-
or
47+
if this.getUnspecifiedType() instanceof PointerType
48+
then output.isReturnValueDeref()
49+
else output.isReturnValue()
50+
)
51+
or
52+
// If there is taint flow from *input to *output then there is also taint
53+
// flow from input to output.
54+
this.hasTaintFlow(input.getIndirectionInput(), output.getIndirectionOutput()) and
55+
// no need to add taint-flow if we already have dataflow
56+
not this.hasDataFlow(input, output)
57+
}
58+
59+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
60+
exists(int i |
61+
input.isParameter(i) and
62+
// see the comment in `hasTaintFlow` for an explanation
63+
(not this.getName().matches("%\\_l") or exists(this.getParameter(i + 1))) and
64+
// These functions always return the same pointer as they are given
65+
this.hasGlobalOrStdOrBslName([strrev(), strlwr(), strupr()]) and
66+
this.getParameter(i).getUnspecifiedType() instanceof PointerType and
4567
output.isReturnValue()
4668
)
4769
}

0 commit comments

Comments
 (0)