Skip to content

Commit 79a72a3

Browse files
author
Robert Marsh
authored
Merge pull request #2680 from geoffw0/modelstrndup
CPP: Model strndup.
2 parents 4d743d2 + 4778914 commit 79a72a3

File tree

9 files changed

+54
-30
lines changed

9 files changed

+54
-30
lines changed

cpp/ql/src/semmle/code/cpp/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ private predicate exprToExprStep(Expr exprIn, Expr exprOut) {
132132
// dest_ptr = strdup(tainted_ptr)
133133
inModel.isParameterDeref(argInIndex) and
134134
exprIn = call.getArgument(argInIndex)
135+
or
136+
inModel.isParameter(argInIndex) and
137+
exprIn = call.getArgument(argInIndex)
135138
)
136139
)
137140
or
@@ -173,6 +176,9 @@ private predicate exprToDefinitionByReferenceStep(Expr exprIn, Expr argOut) {
173176
// memcpy(&dest_var, tainted_ptr, len)
174177
inModel.isParameterDeref(argInIndex) and
175178
exprIn = call.getArgument(argInIndex)
179+
or
180+
inModel.isParameter(argInIndex) and
181+
exprIn = call.getArgument(argInIndex)
176182
)
177183
)
178184
or

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

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,20 +47,11 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
4747
}
4848

4949
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
50-
(
51-
// These always copy the full value of the input buffer to the output
52-
// buffer
53-
this.hasName("strcpy") or
54-
this.hasName("_mbscpy") or
55-
this.hasName("wcscpy")
56-
) and
57-
(
58-
input.isParameterDeref(1) and
59-
output.isParameterDeref(0)
60-
or
61-
input.isParameterDeref(1) and
62-
output.isReturnValueDeref()
63-
)
50+
input.isParameterDeref(1) and
51+
output.isParameterDeref(0)
52+
or
53+
input.isParameterDeref(1) and
54+
output.isReturnValueDeref()
6455
or
6556
input.isParameter(0) and
6657
output.isReturnValue()
@@ -77,10 +68,7 @@ class StrcpyFunction extends ArrayFunction, DataFlowFunction, TaintFunction {
7768
this.hasName("wcsncpy") or
7869
this.hasName("_wcsncpy_l")
7970
) and
80-
(
81-
input.isParameter(2) or
82-
input.isParameterDeref(1)
83-
) and
71+
input.isParameter(2) and
8472
(
8573
output.isParameterDeref(0) or
8674
output.isReturnValueDeref()

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

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,14 @@ import semmle.code.cpp.models.interfaces.Taint
99
class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
1010
StrdupFunction() {
1111
exists(string name |
12-
hasGlobalOrStdName(name) and
12+
hasGlobalName(name) and
1313
(
1414
// strdup(str)
1515
name = "strdup"
1616
or
1717
// wcsdup(str)
1818
name = "wcsdup"
19-
)
20-
or
21-
hasGlobalName(name) and
22-
(
19+
or
2320
// _strdup(str)
2421
name = "_strdup"
2522
or
@@ -37,9 +34,32 @@ class StrdupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction
3734
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
3835

3936
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
40-
// These always copy the full value of the input buffer to the result
41-
// buffer
4237
input.isParameterDeref(0) and
4338
output.isReturnValueDeref()
4439
}
4540
}
41+
42+
/**
43+
* A `strndup` style allocation function.
44+
*/
45+
class StrndupFunction extends AllocationFunction, ArrayFunction, DataFlowFunction {
46+
StrndupFunction() {
47+
exists(string name |
48+
hasGlobalName(name) and
49+
// strndup(str, maxlen)
50+
name = "strndup"
51+
)
52+
}
53+
54+
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
55+
56+
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
57+
58+
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
59+
(
60+
input.isParameterDeref(0) or
61+
input.isParameter(1)
62+
) and
63+
output.isReturnValueDeref()
64+
}
65+
}

cpp/ql/src/semmle/code/cpp/models/interfaces/DataFlow.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ import FunctionInputsAndOutputs
1212
import semmle.code.cpp.models.Models
1313

1414
/**
15-
* A library function for which a value is copied from a parameter or qualifier
16-
* to an output buffer, return value, or qualifier.
15+
* A library function for which a value is or may be copied from a parameter
16+
* or qualifier to an output buffer, return value, or qualifier.
1717
*
1818
* Note that this does not include partial copying of values or partial writes
1919
* to destinations; that is covered by `TaintModel.qll`.

cpp/ql/src/semmle/code/cpp/models/interfaces/Taint.qll

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ import semmle.code.cpp.models.Models
1616
* from a parameter or qualifier to an output buffer, return value, or qualifier.
1717
*
1818
* Note that this does not include direct copying of values; that is covered by
19-
* DataFlowModel.qll
19+
* DataFlowModel.qll. If a value is sometimes copied in full, and sometimes
20+
* altered (for example copying a string with `strncpy`), this is also considered
21+
* data flow.
2022
*/
2123
abstract class TaintFunction extends Function {
2224
abstract predicate hasTaintFlow(FunctionInput input, FunctionOutput output);

cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,13 @@
337337
| taint.cpp:370:13:370:26 | hello, world | taint.cpp:370:6:370:11 | call to strdup | TAINT |
338338
| taint.cpp:371:6:371:12 | call to strndup | taint.cpp:371:2:371:25 | ... = ... | |
339339
| taint.cpp:371:6:371:12 | call to strndup | taint.cpp:374:7:374:7 | c | |
340+
| taint.cpp:371:14:371:19 | source | taint.cpp:371:6:371:12 | call to strndup | TAINT |
341+
| taint.cpp:371:22:371:24 | 100 | taint.cpp:371:6:371:12 | call to strndup | TAINT |
340342
| taint.cpp:377:23:377:28 | source | taint.cpp:381:30:381:35 | source | |
341343
| taint.cpp:381:6:381:12 | call to strndup | taint.cpp:381:2:381:36 | ... = ... | |
342344
| taint.cpp:381:6:381:12 | call to strndup | taint.cpp:382:7:382:7 | a | |
345+
| taint.cpp:381:14:381:27 | hello, world | taint.cpp:381:6:381:12 | call to strndup | TAINT |
346+
| taint.cpp:381:30:381:35 | source | taint.cpp:381:6:381:12 | call to strndup | TAINT |
343347
| taint.cpp:385:27:385:32 | source | taint.cpp:389:13:389:18 | source | |
344348
| taint.cpp:389:6:389:11 | call to wcsdup | taint.cpp:389:2:389:19 | ... = ... | |
345349
| taint.cpp:389:6:389:11 | call to wcsdup | taint.cpp:391:7:391:7 | a | |

cpp/ql/test/library-tests/dataflow/taint-tests/taint.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,15 +371,15 @@ void test_strdup(char *source)
371371
c = strndup(source, 100);
372372
sink(a); // tainted
373373
sink(b);
374-
sink(c); // tainted [NOT DETECTED]
374+
sink(c); // tainted
375375
}
376376

377377
void test_strndup(int source)
378378
{
379379
char *a;
380380

381381
a = strndup("hello, world", source);
382-
sink(a);
382+
sink(a); // tainted
383383
}
384384

385385
void test_wcsdup(wchar_t *source)

cpp/ql/test/library-tests/dataflow/taint-tests/taint.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
| taint.cpp:351:7:351:7 | a | taint.cpp:330:6:330:11 | call to source |
3939
| taint.cpp:352:7:352:7 | b | taint.cpp:330:6:330:11 | call to source |
4040
| taint.cpp:372:7:372:7 | a | taint.cpp:365:24:365:29 | source |
41+
| taint.cpp:374:7:374:7 | c | taint.cpp:365:24:365:29 | source |
42+
| taint.cpp:382:7:382:7 | a | taint.cpp:377:23:377:28 | source |
4143
| taint.cpp:391:7:391:7 | a | taint.cpp:385:27:385:32 | source |
4244
| taint.cpp:423:7:423:7 | a | taint.cpp:422:14:422:19 | call to source |
4345
| taint.cpp:424:9:424:17 | call to getMember | taint.cpp:422:14:422:19 | call to source |

cpp/ql/test/library-tests/dataflow/taint-tests/test_diff.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
| taint.cpp:351:7:351:7 | taint.cpp:330:6:330:11 | AST only |
2626
| taint.cpp:352:7:352:7 | taint.cpp:330:6:330:11 | AST only |
2727
| taint.cpp:372:7:372:7 | taint.cpp:365:24:365:29 | AST only |
28+
| taint.cpp:374:7:374:7 | taint.cpp:365:24:365:29 | AST only |
29+
| taint.cpp:382:7:382:7 | taint.cpp:377:23:377:28 | AST only |
2830
| taint.cpp:391:7:391:7 | taint.cpp:385:27:385:32 | AST only |
2931
| taint.cpp:423:7:423:7 | taint.cpp:422:14:422:19 | AST only |
3032
| taint.cpp:424:9:424:17 | taint.cpp:422:14:422:19 | AST only |

0 commit comments

Comments
 (0)