Skip to content

Commit 3e96028

Browse files
authored
Merge pull request #16063 from MathiasVP/taint-inheriting-content-for-cpp
C++: Add `TaintInheritingContent`
2 parents 2de62df + 3bfaab9 commit 3e96028

File tree

7 files changed

+66
-5
lines changed

7 files changed

+66
-5
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: feature
3+
---
4+
* Added a `TaintInheritingContent` class that can be extended to model taint flowing from a qualifier to a field.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* This file provides an abstract class that can be used to model additional
3+
* object-to-field taint-flow.
4+
*/
5+
6+
private import codeql.util.Unit
7+
private import semmle.code.cpp.dataflow.new.DataFlow
8+
9+
/**
10+
* A `Content` that should be implicitly regarded as tainted whenever an object with such `Content`
11+
* is itself tainted.
12+
*
13+
* For example, if we had a type `struct Container { int field; }`, then by default a tainted
14+
* `Container` and a `Container` with a tainted `int` stored in its `field` are distinct.
15+
*
16+
* If `any(DataFlow::FieldContent fc | fc.getField().hasQualifiedName("Container", "field"))` was
17+
* included in this type however, then a tainted `Container` would imply that its `field` is also
18+
* tainted (but not vice versa).
19+
*/
20+
abstract class TaintInheritingContent extends DataFlow::Content { }

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2301,8 +2301,8 @@ private import ContentStars
23012301

23022302
/** A reference through a non-union instance field. */
23032303
class FieldContent extends Content, TFieldContent {
2304-
Field f;
2305-
int indirectionIndex;
2304+
private Field f;
2305+
private int indirectionIndex;
23062306

23072307
FieldContent() { this = TFieldContent(f, indirectionIndex) }
23082308

@@ -2329,9 +2329,9 @@ class FieldContent extends Content, TFieldContent {
23292329

23302330
/** A reference through an instance field of a union. */
23312331
class UnionContent extends Content, TUnionContent {
2332-
Union u;
2333-
int indirectionIndex;
2334-
int bytes;
2332+
private Union u;
2333+
private int indirectionIndex;
2334+
private int bytes;
23352335

23362336
UnionContent() { this = TUnionContent(u, bytes, indirectionIndex) }
23372337

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ private import semmle.code.cpp.models.interfaces.SideEffect
66
private import DataFlowUtil
77
private import DataFlowPrivate
88
private import SsaInternals as Ssa
9+
private import semmle.code.cpp.ir.dataflow.FlowSteps
910

1011
/**
1112
* Holds if taint propagates from `nodeFrom` to `nodeTo` in exactly one local
@@ -37,6 +38,12 @@ predicate localAdditionalTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeT
3738
)
3839
or
3940
any(Ssa::Indirection ind).isAdditionalTaintStep(nodeFrom, nodeTo)
41+
or
42+
// object->field conflation for content that is a `TaintInheritingContent`.
43+
exists(DataFlow::ContentSet f |
44+
readStep(nodeFrom, f, nodeTo) and
45+
f.getAReadContent() instanceof TaintInheritingContent
46+
)
4047
}
4148

4249
/**

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6676,6 +6676,7 @@ WARNING: Module TaintTracking has been deprecated and may be removed in future (
66766676
| taint.cpp:757:7:757:10 | path | taint.cpp:759:8:759:11 | path | |
66776677
| taint.cpp:758:21:758:24 | ref arg path | taint.cpp:759:8:759:11 | path | |
66786678
| taint.cpp:759:8:759:11 | path | taint.cpp:759:7:759:11 | * ... | |
6679+
| taint.cpp:769:37:769:42 | call to source | taint.cpp:770:7:770:9 | obj | |
66796680
| vector.cpp:16:43:16:49 | source1 | vector.cpp:17:26:17:32 | source1 | |
66806681
| vector.cpp:16:43:16:49 | source1 | vector.cpp:31:38:31:44 | source1 | |
66816682
| vector.cpp:17:21:17:33 | call to vector | vector.cpp:19:14:19:14 | v | |

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -757,4 +757,15 @@ void test_call_sprintf() {
757757
char path[10];
758758
call_sprintf_twice(path, indirect_source());
759759
sink(*path); // $ ast,ir
760+
}
761+
762+
struct TaintInheritingContentObject {
763+
int flowFromObject;
764+
};
765+
766+
TaintInheritingContentObject source(bool);
767+
768+
void test_TaintInheritingContent() {
769+
TaintInheritingContentObject obj = source(true);
770+
sink(obj.flowFromObject); // $ ir MISSING: ast
760771
}

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,24 @@ module AstTest {
7676
module IRTest {
7777
private import semmle.code.cpp.ir.IR
7878
private import semmle.code.cpp.ir.dataflow.TaintTracking
79+
private import semmle.code.cpp.ir.dataflow.FlowSteps
80+
81+
/**
82+
* Object->field flow when the object is of type
83+
* TaintInheritingContentObject and the field is named
84+
* flowFromObject
85+
*/
86+
class TaintInheritingContentTest extends TaintInheritingContent, DataFlow::FieldContent {
87+
TaintInheritingContentTest() {
88+
exists(Struct o, Field f |
89+
this.getField() = f and
90+
f = o.getAField() and
91+
o.hasGlobalName("TaintInheritingContentObject") and
92+
f.hasName("flowFromObject") and
93+
this.getIndirectionIndex() = 1
94+
)
95+
}
96+
}
7997

8098
/** Common data flow configuration to be used by tests. */
8199
module TestAllocationConfig implements DataFlow::ConfigSig {

0 commit comments

Comments
 (0)