Skip to content

Commit 2737961

Browse files
committed
C++: Map operand nodes that are only used once onto the related instruction node
1 parent ce8a84a commit 2737961

File tree

10 files changed

+114
-19
lines changed

10 files changed

+114
-19
lines changed

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

Lines changed: 21 additions & 4 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
@@ -92,11 +97,9 @@ class InstructionNode0 extends Node0Impl, TInstructionNode0 {
9297
/**
9398
* An operand, viewed as a node in a data flow graph.
9499
*/
95-
class OperandNode0 extends Node0Impl, TOperandNode0 {
100+
abstract class OperandNode0 extends Node0Impl {
96101
Operand op;
97102

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

@@ -111,6 +114,20 @@ class OperandNode0 extends Node0Impl, TOperandNode0 {
111114
override string toStringImpl() { result = this.getOperand().toString() }
112115
}
113116

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

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
@@ -366,10 +366,16 @@ private class Node0 extends Node, TNode0 {
366366
* An instruction, viewed as a node in a data flow graph.
367367
*/
368368
class InstructionNode extends Node0 {
369-
override InstructionNode0 node;
370369
Instruction instr;
371370

372-
InstructionNode() { instr = node.getInstruction() }
371+
InstructionNode() {
372+
node.(InstructionNode0).getInstruction() = instr
373+
or
374+
exists(Operand op |
375+
instr = Ssa::getIRRepresentationOfOperand(op) and
376+
node.(SingleUseOperandNode0).getOperand() = op
377+
)
378+
}
373379

374380
/** Gets the instruction corresponding to this node. */
375381
Instruction getInstruction() { result = instr }
@@ -387,7 +393,7 @@ class OperandNode extends Node, Node0 {
387393
OperandNode() { op = node.getOperand() }
388394

389395
/** Gets the operand corresponding to this node. */
390-
Operand getOperand() { result = node.getOperand() }
396+
Operand getOperand() { result = op }
391397

392398
override string toStringImpl() { result = op.getDef().getAst().toString() }
393399
}

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
@@ -620,6 +620,18 @@ private module Cached {
620620
)
621621
}
622622

623+
/**
624+
* Holds if the underlying IR has a suitable instruction to represent a value
625+
* that would otherwise need to be represented by a dedicated `OperandNode` value.
626+
*
627+
* Such operands do not create new `OperandNode` values, but are
628+
* instead associated with the instruction returned by this predicate.
629+
*/
630+
cached
631+
Instruction getIRRepresentationOfOperand(Operand operand) {
632+
operand = unique( | | result.getAUse())
633+
}
634+
623635
/**
624636
* Holds if the underlying IR has a suitable operand to represent a value
625637
* that would otherwise need to be represented by a dedicated `RawIndirectOperand` value.
@@ -640,7 +652,7 @@ private module Cached {
640652
* Holds if the underlying IR has a suitable instruction to represent a value
641653
* that would otherwise need to be represented by a dedicated `RawIndirectInstruction` value.
642654
*
643-
* Such instruction do not create new `RawIndirectOperand` values, but are
655+
* Such instructions do not create new `RawIndirectOperand` values, but are
644656
* instead associated with the instruction returned by this predicate.
645657
*/
646658
cached

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,21 @@ 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 |
22+
| test.cpp:107:31:107:31 | call to operator+ | test.cpp:108:18:108:22 | call to c_str indirection |
2123
| test.cpp:107:33:107:36 | (reference to) indirection | test.cpp:107:31:107:31 | call to operator+ |
24+
| test.cpp:107:33:107:36 | (reference to) indirection | test.cpp:107:31:107:31 | call to operator+ |
25+
| test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | (reference to) indirection |
2226
| test.cpp:113:20:113:25 | call to getenv | test.cpp:114:19:114:22 | (reference to) indirection |
2327
| test.cpp:113:20:113:38 | call to getenv indirection | test.cpp:114:19:114:22 | (reference to) indirection |
2428
| 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 |
2529
| test.cpp:114:17:114:17 | call to operator+ | test.cpp:114:25:114:29 | call to c_str indirection |
2630
| test.cpp:114:19:114:22 | (reference to) indirection | test.cpp:114:10:114:23 | (const basic_string<char, char_traits<char>, allocator<char>>)... |
2731
| test.cpp:114:19:114:22 | (reference to) indirection | test.cpp:114:17:114:17 | call to operator+ |
2832
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | (reference to) indirection |
33+
| test.cpp:119:20:119:25 | call to getenv | test.cpp:120:19:120:22 | (reference to) indirection |
2934
| test.cpp:119:20:119:38 | call to getenv indirection | test.cpp:120:19:120:22 | (reference to) indirection |
3035
| test.cpp:120:17:120:17 | call to operator+ | test.cpp:120:10:120:30 | call to data indirection |
3136
| test.cpp:120:19:120:22 | (reference to) indirection | test.cpp:120:17:120:17 | call to operator+ |
@@ -88,18 +93,22 @@ nodes
8893
| test.cpp:93:17:93:24 | (const char *)... indirection | semmle.label | (const char *)... indirection |
8994
| test.cpp:94:45:94:48 | array to pointer conversion indirection | semmle.label | array to pointer conversion indirection |
9095
| test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv |
96+
| test.cpp:106:20:106:25 | call to getenv | semmle.label | call to getenv |
9197
| test.cpp:106:20:106:38 | call to getenv indirection | semmle.label | call to getenv indirection |
9298
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
99+
| test.cpp:107:31:107:31 | call to operator+ | semmle.label | call to operator+ |
93100
| test.cpp:107:33:107:36 | (reference to) indirection | semmle.label | (reference to) indirection |
94101
| test.cpp:108:18:108:22 | call to c_str indirection | semmle.label | call to c_str indirection |
95102
| test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv |
103+
| test.cpp:113:20:113:25 | call to getenv | semmle.label | call to getenv |
96104
| test.cpp:113:20:113:38 | call to getenv indirection | semmle.label | call to getenv indirection |
97105
| 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>>)... |
98106
| test.cpp:114:17:114:17 | call to operator+ | semmle.label | call to operator+ |
99107
| test.cpp:114:19:114:22 | (reference to) indirection | semmle.label | (reference to) indirection |
100108
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
101109
| test.cpp:114:25:114:29 | call to c_str indirection | semmle.label | call to c_str indirection |
102110
| test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv |
111+
| test.cpp:119:20:119:25 | call to getenv | semmle.label | call to getenv |
103112
| test.cpp:119:20:119:38 | call to getenv indirection | semmle.label | call to getenv indirection |
104113
| test.cpp:120:10:120:30 | call to data indirection | semmle.label | call to data indirection |
105114
| test.cpp:120:17:120:17 | call to operator+ | semmle.label | call to operator+ |
@@ -152,12 +161,19 @@ subpaths
152161
| 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 |
153162
| 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 |
154163
| 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+ |
164+
| 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+ |
165+
| 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+ |
166+
| 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+ |
155167
| 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+ |
168+
| 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+ |
169+
| 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>>)... |
156170
| 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>>)... |
157171
| 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+ |
172+
| 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+ |
158173
| 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>>)... |
159174
| 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+ |
160175
| 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+ |
176+
| 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+ |
161177
| 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+ |
162178
| 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 |
163179
| 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)