Skip to content

Commit c80a06a

Browse files
committed
Ruby: Simplify posix-spawn modeling
1 parent ee82760 commit c80a06a

File tree

4 files changed

+47
-39
lines changed

4 files changed

+47
-39
lines changed

ruby/ql/lib/codeql/ruby/frameworks/PosixSpawn.qll

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,12 @@ module PosixSpawn {
4141
*/
4242
class SystemCall extends SystemCommandExecution::Range, DataFlow::CallNode {
4343
SystemCall() {
44-
exists(API::Node spawn | spawn = API::getTopLevelMember("POSIX").getMember("Spawn") |
45-
this =
46-
posixSpawnModule()
47-
.getAMethodCall(["spawn", "fspawn", "popen4", "pspawn", "system", "_pspawn", "`"])
48-
)
44+
this =
45+
posixSpawnModule()
46+
.getAMethodCall(["spawn", "fspawn", "popen4", "pspawn", "system", "_pspawn", "`"])
4947
}
5048

51-
override DataFlow::Node getAnArgument() { this.argument(result, _) }
49+
override DataFlow::Node getAnArgument() { this.argument(result) }
5250

5351
// From the docs:
5452
// When only command is given and includes a space character, the command
@@ -64,15 +62,16 @@ module PosixSpawn {
6462
// is shell interpreted unless there is another argument with a string
6563
// constant value.
6664
override predicate isShellInterpreted(DataFlow::Node arg) {
67-
exists(int n, int m, DataFlow::Node otherArg |
68-
this.argument(arg, n) and
69-
this.argument(otherArg, m) and
65+
not exists(DataFlow::Node otherArg |
66+
otherArg != arg and
67+
this.argument(arg) and
68+
this.argument(otherArg) and
7069
otherArg.asExpr().getConstantValue().isString(_)
7170
)
7271
}
7372

74-
private predicate argument(DataFlow::Node arg, int n) {
75-
arg = this.getArgument(n) and
73+
private predicate argument(DataFlow::Node arg) {
74+
arg = this.getArgument(_) and
7675
not arg.asExpr() instanceof ExprNodes::HashLiteralCfgNode and
7776
not arg.asExpr() instanceof ExprNodes::ArrayLiteralCfgNode and
7877
not arg.asExpr() instanceof ExprNodes::PairCfgNode
Lines changed: 27 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
11
systemCalls
2-
| PosixSpawn.rb:1:1:1:32 | call to popen4 | PosixSpawn.rb:1:22:1:25 | "ls" |
3-
| PosixSpawn.rb:1:1:1:32 | call to popen4 | PosixSpawn.rb:1:28:1:31 | "-l" |
4-
| PosixSpawn.rb:2:1:2:31 | call to popen4 | PosixSpawn.rb:2:21:2:24 | "ls" |
5-
| PosixSpawn.rb:2:1:2:31 | call to popen4 | PosixSpawn.rb:2:27:2:30 | "-l" |
6-
| PosixSpawn.rb:7:1:7:40 | call to spawn | PosixSpawn.rb:7:20:7:39 | * ... |
7-
| PosixSpawn.rb:8:1:8:30 | call to spawn | PosixSpawn.rb:8:21:8:29 | "sleep 5" |
8-
| PosixSpawn.rb:13:1:13:60 | call to system | PosixSpawn.rb:13:21:13:25 | "foo" |
9-
| PosixSpawn.rb:13:1:13:60 | call to system | PosixSpawn.rb:13:28:13:32 | "bar" |
10-
| PosixSpawn.rb:13:1:13:60 | call to system | PosixSpawn.rb:13:35:13:44 | "--a-flag" |
11-
| PosixSpawn.rb:13:1:13:60 | call to system | PosixSpawn.rb:13:47:13:52 | call to before |
12-
| PosixSpawn.rb:13:1:13:60 | call to system | PosixSpawn.rb:13:55:13:59 | call to after |
13-
| PosixSpawn.rb:15:1:15:28 | call to fspawn | PosixSpawn.rb:15:21:15:27 | call to command |
14-
| PosixSpawn.rb:16:1:16:28 | call to pspawn | PosixSpawn.rb:16:21:16:27 | call to command |
15-
| PosixSpawn.rb:17:1:17:28 | call to popen4 | PosixSpawn.rb:17:21:17:27 | call to command |
16-
| PosixSpawn.rb:19:1:19:28 | call to ` | PosixSpawn.rb:19:16:19:20 | "foo" |
17-
| PosixSpawn.rb:19:1:19:28 | call to ` | PosixSpawn.rb:19:23:19:27 | "bar" |
2+
| PosixSpawn.rb:1:1:1:32 | call to popen4 | PosixSpawn.rb:1:22:1:25 | "ls" | false |
3+
| PosixSpawn.rb:1:1:1:32 | call to popen4 | PosixSpawn.rb:1:28:1:31 | "-l" | false |
4+
| PosixSpawn.rb:2:1:2:31 | call to popen4 | PosixSpawn.rb:2:21:2:24 | "ls" | false |
5+
| PosixSpawn.rb:2:1:2:31 | call to popen4 | PosixSpawn.rb:2:27:2:30 | "-l" | false |
6+
| PosixSpawn.rb:7:1:7:40 | call to spawn | PosixSpawn.rb:7:20:7:39 | * ... | true |
7+
| PosixSpawn.rb:8:1:8:30 | call to spawn | PosixSpawn.rb:8:21:8:29 | "sleep 5" | true |
8+
| PosixSpawn.rb:9:1:9:23 | call to spawn | PosixSpawn.rb:9:20:9:22 | call to cmd | true |
9+
| PosixSpawn.rb:10:1:10:29 | call to spawn | PosixSpawn.rb:10:20:10:22 | call to env | false |
10+
| PosixSpawn.rb:10:1:10:29 | call to spawn | PosixSpawn.rb:10:25:10:28 | "ls" | true |
11+
| PosixSpawn.rb:15:1:15:60 | call to system | PosixSpawn.rb:15:21:15:25 | "foo" | false |
12+
| PosixSpawn.rb:15:1:15:60 | call to system | PosixSpawn.rb:15:28:15:32 | "bar" | false |
13+
| PosixSpawn.rb:15:1:15:60 | call to system | PosixSpawn.rb:15:35:15:44 | "--a-flag" | false |
14+
| PosixSpawn.rb:15:1:15:60 | call to system | PosixSpawn.rb:15:47:15:52 | call to before | false |
15+
| PosixSpawn.rb:15:1:15:60 | call to system | PosixSpawn.rb:15:55:15:59 | call to after | false |
16+
| PosixSpawn.rb:17:1:17:28 | call to fspawn | PosixSpawn.rb:17:21:17:27 | call to command | true |
17+
| PosixSpawn.rb:18:1:18:28 | call to pspawn | PosixSpawn.rb:18:21:18:27 | call to command | true |
18+
| PosixSpawn.rb:19:1:19:28 | call to popen4 | PosixSpawn.rb:19:21:19:27 | call to command | true |
19+
| PosixSpawn.rb:21:1:21:28 | call to ` | PosixSpawn.rb:21:16:21:20 | "foo" | false |
20+
| PosixSpawn.rb:21:1:21:28 | call to ` | PosixSpawn.rb:21:23:21:27 | "bar" | false |
1821
childCalls
19-
| PosixSpawn.rb:4:1:4:77 | call to new | PosixSpawn.rb:4:25:4:39 | call to [] |
20-
| PosixSpawn.rb:4:1:4:77 | call to new | PosixSpawn.rb:4:42:4:51 | ... + ... |
21-
| PosixSpawn.rb:4:1:4:77 | call to new | PosixSpawn.rb:4:54:4:58 | * ... |
22-
| PosixSpawn.rb:5:1:5:80 | call to new | PosixSpawn.rb:5:25:5:32 | * ... |
23-
| PosixSpawn.rb:10:1:10:35 | call to new | PosixSpawn.rb:10:25:10:28 | "ls" |
24-
| PosixSpawn.rb:10:1:10:35 | call to new | PosixSpawn.rb:10:31:10:34 | "-l" |
25-
| PosixSpawn.rb:11:1:11:38 | call to build | PosixSpawn.rb:11:27:11:32 | "echo" |
26-
| PosixSpawn.rb:11:1:11:38 | call to build | PosixSpawn.rb:11:35:11:37 | call to msg |
22+
| PosixSpawn.rb:4:1:4:77 | call to new | PosixSpawn.rb:4:25:4:39 | call to [] | false |
23+
| PosixSpawn.rb:4:1:4:77 | call to new | PosixSpawn.rb:4:42:4:51 | ... + ... | false |
24+
| PosixSpawn.rb:4:1:4:77 | call to new | PosixSpawn.rb:4:54:4:58 | * ... | false |
25+
| PosixSpawn.rb:5:1:5:80 | call to new | PosixSpawn.rb:5:25:5:32 | * ... | false |
26+
| PosixSpawn.rb:12:1:12:35 | call to new | PosixSpawn.rb:12:25:12:28 | "ls" | false |
27+
| PosixSpawn.rb:12:1:12:35 | call to new | PosixSpawn.rb:12:31:12:34 | "-l" | false |
28+
| PosixSpawn.rb:13:1:13:38 | call to build | PosixSpawn.rb:13:27:13:32 | "echo" | false |
29+
| PosixSpawn.rb:13:1:13:38 | call to build | PosixSpawn.rb:13:35:13:37 | call to msg | false |

ruby/ql/test/library-tests/frameworks/PosixSpawn.ql

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,14 @@ import ruby
22
import codeql.ruby.frameworks.PosixSpawn
33
import codeql.ruby.DataFlow
44

5-
query predicate systemCalls(PosixSpawn::SystemCall call, DataFlow::Node arg) {
6-
arg = call.getAnArgument()
5+
query predicate systemCalls(
6+
PosixSpawn::SystemCall call, DataFlow::Node arg, boolean shellInterpreted
7+
) {
8+
arg = call.getAnArgument() and
9+
if call.isShellInterpreted(arg) then shellInterpreted = true else shellInterpreted = false
710
}
811

9-
query predicate childCalls(PosixSpawn::ChildCall call, DataFlow::Node arg) {
10-
arg = call.getAnArgument()
12+
query predicate childCalls(PosixSpawn::ChildCall call, DataFlow::Node arg, boolean shellInterpreted) {
13+
arg = call.getAnArgument() and
14+
if call.isShellInterpreted(arg) then shellInterpreted = true else shellInterpreted = false
1115
}

ruby/ql/test/library-tests/frameworks/PosixSpawn.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
POSIX::Spawn.spawn(*(argv+[{:in => f}]))
88
POSIX::Spawn::spawn('sleep 5')
9+
POSIX::Spawn.spawn(cmd)
10+
POSIX::Spawn.spawn(env, "ls")
911

1012
POSIX::Spawn::Child.new("ls", "-l")
1113
POSIX::Spawn::Child.build("echo", msg)

0 commit comments

Comments
 (0)