Skip to content

Commit 1b49bfe

Browse files
authored
Merge pull request github#11497 from alexrford/ruby/rails_globalid
Ruby: model `rails/globalid` component
2 parents 1500fa5 + 2af5925 commit 1b49bfe

File tree

5 files changed

+278
-0
lines changed

5 files changed

+278
-0
lines changed
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
category: minorAnalysis
3+
---
4+
* Calls to `GlobalID::Locator.locate` and its variants are now recognized as instances of `OrmInstantiation`.
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
/**
2+
* Provides modeling for `GlobalID`, a library for identifying model instances by URI.
3+
* Version: 1.0.0
4+
* https://github.com/rails/globalid
5+
*/
6+
7+
private import codeql.ruby.ApiGraphs
8+
private import codeql.ruby.Concepts
9+
private import codeql.ruby.DataFlow
10+
private import codeql.ruby.frameworks.ActiveRecord
11+
12+
/**
13+
* Provides modeling for `GlobalID`, a library for identifying model instances by URI.
14+
* Version: 1.0.0
15+
* https://github.com/rails/globalid
16+
*/
17+
module GlobalId {
18+
/** A call to `GlobalID::parse` */
19+
class ParseCall extends DataFlow::CallNode {
20+
ParseCall() { this = API::getTopLevelMember("GlobalID").getAMethodCall("parse") }
21+
}
22+
23+
/** A call to `GlobalID::find` */
24+
class FindCall extends DataFlow::CallNode, OrmInstantiation::Range {
25+
FindCall() { this = API::getTopLevelMember("GlobalID").getAMethodCall("find") }
26+
27+
override predicate methodCallMayAccessField(string methodName) { none() }
28+
}
29+
30+
/** `GlobalID::Locator` */
31+
module Locator {
32+
/** A call to `GlobalID::Locator.locate` */
33+
class LocateCall extends DataFlow::CallNode, OrmInstantiation::Range {
34+
LocateCall() {
35+
this = API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate")
36+
}
37+
38+
override predicate methodCallMayAccessField(string methodName) { none() }
39+
}
40+
41+
/** A call to `GlobalID::Locator.locate_signed` */
42+
class LocateSignedCall extends DataFlow::CallNode, OrmInstantiation::Range {
43+
LocateSignedCall() {
44+
this =
45+
API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate_signed")
46+
}
47+
48+
override predicate methodCallMayAccessField(string methodName) { none() }
49+
}
50+
51+
/** A call to `GlobalID::Locator.locate_many` */
52+
class LocateManyCall extends DataFlow::CallNode, OrmInstantiation::Range {
53+
LocateManyCall() {
54+
this = API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate_many")
55+
}
56+
57+
override predicate methodCallMayAccessField(string methodName) { none() }
58+
}
59+
60+
/** A call to `GlobalID::Locator.locate_many_signed` */
61+
class LocateManySignedCall extends DataFlow::CallNode, OrmInstantiation::Range {
62+
LocateManySignedCall() {
63+
this =
64+
API::getTopLevelMember("GlobalID")
65+
.getMember("Locator")
66+
.getAMethodCall("locate_many_signed")
67+
}
68+
69+
override predicate methodCallMayAccessField(string methodName) { none() }
70+
}
71+
}
72+
73+
/** `GlobalID::Identification` */
74+
module Identification {
75+
/** A `DataFlow::CallNode` against an instance of a class that includes the `GlobalID::Identification` module */
76+
private class IdentificationInstanceCall extends DataFlow::CallNode {
77+
IdentificationInstanceCall() {
78+
this =
79+
DataFlow::getConstant("GlobalID")
80+
.getConstant("Identification")
81+
.getADescendentModule()
82+
.getAnImmediateReference()
83+
.getAMethodCall(["new", "find"])
84+
.getAMethodCall()
85+
or
86+
this instanceof ActiveRecordInstanceMethodCall
87+
}
88+
}
89+
90+
/** A call to `GlobalID::Identification.to_global_id` */
91+
class ToGlobalIdCall extends IdentificationInstanceCall {
92+
ToGlobalIdCall() { this.getMethodName() = ["to_global_id", "to_gid"] }
93+
}
94+
95+
/** A call to `GlobalID::Identification.to_gid_param` */
96+
class ToGidParamCall extends DataFlow::CallNode {
97+
ToGidParamCall() { this.getMethodName() = "to_gid_param" }
98+
}
99+
100+
/** A call to `GlobalID::Identification.to_signed_global_id` */
101+
class ToSignedGlobalIdCall extends DataFlow::CallNode {
102+
ToSignedGlobalIdCall() { this.getMethodName() = ["to_signed_global_id", "to_sgid"] }
103+
}
104+
105+
/** A call to `GlobalID::Identification.to_sgid_param` */
106+
class ToSgidParamCall extends DataFlow::CallNode {
107+
ToSgidParamCall() { this.getMethodName() = "to_sgid_param" }
108+
}
109+
}
110+
}
111+
112+
/** Provides modeling for `SignedGlobalID`, a module of the `rails/globalid` library. */
113+
module SignedGlobalId {
114+
/** A call to `SignedGlobalID::parse` */
115+
class ParseCall extends DataFlow::CallNode {
116+
ParseCall() { this = API::getTopLevelMember("SignedGlobalID").getAMethodCall("parse") }
117+
}
118+
119+
/** A call to `SignedGlobalID::find` */
120+
class FindCall extends DataFlow::CallNode, OrmInstantiation::Range {
121+
FindCall() { this = API::getTopLevelMember("SignedGlobalID").getAMethodCall("find") }
122+
123+
override predicate methodCallMayAccessField(string methodName) { none() }
124+
}
125+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
locateCalls
2+
| globalid.rb:6:3:6:30 | call to locate |
3+
| globalid.rb:11:3:11:30 | call to locate |
4+
| globalid.rb:70:3:70:30 | call to locate |
5+
locateSignedCalls
6+
| globalid.rb:16:3:16:38 | call to locate_signed |
7+
| globalid.rb:21:3:21:38 | call to locate_signed |
8+
| globalid.rb:89:3:89:38 | call to locate_signed |
9+
toGlobalIdCalls
10+
| globalid.rb:5:9:5:33 | call to to_global_id |
11+
| globalid.rb:10:9:10:27 | call to to_gid |
12+
| globalid.rb:56:9:56:16 | call to to_gid |
13+
| globalid.rb:62:9:62:22 | call to to_global_id |
14+
toGidParamCalls
15+
| globalid.rb:35:10:35:34 | call to to_gid_param |
16+
| globalid.rb:68:10:68:23 | call to to_gid_param |
17+
toSignedGlobalIdCalls
18+
| globalid.rb:15:10:15:41 | call to to_signed_global_id |
19+
| globalid.rb:20:10:20:29 | call to to_sgid |
20+
| globalid.rb:75:10:75:18 | call to to_sgid |
21+
| globalid.rb:81:10:81:30 | call to to_signed_global_id |
22+
toSgidParamCalls
23+
| globalid.rb:41:11:41:36 | call to to_sgid_param |
24+
| globalid.rb:87:11:87:25 | call to to_sgid_param |
25+
globalIdParseCalls
26+
| globalid.rb:36:9:36:27 | call to parse |
27+
| globalid.rb:69:9:69:27 | call to parse |
28+
globalIdFindCalls
29+
| globalid.rb:37:3:37:19 | call to find |
30+
| globalid.rb:57:3:57:19 | call to find |
31+
| globalid.rb:63:3:63:19 | call to find |
32+
signedGlobalIdParseCalls
33+
| globalid.rb:42:10:42:35 | call to parse |
34+
| globalid.rb:88:10:88:35 | call to parse |
35+
signedGlobalIdFindCalls
36+
| globalid.rb:43:3:43:26 | call to find |
37+
| globalid.rb:76:3:76:26 | call to find |
38+
| globalid.rb:82:3:82:26 | call to find |
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import codeql.ruby.frameworks.GlobalId
2+
3+
query predicate locateCalls(GlobalId::Locator::LocateCall c) { any() }
4+
5+
query predicate locateSignedCalls(GlobalId::Locator::LocateSignedCall c) { any() }
6+
7+
query predicate toGlobalIdCalls(GlobalId::Identification::ToGlobalIdCall c) { any() }
8+
9+
query predicate toGidParamCalls(GlobalId::Identification::ToGidParamCall c) { any() }
10+
11+
query predicate toSignedGlobalIdCalls(GlobalId::Identification::ToSignedGlobalIdCall c) { any() }
12+
13+
query predicate toSgidParamCalls(GlobalId::Identification::ToSgidParamCall c) { any() }
14+
15+
query predicate globalIdParseCalls(GlobalId::ParseCall c) { any() }
16+
17+
query predicate globalIdFindCalls(GlobalId::FindCall c) { any() }
18+
19+
query predicate signedGlobalIdParseCalls(SignedGlobalId::ParseCall c) { any() }
20+
21+
query predicate signedGlobalIdFindCalls(SignedGlobalId::FindCall c) { any() }
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
class User < ActiveRecord::Base
2+
end
3+
4+
def m1
5+
gid = User.find(1).to_global_id
6+
GlobalID::Locator.locate gid
7+
end
8+
9+
def m2
10+
gid = User.find(1).to_gid
11+
GlobalID::Locator.locate gid
12+
end
13+
14+
def m3
15+
sgid = User.find(1).to_signed_global_id
16+
GlobalID::Locator.locate_signed sgid
17+
end
18+
19+
def m4
20+
sgid = User.find(1).to_sgid
21+
GlobalID::Locator.locate_signed sgid
22+
end
23+
24+
def m5
25+
gids = User.all.map(&:to_gid)
26+
GlobalID::Locator.locate_many gids
27+
end
28+
29+
def m6
30+
sgids = User.all.map(&:to_sgid)
31+
GlobalID::Locator.locate_many_signed sgids
32+
end
33+
34+
def m7
35+
gidp = User.find(1).to_gid_param
36+
gid = GlobalID.parse gidp
37+
GlobalID.find gid
38+
end
39+
40+
def m8
41+
sgidp = User.find(1).to_sgid_param
42+
sgid = SignedGlobalID.parse sgidp
43+
SignedGlobalID.find sgid
44+
end
45+
46+
class Person
47+
include GlobalID::Identification
48+
49+
def self.find(id)
50+
# implementation goes here
51+
end
52+
end
53+
54+
def m9
55+
p = Person.find(1)
56+
gid = p.to_gid
57+
GlobalID.find gid
58+
end
59+
60+
def m10
61+
p = Person.find(1)
62+
gid = p.to_global_id
63+
GlobalID.find gid
64+
end
65+
66+
def m11
67+
p = Person.find(1)
68+
gidp = p.to_gid_param
69+
gid = GlobalID.parse gidp
70+
GlobalID::Locator.locate gid
71+
end
72+
73+
def m12
74+
p = Person.find(1)
75+
sgid = p.to_sgid
76+
SignedGlobalID.find sgid
77+
end
78+
79+
def m10
80+
p = Person.find(1)
81+
sgid = p.to_signed_global_id
82+
SignedGlobalID.find sgid
83+
end
84+
85+
def m11
86+
p = Person.find(1)
87+
sgidp = p.to_sgid_param
88+
sgid = SignedGlobalID.parse sgidp
89+
GlobalID::Locator.locate_signed sgid
90+
end

0 commit comments

Comments
 (0)