Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit df37980

Browse files
committed
Ruby: support CSV rows of form ;any;Method[foo]
1 parent 05ea330 commit df37980

4 files changed

Lines changed: 56 additions & 0 deletions

File tree

ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModelsSpecific.qll

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,43 @@ API::Node getExtraNodeFromPath(string package, string type, AccessPath path, int
5353
type = "" and
5454
n = 0 and
5555
result = API::root()
56+
or
57+
// A row of form `;any;Method[foo]` should match any method named `foo`.
58+
package = any(string s) and
59+
type = "any" and
60+
n = 1 and
61+
exists(EntryPointFromAnyType entry |
62+
methodMatchedByName(path, entry.getName()) and
63+
result = entry.getNode()
64+
)
65+
}
66+
67+
/**
68+
* Holds if `path` occurs in a CSV row with type `any`, meaning it can start
69+
* matching anywhere, and the path begins with `Method[methodName]`.
70+
*/
71+
private predicate methodMatchedByName(AccessPath path, string methodName) {
72+
isRelevantFullPath(_, "any", path) and
73+
exists(AccessPathToken token |
74+
token = path.getToken(0) and
75+
token.getName() = "Method" and
76+
methodName = token.getAnArgument()
77+
)
78+
}
79+
80+
/**
81+
* An API graph entry point corresponding to a method name such as `foo` in `;any;Method[foo]`.
82+
*
83+
* This ensures that the API graph rooted in that method call is materialized.
84+
*/
85+
private class EntryPointFromAnyType extends API::EntryPoint {
86+
string name;
87+
88+
EntryPointFromAnyType() { this = "AnyMethod[" + name + "]" and methodMatchedByName(_, name) }
89+
90+
override DataFlow::CallNode getACall() { result.getMethodName() = name }
91+
92+
string getName() { result = name }
5693
}
5794

5895
/**

ruby/ql/test/library-tests/dataflow/summaries/Summaries.expected

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ edges
2525
| summaries.rb:26:31:26:37 | tainted : | summaries.rb:26:12:26:38 | call to secondArg : |
2626
| summaries.rb:30:24:30:30 | tainted : | summaries.rb:30:6:30:42 | call to onlyWithBlock |
2727
| summaries.rb:31:27:31:33 | tainted : | summaries.rb:31:6:31:34 | call to onlyWithoutBlock |
28+
| summaries.rb:40:7:40:13 | "taint" : | summaries.rb:41:24:41:24 | t : |
29+
| summaries.rb:40:7:40:13 | "taint" : | summaries.rb:42:24:42:24 | t : |
30+
| summaries.rb:41:24:41:24 | t : | summaries.rb:41:8:41:25 | call to matchedByName |
31+
| summaries.rb:42:24:42:24 | t : | summaries.rb:42:8:42:25 | call to matchedByName |
2832
nodes
2933
| summaries.rb:1:11:1:26 | call to identity : | semmle.label | call to identity : |
3034
| summaries.rb:1:20:1:26 | "taint" : | semmle.label | "taint" : |
@@ -53,6 +57,11 @@ nodes
5357
| summaries.rb:35:16:35:22 | tainted | semmle.label | tainted |
5458
| summaries.rb:36:21:36:27 | tainted | semmle.label | tainted |
5559
| summaries.rb:37:36:37:42 | tainted | semmle.label | tainted |
60+
| summaries.rb:40:7:40:13 | "taint" : | semmle.label | "taint" : |
61+
| summaries.rb:41:8:41:25 | call to matchedByName | semmle.label | call to matchedByName |
62+
| summaries.rb:41:24:41:24 | t : | semmle.label | t : |
63+
| summaries.rb:42:8:42:25 | call to matchedByName | semmle.label | call to matchedByName |
64+
| summaries.rb:42:24:42:24 | t : | semmle.label | t : |
5665
subpaths
5766
invalidSpecComponent
5867
invalidOutputSpecComponent
@@ -70,3 +79,5 @@ invalidOutputSpecComponent
7079
| summaries.rb:35:16:35:22 | tainted | summaries.rb:1:20:1:26 | "taint" : | summaries.rb:35:16:35:22 | tainted | $@ | summaries.rb:1:20:1:26 | "taint" : | "taint" : |
7180
| summaries.rb:36:21:36:27 | tainted | summaries.rb:1:20:1:26 | "taint" : | summaries.rb:36:21:36:27 | tainted | $@ | summaries.rb:1:20:1:26 | "taint" : | "taint" : |
7281
| summaries.rb:37:36:37:42 | tainted | summaries.rb:1:20:1:26 | "taint" : | summaries.rb:37:36:37:42 | tainted | $@ | summaries.rb:1:20:1:26 | "taint" : | "taint" : |
82+
| summaries.rb:41:8:41:25 | call to matchedByName | summaries.rb:40:7:40:13 | "taint" : | summaries.rb:41:8:41:25 | call to matchedByName | $@ | summaries.rb:40:7:40:13 | "taint" : | "taint" : |
83+
| summaries.rb:42:8:42:25 | call to matchedByName | summaries.rb:40:7:40:13 | "taint" : | summaries.rb:42:8:42:25 | call to matchedByName | $@ | summaries.rb:40:7:40:13 | "taint" : | "taint" : |

ruby/ql/test/library-tests/dataflow/summaries/Summaries.ql

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ private class StepsFromModel extends ModelInput::SummaryModelCsv {
7373
";;Member[Foo].Method[secondArg];Argument[1];ReturnValue;taint",
7474
";;Member[Foo].Method[onlyWithoutBlock].WithoutBlock;Argument[0];ReturnValue;taint",
7575
";;Member[Foo].Method[onlyWithBlock].WithBlock;Argument[0];ReturnValue;taint",
76+
";any;Method[matchedByName];Argument[0];ReturnValue;taint"
7677
]
7778
}
7879
}

ruby/ql/test/library-tests/dataflow/summaries/summaries.rb

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,10 @@
3535
Bar.new.method(tainted)
3636
Bar.new.next.method(tainted)
3737
Bar.new.next.next.next.next.method(tainted)
38+
39+
def userDefinedFunction(x, y)
40+
t = "taint"
41+
sink(x.matchedByName(t))
42+
sink(y.matchedByName(t))
43+
sink(x.unmatchedName(t))
44+
end

0 commit comments

Comments
 (0)