Skip to content

Commit a3e1f54

Browse files
committed
C++: Refactor models to prevent IR reevaluation
1 parent 509a349 commit a3e1f54

File tree

4 files changed

+63
-36
lines changed

4 files changed

+63
-36
lines changed

cpp/ql/lib/semmle/code/cpp/models/Models.qll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,4 @@ private import implementations.Recv
3333
private import implementations.Accept
3434
private import implementations.Poll
3535
private import implementations.Select
36+
private import implementations.System
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import cpp
2+
import semmle.code.cpp.security.FunctionWithWrappers
3+
import semmle.code.cpp.models.interfaces.SideEffect
4+
import semmle.code.cpp.models.interfaces.Alias
5+
import semmle.code.cpp.models.interfaces.CommandExecution
6+
7+
/**
8+
* A function for running a command using a command interpreter.
9+
*/
10+
private class SystemFunction extends CommandExecutionFunction, ArrayFunction, AliasFunction,
11+
SideEffectFunction {
12+
SystemFunction() {
13+
hasGlobalOrStdName("system") or // system(command)
14+
hasGlobalName("popen") or // popen(command, mode)
15+
// Windows variants
16+
hasGlobalName("_popen") or // _popen(command, mode)
17+
hasGlobalName("_wpopen") or // _wpopen(command, mode)
18+
hasGlobalName("_wsystem") // _wsystem(command)
19+
}
20+
21+
override predicate hasCommandArgument(FunctionInput input) { input.isParameterDeref(0) }
22+
23+
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 or bufParam = 1 }
24+
25+
override predicate hasArrayInput(int bufParam) { bufParam = 0 or bufParam = 1 }
26+
27+
override predicate parameterNeverEscapes(int index) { index = 0 or index = 1 }
28+
29+
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
30+
31+
override predicate parameterIsAlwaysReturned(int index) { none() }
32+
33+
override predicate hasOnlySpecificReadSideEffects() { any() }
34+
35+
override predicate hasOnlySpecificWriteSideEffects() {
36+
hasGlobalOrStdName("system") or
37+
hasGlobalName("_wsystem")
38+
}
39+
40+
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
41+
(i = 0 or i = 1) and
42+
buffer = true
43+
}
44+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import cpp
2+
import FunctionInputsAndOutputs
3+
import semmle.code.cpp.models.Models
4+
5+
abstract class CommandExecutionFunction extends Function {
6+
abstract predicate hasCommandArgument(FunctionInput input);
7+
}

cpp/ql/lib/semmle/code/cpp/security/CommandExecution.qll

Lines changed: 11 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,42 +4,17 @@ import cpp
44
import semmle.code.cpp.security.FunctionWithWrappers
55
import semmle.code.cpp.models.interfaces.SideEffect
66
import semmle.code.cpp.models.interfaces.Alias
7+
import semmle.code.cpp.models.interfaces.CommandExecution
78

8-
/**
9-
* A function for running a command using a command interpreter.
10-
*/
11-
class SystemFunction extends FunctionWithWrappers, ArrayFunction, AliasFunction, SideEffectFunction {
12-
SystemFunction() {
13-
hasGlobalOrStdName("system") or // system(command)
14-
hasGlobalName("popen") or // popen(command, mode)
15-
// Windows variants
16-
hasGlobalName("_popen") or // _popen(command, mode)
17-
hasGlobalName("_wpopen") or // _wpopen(command, mode)
18-
hasGlobalName("_wsystem") // _wsystem(command)
19-
}
20-
21-
override predicate interestingArg(int arg) { arg = 0 }
22-
23-
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 or bufParam = 1 }
24-
25-
override predicate hasArrayInput(int bufParam) { bufParam = 0 or bufParam = 1 }
26-
27-
override predicate parameterNeverEscapes(int index) { index = 0 or index = 1 }
28-
29-
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
30-
31-
override predicate parameterIsAlwaysReturned(int index) { none() }
32-
33-
override predicate hasOnlySpecificReadSideEffects() { any() }
34-
35-
override predicate hasOnlySpecificWriteSideEffects() {
36-
hasGlobalOrStdName("system") or
37-
hasGlobalName("_wsystem")
38-
}
39-
40-
override predicate hasSpecificReadSideEffect(ParameterIndex i, boolean buffer) {
41-
(i = 0 or i = 1) and
42-
buffer = true
9+
class WrappedSystemFunction extends FunctionWithWrappers instanceof CommandExecutionFunction {
10+
override predicate interestingArg(int arg) {
11+
exists(FunctionInput input |
12+
this.(CommandExecutionFunction).hasCommandArgument(input) and
13+
(
14+
input.isParameterDerefOrQualifierObject(arg) or
15+
input.isParameterOrQualifierAddress(arg)
16+
)
17+
)
4318
}
4419
}
4520

@@ -185,7 +160,7 @@ predicate shellCommandPreface(string cmd, string flag) {
185160
*/
186161
predicate shellCommand(Expr command, string callChain) {
187162
// A call to a function like system()
188-
exists(SystemFunction systemFunction |
163+
exists(WrappedSystemFunction systemFunction |
189164
systemFunction.outermostWrapperFunctionCall(command, callChain)
190165
)
191166
or

0 commit comments

Comments
 (0)