Skip to content

Commit 9d6098a

Browse files
authored
Merge pull request #12004 from jketema/single-use
C++: Map operand nodes that are only used once onto the related instruction node
2 parents 946e301 + e4c211d commit 9d6098a

File tree

6 files changed

+66
-51
lines changed

6 files changed

+66
-51
lines changed

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

Lines changed: 46 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,21 @@ private module Cached {
1212
newtype TIRDataFlowNode0 =
1313
TInstructionNode0(Instruction i) {
1414
not Ssa::ignoreInstruction(i) and
15+
not exists(Operand op |
16+
not Ssa::ignoreOperand(op) and i = Ssa::getIRRepresentationOfOperand(op)
17+
) and
1518
// We exclude `void`-typed instructions because they cannot contain data.
1619
// However, if the instruction is a glvalue, and their type is `void`, then the result
1720
// type of the instruction is really `void*`, and thus we still want to have a dataflow
1821
// node for it.
1922
(not i.getResultType() instanceof VoidType or i.isGLValue())
2023
} or
21-
TOperandNode0(Operand op) { not Ssa::ignoreOperand(op) }
24+
TMultipleUseOperandNode0(Operand op) {
25+
not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op))
26+
} or
27+
TSingleUseOperandNode0(Operand op) {
28+
not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op))
29+
}
2230
}
2331

2432
private import Cached
@@ -66,11 +74,9 @@ class Node0Impl extends TIRDataFlowNode0 {
6674
/**
6775
* An instruction, viewed as a node in a data flow graph.
6876
*/
69-
class InstructionNode0 extends Node0Impl, TInstructionNode0 {
77+
abstract class InstructionNode0 extends Node0Impl {
7078
Instruction instr;
7179

72-
InstructionNode0() { this = TInstructionNode0(instr) }
73-
7480
/** Gets the instruction corresponding to this node. */
7581
Instruction getInstruction() { result = instr }
7682

@@ -85,18 +91,35 @@ class InstructionNode0 extends Node0Impl, TInstructionNode0 {
8591
override string toStringImpl() {
8692
// This predicate is overridden in subclasses. This default implementation
8793
// does not use `Instruction.toString` because that's expensive to compute.
88-
result = this.getInstruction().getOpcode().toString()
94+
result = instr.getOpcode().toString()
95+
}
96+
}
97+
98+
/**
99+
* An instruction without an operand that is used only once, viewed as a node in a data flow graph.
100+
*/
101+
private class InstructionInstructionNode0 extends InstructionNode0, TInstructionNode0 {
102+
InstructionInstructionNode0() { this = TInstructionNode0(instr) }
103+
}
104+
105+
/**
106+
* An instruction with an operand that is used only once, viewed as a node in a data flow graph.
107+
*/
108+
private class SingleUseOperandInstructionNode0 extends InstructionNode0, TSingleUseOperandNode0 {
109+
SingleUseOperandInstructionNode0() {
110+
exists(Operand op |
111+
this = TSingleUseOperandNode0(op) and
112+
instr = Ssa::getIRRepresentationOfOperand(op)
113+
)
89114
}
90115
}
91116

92117
/**
93118
* An operand, viewed as a node in a data flow graph.
94119
*/
95-
class OperandNode0 extends Node0Impl, TOperandNode0 {
120+
abstract class OperandNode0 extends Node0Impl {
96121
Operand op;
97122

98-
OperandNode0() { this = TOperandNode0(op) }
99-
100123
/** Gets the operand corresponding to this node. */
101124
Operand getOperand() { result = op }
102125

@@ -108,7 +131,21 @@ class OperandNode0 extends Node0Impl, TOperandNode0 {
108131

109132
final override Location getLocationImpl() { result = op.getLocation() }
110133

111-
override string toStringImpl() { result = this.getOperand().toString() }
134+
override string toStringImpl() { result = op.toString() }
135+
}
136+
137+
/**
138+
* An operand that is used multiple times, viewed as a node in a data flow graph.
139+
*/
140+
private class MultipleUseOperandNode0 extends OperandNode0, TMultipleUseOperandNode0 {
141+
MultipleUseOperandNode0() { this = TMultipleUseOperandNode0(op) }
142+
}
143+
144+
/**
145+
* An operand that is used only once, viewed as a node in a data flow graph.
146+
*/
147+
private class SingleUseOperandNode0 extends OperandNode0, TSingleUseOperandNode0 {
148+
SingleUseOperandNode0() { this = TSingleUseOperandNode0(op) }
112149
}
113150

114151
/**

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -404,7 +404,7 @@ class OperandNode extends Node, Node0 {
404404
OperandNode() { op = node.getOperand() }
405405

406406
/** Gets the operand corresponding to this node. */
407-
Operand getOperand() { result = node.getOperand() }
407+
Operand getOperand() { result = op }
408408

409409
override string toStringImpl() { result = op.getDef().getAst().toString() }
410410
}
@@ -1439,7 +1439,13 @@ private module Cached {
14391439
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
14401440
or
14411441
// Instruction -> Operand flow
1442-
simpleOperandLocalFlowStep(nodeFrom.asInstruction(), nodeTo.asOperand())
1442+
exists(Instruction iFrom, Operand opTo |
1443+
iFrom = nodeFrom.asInstruction() and opTo = nodeTo.asOperand()
1444+
|
1445+
simpleOperandLocalFlowStep(iFrom, opTo) and
1446+
// Omit when the instruction node also represents the operand.
1447+
not iFrom = Ssa::getIRRepresentationOfOperand(opTo)
1448+
)
14431449
or
14441450
// Phi node -> Node flow
14451451
Ssa::fromPhiNode(nodeFrom, nodeTo)

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,18 @@ private module Cached {
719719
)
720720
}
721721

722+
/**
723+
* Holds if the underlying IR has a suitable instruction to represent a value
724+
* that would otherwise need to be represented by a dedicated `OperandNode` value.
725+
*
726+
* Such operands do not create new `OperandNode` values, but are
727+
* instead associated with the instruction returned by this predicate.
728+
*/
729+
cached
730+
Instruction getIRRepresentationOfOperand(Operand operand) {
731+
operand = unique( | | result.getAUse())
732+
}
733+
722734
/**
723735
* Holds if the underlying IR has a suitable operand to represent a value
724736
* that would otherwise need to be represented by a dedicated `RawIndirectOperand` value.
Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,30 @@
11
edges
22
| test1.c:7:26:7:29 | argv | test1.c:9:9:9:9 | i |
33
| test1.c:7:26:7:29 | argv | test1.c:11:9:11:9 | i |
4-
| test1.c:7:26:7:29 | argv | test1.c:12:9:12:9 | i |
54
| test1.c:7:26:7:29 | argv | test1.c:13:9:13:9 | i |
65
| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i |
76
| test1.c:7:26:7:29 | argv indirection | test1.c:9:9:9:9 | i |
87
| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i |
98
| test1.c:7:26:7:29 | argv indirection | test1.c:11:9:11:9 | i |
10-
| test1.c:7:26:7:29 | argv indirection | test1.c:12:9:12:9 | i |
11-
| test1.c:7:26:7:29 | argv indirection | test1.c:12:9:12:9 | i |
129
| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i |
1310
| test1.c:7:26:7:29 | argv indirection | test1.c:13:9:13:9 | i |
1411
| test1.c:9:9:9:9 | i | test1.c:16:16:16:16 | i |
1512
| test1.c:11:9:11:9 | i | test1.c:32:16:32:16 | i |
16-
| test1.c:12:9:12:9 | i | test1.c:40:16:40:16 | i |
1713
| test1.c:13:9:13:9 | i | test1.c:48:16:48:16 | i |
1814
| test1.c:16:16:16:16 | i | test1.c:18:16:18:16 | i |
1915
| test1.c:32:16:32:16 | i | test1.c:33:11:33:11 | i |
20-
| test1.c:40:16:40:16 | i | test1.c:41:11:41:11 | i |
2116
| test1.c:48:16:48:16 | i | test1.c:53:15:53:15 | j |
2217
nodes
2318
| test1.c:7:26:7:29 | argv | semmle.label | argv |
2419
| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection |
2520
| test1.c:7:26:7:29 | argv indirection | semmle.label | argv indirection |
2621
| test1.c:9:9:9:9 | i | semmle.label | i |
2722
| test1.c:11:9:11:9 | i | semmle.label | i |
28-
| test1.c:12:9:12:9 | i | semmle.label | i |
2923
| test1.c:13:9:13:9 | i | semmle.label | i |
3024
| test1.c:16:16:16:16 | i | semmle.label | i |
3125
| test1.c:18:16:18:16 | i | semmle.label | i |
3226
| test1.c:32:16:32:16 | i | semmle.label | i |
3327
| test1.c:33:11:33:11 | i | semmle.label | i |
34-
| test1.c:40:16:40:16 | i | semmle.label | i |
35-
| test1.c:41:11:41:11 | i | semmle.label | i |
3628
| test1.c:48:16:48:16 | i | semmle.label | i |
3729
| test1.c:53:15:53:15 | j | semmle.label | j |
3830
subpaths
@@ -43,9 +35,6 @@ subpaths
4335
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
4436
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
4537
| test1.c:33:11:33:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:33:11:33:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
46-
| test1.c:41:11:41:11 | i | test1.c:7:26:7:29 | argv | test1.c:41:11:41:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
47-
| test1.c:41:11:41:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:41:11:41:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
48-
| test1.c:41:11:41:11 | i | test1.c:7:26:7:29 | argv indirection | test1.c:41:11:41:11 | i | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
4938
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv | a command-line argument |
5039
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |
5140
| test1.c:53:15:53:15 | j | test1.c:7:26:7:29 | argv indirection | test1.c:53:15:53:15 | j | An array indexing expression depends on $@ that might be outside the bounds of the array. | test1.c:7:26:7:29 | argv indirection | a command-line argument |

cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ edges
22
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
33
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
44
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
5-
| globalVars.c:8:7:8:10 | copy | globalVars.c:27:9:27:12 | copy |
65
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
76
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
87
| globalVars.c:8:7:8:10 | copy | globalVars.c:30:15:30:18 | copy |
@@ -12,15 +11,13 @@ edges
1211
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
1312
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
1413
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
15-
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:38:9:38:13 | copy2 |
1614
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
1715
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
1816
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:41:15:41:19 | copy2 |
1917
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:44:15:44:19 | copy2 |
2018
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
2119
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
2220
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
23-
| globalVars.c:9:7:9:11 | copy2 | globalVars.c:50:9:50:13 | copy2 |
2421
| globalVars.c:11:22:11:25 | argv | globalVars.c:8:7:8:10 | copy |
2522
| globalVars.c:11:22:11:25 | argv | globalVars.c:12:2:12:15 | ... = ... |
2623
| globalVars.c:12:2:12:15 | ... = ... | globalVars.c:8:7:8:10 | copy |
@@ -29,26 +26,12 @@ edges
2926
| globalVars.c:16:2:16:12 | ... = ... | globalVars.c:9:7:9:11 | copy2 |
3027
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
3128
| globalVars.c:24:11:24:14 | argv | globalVars.c:11:22:11:25 | argv |
32-
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy |
33-
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy |
34-
| globalVars.c:27:9:27:12 | copy | globalVars.c:27:9:27:12 | copy |
35-
| globalVars.c:27:9:27:12 | copy | globalVars.c:30:15:30:18 | copy |
36-
| globalVars.c:27:9:27:12 | copy | globalVars.c:30:15:30:18 | copy |
37-
| globalVars.c:27:9:27:12 | copy | globalVars.c:35:11:35:14 | copy |
3829
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
3930
| globalVars.c:30:15:30:18 | copy | globalVars.c:30:15:30:18 | copy |
4031
| globalVars.c:30:15:30:18 | copy | globalVars.c:35:11:35:14 | copy |
4132
| globalVars.c:33:15:33:18 | copy | globalVars.c:35:11:35:14 | copy |
4233
| globalVars.c:35:11:35:14 | copy | globalVars.c:15:21:15:23 | val |
4334
| globalVars.c:35:11:35:14 | copy | globalVars.c:35:11:35:14 | copy |
44-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 |
45-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 |
46-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:38:9:38:13 | copy2 |
47-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:41:15:41:19 | copy2 |
48-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:41:15:41:19 | copy2 |
49-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
50-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
51-
| globalVars.c:38:9:38:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
5235
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
5336
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:41:15:41:19 | copy2 |
5437
| globalVars.c:41:15:41:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
@@ -57,9 +40,6 @@ edges
5740
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
5841
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
5942
| globalVars.c:44:15:44:19 | copy2 | globalVars.c:50:9:50:13 | copy2 |
60-
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
61-
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
62-
| globalVars.c:50:9:50:13 | copy2 | globalVars.c:50:9:50:13 | copy2 |
6343
subpaths
6444
nodes
6545
| globalVars.c:8:7:8:10 | copy | semmle.label | copy |
@@ -73,7 +53,6 @@ nodes
7353
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
7454
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
7555
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
76-
| globalVars.c:27:9:27:12 | copy | semmle.label | copy |
7756
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
7857
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
7958
| globalVars.c:30:15:30:18 | copy | semmle.label | copy |
@@ -83,15 +62,13 @@ nodes
8362
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
8463
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
8564
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
86-
| globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 |
8765
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
8866
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
8967
| globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 |
9068
| globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 |
9169
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
9270
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
9371
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
94-
| globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 |
9572
#select
9673
| globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv |
9774
| globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv |

cpp/ql/test/query-tests/Security/CWE/CWE-326/InsufficientKeySize.expected

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
edges
2-
| test.cpp:34:45:34:48 | 1024 | test.cpp:34:45:34:48 | 1024 |
3-
| test.cpp:35:49:35:52 | 1024 | test.cpp:35:49:35:52 | 1024 |
4-
| test.cpp:37:43:37:46 | 1024 | test.cpp:37:43:37:46 | 1024 |
52
nodes
63
| test.cpp:34:45:34:48 | 1024 | semmle.label | 1024 |
7-
| test.cpp:34:45:34:48 | 1024 | semmle.label | 1024 |
8-
| test.cpp:35:49:35:52 | 1024 | semmle.label | 1024 |
94
| test.cpp:35:49:35:52 | 1024 | semmle.label | 1024 |
105
| test.cpp:37:43:37:46 | 1024 | semmle.label | 1024 |
11-
| test.cpp:37:43:37:46 | 1024 | semmle.label | 1024 |
126
subpaths
137
#select
148
| test.cpp:34:5:34:38 | call to EVP_PKEY_CTX_set_dsa_paramgen_bits | test.cpp:34:45:34:48 | 1024 | test.cpp:34:45:34:48 | 1024 | The key size $@ is less than the recommended key size of 2048 bits. | test.cpp:34:45:34:48 | 1024 | 1024 |

0 commit comments

Comments
 (0)