Skip to content

Commit dc7ce3f

Browse files
authored
Merge pull request #21171 from MathiasVP/fix-conflation-in-guards
C++: Fix conflation in barrier guards
2 parents 077bbb2 + f05bff0 commit dc7ce3f

File tree

8 files changed

+59
-36
lines changed

8 files changed

+59
-36
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: fix
3+
---
4+
* Fixed a bug in the `DataFlow::BarrierGuard<...>::getABarrierNode` predicate which caused the predicate to return `DataFlow::Node`s with incorrect indirections. If you use `getABarrierNode` to implement barriers in a dataflow/taint-tracking query it may result in more query results. You can use `DataFlow::BarrierGuard<...>::getAnIndirectBarrierNode` to remove those query results.

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

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ class Node extends TIRDataFlowNode {
156156
* If `isGLValue()` holds, then the type of this node
157157
* should be thought of as "pointer to `getType()`".
158158
*/
159-
DataFlowType getType() { none() } // overridden in subclasses
159+
Type getType() { none() } // overridden in subclasses
160160

161161
/** Gets the instruction corresponding to this node, if any. */
162162
Instruction asInstruction() { result = this.(InstructionNode).getInstruction() }
@@ -541,7 +541,7 @@ class Node extends TIRDataFlowNode {
541541
/**
542542
* Gets an upper bound on the type of this node.
543543
*/
544-
DataFlowType getTypeBound() { result = this.getType() }
544+
Type getTypeBound() { result = this.getType() }
545545

546546
/** Gets the location of this element. */
547547
cached
@@ -585,7 +585,7 @@ private class Node0 extends Node, TNode0 {
585585

586586
override string toStringImpl() { result = node.toString() }
587587

588-
override DataFlowType getType() { result = node.getType() }
588+
override Type getType() { result = node.getType() }
589589

590590
override predicate isGLValue() { node.isGLValue() }
591591
}
@@ -704,7 +704,7 @@ class SsaSynthNode extends Node, TSsaSynthNode {
704704

705705
override Declaration getFunction() { result = node.getBasicBlock().getEnclosingFunction() }
706706

707-
override DataFlowType getType() { result = node.getSourceVariable().getType() }
707+
override Type getType() { result = node.getSourceVariable().getType() }
708708

709709
override predicate isGLValue() { node.getSourceVariable().isGLValue() }
710710

@@ -732,7 +732,7 @@ class SsaIteratorNode extends Node, TSsaIteratorNode {
732732

733733
override Declaration getFunction() { result = node.getFunction() }
734734

735-
override DataFlowType getType() { result = node.getType() }
735+
override Type getType() { result = node.getType() }
736736

737737
final override Location getLocationImpl() { result = node.getLocation() }
738738

@@ -792,7 +792,7 @@ class FinalGlobalValue extends Node, TFinalGlobalValue {
792792

793793
override Declaration getFunction() { result = globalUse.getIRFunction().getFunction() }
794794

795-
override DataFlowType getType() {
795+
override Type getType() {
796796
exists(int indirectionIndex |
797797
indirectionIndex = globalUse.getIndirectionIndex() and
798798
result = getTypeImpl(globalUse.getUnderlyingType(), indirectionIndex)
@@ -826,7 +826,7 @@ class InitialGlobalValue extends Node, TInitialGlobalValue {
826826

827827
final override predicate isGLValue() { globalDef.getIndirectionIndex() = 0 }
828828

829-
override DataFlowType getType() { result = globalDef.getUnderlyingType() }
829+
override Type getType() { result = globalDef.getUnderlyingType() }
830830

831831
final override Location getLocationImpl() { result = globalDef.getLocation() }
832832

@@ -853,7 +853,7 @@ class BodyLessParameterNodeImpl extends Node, TBodyLessParameterNodeImpl {
853853
/** Gets the indirection index of this node. */
854854
int getIndirectionIndex() { result = indirectionIndex }
855855

856-
override DataFlowType getType() {
856+
override Type getType() {
857857
result = getTypeImpl(p.getUnderlyingType(), this.getIndirectionIndex())
858858
}
859859

@@ -1117,8 +1117,8 @@ private module RawIndirectNodes {
11171117

11181118
override predicate isGLValue() { this.getOperand().isGLValue() }
11191119

1120-
override DataFlowType getType() {
1121-
exists(int sub, DataFlowType type, boolean isGLValue |
1120+
override Type getType() {
1121+
exists(int sub, Type type, boolean isGLValue |
11221122
type = getOperandType(this.getOperand(), isGLValue) and
11231123
if isGLValue = true then sub = 1 else sub = 0
11241124
|
@@ -1163,8 +1163,8 @@ private module RawIndirectNodes {
11631163

11641164
override predicate isGLValue() { this.getInstruction().isGLValue() }
11651165

1166-
override DataFlowType getType() {
1167-
exists(int sub, DataFlowType type, boolean isGLValue |
1166+
override Type getType() {
1167+
exists(int sub, Type type, boolean isGLValue |
11681168
type = getInstructionType(this.getInstruction(), isGLValue) and
11691169
if isGLValue = true then sub = 1 else sub = 0
11701170
|
@@ -1263,7 +1263,7 @@ class FinalParameterNode extends Node, TFinalParameterNode {
12631263
result.asSourceCallable() = this.getFunction()
12641264
}
12651265

1266-
override DataFlowType getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
1266+
override Type getType() { result = getTypeImpl(p.getUnderlyingType(), indirectionIndex) }
12671267

12681268
final override Location getLocationImpl() {
12691269
// Parameters can have multiple locations. When there's a unique location we use
@@ -1539,7 +1539,7 @@ abstract class PostUpdateNode extends Node {
15391539
*/
15401540
abstract Node getPreUpdateNode();
15411541

1542-
final override DataFlowType getType() { result = this.getPreUpdateNode().getType() }
1542+
final override Type getType() { result = this.getPreUpdateNode().getType() }
15431543
}
15441544

15451545
/**
@@ -1632,9 +1632,7 @@ class VariableNode extends Node, TGlobalLikeVariableNode {
16321632
result.asSourceCallable() = v
16331633
}
16341634

1635-
override DataFlowType getType() {
1636-
result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1)
1637-
}
1635+
override Type getType() { result = getTypeImpl(v.getUnderlyingType(), indirectionIndex - 1) }
16381636

16391637
final override Location getLocationImpl() {
16401638
// Certain variables (such as parameters) can have multiple locations.

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

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ private module SourceVariables {
5353
* the type of this source variable should be thought of as "pointer
5454
* to `getType()`".
5555
*/
56-
DataFlowType getType() {
56+
Type getType() {
5757
if this.isGLValue()
5858
then result = base.getType()
5959
else result = getTypeImpl(base.getType(), ind - 1)
@@ -1064,8 +1064,15 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
10641064
DataFlowIntegrationInput::Guard g, SsaImpl::Definition def, IRGuards::GuardValue val,
10651065
int indirectionIndex
10661066
) {
1067-
IRGuards::Guards_v1::ParameterizedValidationWrapper<int, guardChecksInstr/4>::guardChecksDef(g,
1068-
def, val, indirectionIndex)
1067+
exists(Instruction e |
1068+
IRGuards::Guards_v1::ParameterizedValidationWrapper<int, guardChecksInstr/4>::guardChecks(g,
1069+
e, val, indirectionIndex)
1070+
|
1071+
indirectionIndex = 0 and
1072+
def.(Definition).getAUse().getDef() = e
1073+
or
1074+
def.(Definition).getAnIndirectUse(indirectionIndex).getDef() = e
1075+
)
10691076
}
10701077

10711078
Node getABarrierNode(int indirectionIndex) {

cpp/ql/src/Security/CWE/CWE-120/UnboundedWrite.ql

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,8 @@ module Config implements DataFlow::ConfigSig {
122122

123123
predicate isBarrier(DataFlow::Node node) {
124124
// Block flow if the node is guarded by any <, <= or = operations.
125-
node = DataFlow::BarrierGuard<lessThanOrEqual/3>::getABarrierNode()
125+
node = DataFlow::BarrierGuard<lessThanOrEqual/3>::getABarrierNode() or
126+
node = DataFlow::BarrierGuard<lessThanOrEqual/3>::getAnIndirectBarrierNode()
126127
}
127128

128129
predicate observeDiffInformedIncrementalMode() { any() }

cpp/ql/src/utils/modelgenerator/internal/CaptureModels.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ module ModelGeneratorCommonInput implements ModelGeneratorCommonInputSig<Cpp::Lo
7878
{
7979
private module DataFlow = Df::DataFlow;
8080

81-
class Type = DataFlowPrivate::DataFlowType;
81+
class Type = Cpp::Type;
8282

8383
// Note: This also includes `this`
8484
class Parameter = DataFlow::ParameterNode;

cpp/ql/test/library-tests/dataflow/ir-barrier-guards/test.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@ void sink(int);
44

55
void testCheckArgument(int* p) {
66
if (checkArgument(p)) {
7-
sink(*p); // $ barrier barrier=1
7+
sink(*p); // $ indirect_barrier=int barrier=int*
8+
}
9+
}
10+
11+
void testCheckArgument(int p) {
12+
if (checkArgument(&p)) {
13+
sink(p); // $ barrier=glval<int> indirect_barrier=int
814
}
915
}

cpp/ql/test/library-tests/dataflow/ir-barrier-guards/test.ql

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,26 +13,33 @@ predicate instructionGuardChecks(IRGuardCondition gc, Instruction checked, boole
1313

1414
module BarrierGuard = DataFlow::InstructionBarrierGuard<instructionGuardChecks/3>;
1515

16-
predicate indirectBarrierGuard(DataFlow::Node node, int indirectionIndex) {
17-
node = BarrierGuard::getAnIndirectBarrierNode(indirectionIndex)
16+
predicate indirectBarrierGuard(DataFlow::Node node, string s) {
17+
node = BarrierGuard::getAnIndirectBarrierNode(_) and
18+
if node.isGLValue()
19+
then s = "glval<" + node.getType().toString().replaceAll(" ", "") + ">"
20+
else s = node.getType().toString().replaceAll(" ", "")
1821
}
1922

20-
predicate barrierGuard(DataFlow::Node node) { node = BarrierGuard::getABarrierNode() }
23+
predicate barrierGuard(DataFlow::Node node, string s) {
24+
node = BarrierGuard::getABarrierNode() and
25+
if node.isGLValue()
26+
then s = "glval<" + node.getType().toString().replaceAll(" ", "") + ">"
27+
else s = node.getType().toString().replaceAll(" ", "")
28+
}
2129

2230
module Test implements TestSig {
23-
string getARelevantTag() { result = "barrier" }
31+
string getARelevantTag() { result = ["barrier", "indirect_barrier"] }
2432

2533
predicate hasActualResult(Location location, string element, string tag, string value) {
26-
exists(DataFlow::Node node |
27-
barrierGuard(node) and
28-
value = ""
34+
exists(DataFlow::Node node, string s |
35+
indirectBarrierGuard(node, s) and
36+
value = s and
37+
tag = "indirect_barrier"
2938
or
30-
exists(int indirectionIndex |
31-
indirectBarrierGuard(node, indirectionIndex) and
32-
value = indirectionIndex.toString()
33-
)
39+
barrierGuard(node, s) and
40+
value = s and
41+
tag = "barrier"
3442
|
35-
tag = "barrier" and
3643
element = node.toString() and
3744
location = node.getLocation()
3845
)

shared/controlflow/codeql/controlflow/Guards.qll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1364,7 +1364,7 @@ module Make<
13641364
/**
13651365
* Holds if the guard `g` validates the expression `e` upon evaluating to `val`.
13661366
*/
1367-
private predicate guardChecks(Guard g, Expr e, GuardValue val, P par) {
1367+
predicate guardChecks(Guard g, Expr e, GuardValue val, P par) {
13681368
guardChecks0(g, e, val, par)
13691369
or
13701370
exists(NonOverridableMethodCall call, ParameterPosition ppos, ArgumentPosition apos |

0 commit comments

Comments
 (0)