Skip to content

Commit deeaf70

Browse files
committed
C++: Map operand nodes that are only used once onto the related instruction node
Also revert the changes to default taint tracking and `TaintedAllocationSize.ql` as these are no longer needed with the above mapping.
1 parent bfe9ae2 commit deeaf70

File tree

12 files changed

+122
-32
lines changed

12 files changed

+122
-32
lines changed

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

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ private module Cached {
1818
// node for it.
1919
(not i.getResultType() instanceof VoidType or i.isGLValue())
2020
} or
21-
TOperandNode0(Operand op) { not Ssa::ignoreOperand(op) }
21+
TMultipleUseOperandNode0(Operand op) {
22+
not Ssa::ignoreOperand(op) and not exists(Ssa::getIRRepresentationOfOperand(op))
23+
} or
24+
TSingleUseOperandNode0(Operand op) {
25+
not Ssa::ignoreOperand(op) and exists(Ssa::getIRRepresentationOfOperand(op))
26+
}
2227
}
2328

2429
private import Cached
@@ -44,7 +49,10 @@ class Node0Impl extends TIRDataFlowNode0 {
4449
Instruction asInstruction() { result = this.(InstructionNode0).getInstruction() }
4550

4651
/** Gets the operands corresponding to this node, if any. */
47-
Operand asOperand() { result = this.(OperandNode0).getOperand() }
52+
Operand asOperand() {
53+
result = this.(MultipleUseOperandNode0).getOperand() or
54+
result = this.(SingleUseOperandNode0).getOperand()
55+
}
4856

4957
/** INTERNAL: Do not use. */
5058
Location getLocationImpl() {
@@ -92,11 +100,9 @@ class InstructionNode0 extends Node0Impl, TInstructionNode0 {
92100
/**
93101
* An operand, viewed as a node in a data flow graph.
94102
*/
95-
class OperandNode0 extends Node0Impl, TOperandNode0 {
103+
abstract class OperandNode0 extends Node0Impl {
96104
Operand op;
97105

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

@@ -111,6 +117,20 @@ class OperandNode0 extends Node0Impl, TOperandNode0 {
111117
override string toStringImpl() { result = this.getOperand().toString() }
112118
}
113119

120+
/**
121+
* An operand that is used multiple times, viewed as a node in a data flow graph.
122+
*/
123+
class MultipleUseOperandNode0 extends OperandNode0, TMultipleUseOperandNode0 {
124+
MultipleUseOperandNode0() { this = TMultipleUseOperandNode0(op) }
125+
}
126+
127+
/**
128+
* An operand that is used only once, viewed as a node in a data flow graph.
129+
*/
130+
class SingleUseOperandNode0 extends OperandNode0, TSingleUseOperandNode0 {
131+
SingleUseOperandNode0() { this = TSingleUseOperandNode0(op) }
132+
}
133+
114134
/**
115135
* INTERNAL: Do not use.
116136
*

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

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,10 +356,16 @@ private class Node0 extends Node, TNode0 {
356356
* An instruction, viewed as a node in a data flow graph.
357357
*/
358358
class InstructionNode extends Node0 {
359-
override InstructionNode0 node;
360359
Instruction instr;
361360

362-
InstructionNode() { instr = node.getInstruction() }
361+
InstructionNode() {
362+
node.(InstructionNode0).getInstruction() = instr
363+
or
364+
exists(Operand op |
365+
instr = Ssa::getIRRepresentationOfOperand(op) and
366+
node.(SingleUseOperandNode0).getOperand() = op
367+
)
368+
}
363369

364370
/** Gets the instruction corresponding to this node. */
365371
Instruction getInstruction() { result = instr }
@@ -377,7 +383,7 @@ class OperandNode extends Node, Node0 {
377383
OperandNode() { op = node.getOperand() }
378384

379385
/** Gets the operand corresponding to this node. */
380-
Operand getOperand() { result = node.getOperand() }
386+
Operand getOperand() { result = op }
381387

382388
override string toStringImpl() { result = op.getDef().getAst().toString() }
383389
}

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

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -168,18 +168,16 @@ private predicate hasUpperBoundsCheck(Variable var) {
168168
private predicate nodeIsBarrierEqualityCandidate(
169169
DataFlow::Node node, Operand access, Variable checkedVar
170170
) {
171-
exists(Instruction instr | instr = node.asOperand().getDef() |
172-
readsVariable(instr, checkedVar) and
173-
any(IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
174-
)
171+
readsVariable(node.asInstruction(), checkedVar) and
172+
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
175173
}
176174

177175
cached
178176
private module Cached {
179177
cached
180178
predicate nodeIsBarrier(DataFlow::Node node) {
181-
exists(Variable checkedVar, Instruction instr | instr = node.asOperand().getDef() |
182-
readsVariable(instr, checkedVar) and
179+
exists(Variable checkedVar |
180+
readsVariable(node.asInstruction(), checkedVar) and
183181
hasUpperBoundsCheck(checkedVar)
184182
)
185183
or

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,18 @@ private module Cached {
607607
)
608608
}
609609

610+
/**
611+
* Holds if the underlying IR has a suitable instruction to represent a value
612+
* that would otherwise need to be represented by a dedicated `OperandNode` value.
613+
*
614+
* Such operands do not create new `OperandNode` values, but are
615+
* instead associated with the instruction returned by this predicate.
616+
*/
617+
cached
618+
Instruction getIRRepresentationOfOperand(Operand operand) {
619+
operand = unique( | | result.getAUse())
620+
}
621+
610622
/**
611623
* Holds if the underlying IR has a suitable operand to represent a value
612624
* that would otherwise need to be represented by a dedicated `RawIndirectOperand` value.
@@ -627,7 +639,7 @@ private module Cached {
627639
* Holds if the underlying IR has a suitable instruction to represent a value
628640
* that would otherwise need to be represented by a dedicated `RawIndirectInstruction` value.
629641
*
630-
* Such instruction do not create new `RawIndirectOperand` values, but are
642+
* Such instructions do not create new `RawIndirectOperand` values, but are
631643
* instead associated with the instruction returned by this predicate.
632644
*/
633645
cached

cpp/ql/src/Security/CWE/CWE-190/TaintedAllocationSize.ql

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,8 @@ predicate hasUpperBoundsCheck(Variable var) {
4646
}
4747

4848
predicate nodeIsBarrierEqualityCandidate(DataFlow::Node node, Operand access, Variable checkedVar) {
49-
exists(Instruction instr | instr = node.asOperand().getDef() |
50-
readsVariable(instr, checkedVar) and
51-
any(IRGuardCondition guard).ensuresEq(access, _, _, instr.getBlock(), true)
52-
)
49+
readsVariable(node.asInstruction(), checkedVar) and
50+
any(IRGuardCondition guard).ensuresEq(access, _, _, node.asInstruction().getBlock(), true)
5351
}
5452

5553
predicate isFlowSource(FlowSource source, string sourceType) { sourceType = source.getSourceType() }
@@ -81,8 +79,8 @@ class TaintedAllocationSizeConfiguration extends TaintTracking::Configuration {
8179
e = any(PointerDiffExpr diff).getAnOperand()
8280
)
8381
or
84-
exists(Variable checkedVar, Instruction instr | instr = node.asOperand().getDef() |
85-
readsVariable(instr, checkedVar) and
82+
exists(Variable checkedVar |
83+
readsVariable(node.asInstruction(), checkedVar) and
8684
hasUpperBoundsCheck(checkedVar)
8785
)
8886
or

cpp/ql/test/query-tests/Security/CWE/CWE-078/semmle/ExecTainted/ExecTainted.expected

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@ edges
1616
| test.cpp:93:11:93:14 | strncat output argument | test.cpp:94:45:94:48 | array to pointer conversion indirection |
1717
| test.cpp:93:17:93:24 | (const char *)... indirection | test.cpp:93:11:93:14 | strncat output argument |
1818
| test.cpp:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | (reference to) indirection |
19+
| test.cpp:106:20:106:25 | call to getenv | test.cpp:107:33:107:36 | (reference to) indirection |
1920
| test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:107:33:107:36 | (reference to) indirection |
2021
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection |
2122
| test.cpp:107:33:107:36 | (reference to) indirection | test.cpp:107:31:107:31 | call to operator+ |
23+
| test.cpp:107:33:107:36 | (reference to) indirection | test.cpp:108:18:108:22 | call to c_str indirection |
24+
| test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | (reference to) indirection |
2225
| test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | (reference to) indirection |
2326
| test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:19:114:22 | (reference to) indirection |
2427
| test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... | test.cpp:114:25:114:29 | call to c_str indirection |
2528
| test.cpp:114:17:114:17 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection |
2629
| test.cpp:114:19:114:22 | (reference to) indirection | test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... |
2730
| test.cpp:114:19:114:22 | (reference to) indirection | test.cpp:114:17:114:17 | call to operator+ |
2831
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | (reference to) indirection |
32+
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | (reference to) indirection |
2933
| test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:19:120:22 | (reference to) indirection |
3034
| test.cpp:120:17:120:17 | call to operator+ | test.cpp:120:10:120:30 | call to data indirection |
3135
| test.cpp:120:19:120:22 | (reference to) indirection | test.cpp:120:17:120:17 | call to operator+ |
@@ -123,18 +127,21 @@ nodes
123127
| test.cpp:93:17:93:24 | (const char *)... indirection | semmle.label | (const char *)... indirection |
124128
| test.cpp:94:45:94:48 | array to pointer conversion indirection | semmle.label | array to pointer conversion indirection |
125129
| test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv |
130+
| test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv |
126131
| test.cpp:106:20:106:38 | call to getenv indirection | semmle.label | call to getenv indirection |
127132
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
128133
| test.cpp:107:33:107:36 | (reference to) indirection | semmle.label | (reference to) indirection |
129134
| test.cpp:108:18:108:22 | call to c_str indirection | semmle.label | call to c_str indirection |
130135
| test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv |
136+
| test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv |
131137
| test.cpp:113:20:113:38 | call to getenv indirection | semmle.label | call to getenv indirection |
132138
| test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... | semmle.label | (const basic_string<char, char_traits<char>, allocator<char>>)... |
133139
| test.cpp:114:17:114:17 | call to operator+ | semmle.label | call to operator+ |
134140
| test.cpp:114:19:114:22 | (reference to) indirection | semmle.label | (reference to) indirection |
135141
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
136142
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
137143
| test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv |
144+
| test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv |
138145
| test.cpp:119:20:119:38 | call to getenv indirection | semmle.label | call to getenv indirection |
139146
| test.cpp:120:10:120:30 | call to data indirection | semmle.label | call to data indirection |
140147
| test.cpp:120:17:120:17 | call to operator+ | semmle.label | call to operator+ |
@@ -218,12 +225,19 @@ subpaths
218225
| test.cpp:85:32:85:38 | command | test.cpp:82:9:82:16 | fread output argument | test.cpp:85:32:85:38 | array to pointer conversion indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:82:9:82:16 | fread output argument | user input (string read by fread) | test.cpp:84:11:84:17 | strncat output argument | strncat output argument |
219226
| test.cpp:94:45:94:48 | path | test.cpp:91:9:91:16 | fread output argument | test.cpp:94:45:94:48 | array to pointer conversion indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:91:9:91:16 | fread output argument | user input (string read by fread) | test.cpp:93:11:93:14 | strncat output argument | strncat output argument |
220227
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
228+
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
229+
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
230+
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:25 | call to getenv | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:25 | call to getenv | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
231+
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv indirection | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
221232
| test.cpp:108:18:108:22 | call to c_str | test.cpp:106:20:106:38 | call to getenv indirection | test.cpp:108:18:108:22 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:106:20:106:38 | call to getenv indirection | user input (an environment variable) | test.cpp:107:31:107:31 | call to operator+ | call to operator+ |
222233
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... | (const basic_string<char, char_traits<char>, allocator<char>>)... |
234+
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... | (const basic_string<char, char_traits<char>, allocator<char>>)... |
235+
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
223236
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:25 | call to getenv | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:25 | call to getenv | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
224237
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... | (const basic_string<char, char_traits<char>, allocator<char>>)... |
225238
| test.cpp:114:25:114:29 | call to c_str | test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:25:114:29 | call to c_str indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:113:20:113:38 | call to getenv indirection | user input (an environment variable) | test.cpp:114:17:114:17 | call to operator+ | call to operator+ |
226239
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
240+
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:25 | call to getenv | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:25 | call to getenv | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
227241
| test.cpp:120:25:120:28 | call to data | test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:10:120:30 | call to data indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:119:20:119:38 | call to getenv indirection | user input (an environment variable) | test.cpp:120:17:120:17 | call to operator+ | call to operator+ |
228242
| test.cpp:143:10:143:16 | command | test.cpp:140:9:140:11 | fread output argument | test.cpp:143:10:143:16 | (const char *)... indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to system(string). | test.cpp:140:9:140:11 | fread output argument | user input (string read by fread) | test.cpp:142:11:142:17 | sprintf output argument | sprintf output argument |
229243
| test.cpp:183:32:183:38 | command | test.cpp:174:9:174:16 | fread output argument | test.cpp:183:32:183:38 | array to pointer conversion indirection | This argument to an OS command is derived from $@, dangerously concatenated into $@, and then passed to execl. | test.cpp:174:9:174:16 | fread output argument | user input (string read by fread) | test.cpp:177:13:177:17 | strncat output argument | strncat output argument |

0 commit comments

Comments
 (0)