Skip to content

Commit bb2feda

Browse files
authored
Merge pull request github#7703 from geoffw0/getslocal
2 parents 0f239e3 + 0396a84 commit bb2feda

File tree

4 files changed

+72
-13
lines changed

4 files changed

+72
-13
lines changed

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

Lines changed: 51 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ import semmle.code.cpp.models.interfaces.SideEffect
1111
import semmle.code.cpp.models.interfaces.FlowSource
1212

1313
/**
14-
* The standard functions `gets` and `fgets`.
14+
* The standard functions `fgets` and `fgetws`.
1515
*/
16-
private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
16+
private class FgetsFunction extends DataFlowFunction, TaintFunction, ArrayFunction, AliasFunction,
1717
SideEffectFunction, RemoteFlowSourceFunction {
18-
GetsFunction() {
19-
// gets(str)
18+
FgetsFunction() {
2019
// fgets(str, num, stream)
2120
// fgetws(wstr, num, stream)
22-
this.hasGlobalOrStdOrBslName(["gets", "fgets", "fgetws"])
21+
this.hasGlobalOrStdOrBslName(["fgets", "fgetws"])
2322
}
2423

2524
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
@@ -51,20 +50,61 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio
5150
override predicate hasRemoteFlowSource(FunctionOutput output, string description) {
5251
output.isParameterDeref(0) and
5352
description = "String read by " + this.getName()
53+
or
54+
output.isReturnValue() and
55+
description = "String read by " + this.getName()
5456
}
5557

5658
override predicate hasArrayWithVariableSize(int bufParam, int countParam) {
57-
not this.hasName("gets") and
5859
bufParam = 0 and
5960
countParam = 1
6061
}
6162

62-
override predicate hasArrayWithUnknownSize(int bufParam) {
63-
this.hasName("gets") and
64-
bufParam = 0
63+
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
64+
65+
override predicate hasSocketInput(FunctionInput input) { input.isParameterDeref(2) }
66+
}
67+
68+
/**
69+
* The standard functions `gets`.
70+
*/
71+
private class GetsFunction extends DataFlowFunction, ArrayFunction, AliasFunction,
72+
SideEffectFunction, LocalFlowSourceFunction {
73+
GetsFunction() {
74+
// gets(str)
75+
this.hasGlobalOrStdOrBslName("gets")
6576
}
6677

67-
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
78+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
79+
input.isParameter(0) and
80+
output.isReturnValue()
81+
}
82+
83+
override predicate parameterNeverEscapes(int index) { none() }
84+
85+
override predicate parameterEscapesOnlyViaReturn(int index) { index = 0 }
6886

69-
override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) }
87+
override predicate parameterIsAlwaysReturned(int index) { index = 0 }
88+
89+
override predicate hasOnlySpecificReadSideEffects() { any() }
90+
91+
override predicate hasOnlySpecificWriteSideEffects() { any() }
92+
93+
override predicate hasSpecificWriteSideEffect(ParameterIndex i, boolean buffer, boolean mustWrite) {
94+
i = 0 and
95+
buffer = true and
96+
mustWrite = true
97+
}
98+
99+
override predicate hasLocalFlowSource(FunctionOutput output, string description) {
100+
output.isParameterDeref(0) and
101+
description = "String read by " + this.getName()
102+
or
103+
output.isReturnValue() and
104+
description = "String read by " + this.getName()
105+
}
106+
107+
override predicate hasArrayWithUnknownSize(int bufParam) { bufParam = 0 }
108+
109+
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
70110
}

cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,10 @@ class Send extends SendRecv instanceof RemoteFlowSinkFunction {
5858
call.getTarget() = this and
5959
exists(FunctionInput input, int arg |
6060
super.hasSocketInput(input) and
61-
input.isParameter(arg) and
61+
(
62+
input.isParameter(arg) or
63+
input.isParameterDeref(arg)
64+
) and
6265
result = call.getArgument(arg)
6366
)
6467
}
@@ -81,7 +84,10 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
8184
call.getTarget() = this and
8285
exists(FunctionInput input, int arg |
8386
super.hasSocketInput(input) and
84-
input.isParameter(arg) and
87+
(
88+
input.isParameter(arg) or
89+
input.isParameterDeref(arg)
90+
) and
8591
result = call.getArgument(arg)
8692
)
8793
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
edges
22
| test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input |
33
nodes
4+
| test2.cpp:110:3:110:6 | call to gets | semmle.label | call to gets |
45
| test.cpp:54:17:54:20 | argv | semmle.label | argv |
56
| test.cpp:58:25:58:29 | input | semmle.label | input |
67
subpaths
78
#select
9+
| test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | test2.cpp:110:3:110:6 | call to gets | This write into buffer 'password' may contain unencrypted data from $@ | test2.cpp:110:3:110:6 | call to gets | user input (String read by gets) |
810
| test.cpp:58:3:58:9 | call to sprintf | test.cpp:54:17:54:20 | argv | test.cpp:58:25:58:29 | input | This write into buffer 'passwd' may contain unencrypted data from $@ | test.cpp:54:17:54:20 | argv | user input (a command-line argument) |

cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test2.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,3 +99,14 @@ void tests(FILE *log, myStruct &s)
9999
fprintf(log, "log: %s", buffer); // BAD
100100
}
101101
}
102+
103+
char *gets(char *s);
104+
105+
void test_gets()
106+
{
107+
{
108+
char password[1024];
109+
110+
gets(password); // BAD
111+
}
112+
}

0 commit comments

Comments
 (0)