mirror of
https://github.com/github/codeql.git
synced 2026-04-25 16:55:19 +02:00
Merge pull request #11497 from alexrford/ruby/rails_globalid
Ruby: model `rails/globalid` component
This commit is contained in:
4
ruby/ql/lib/change-notes/2022-11-30-rails-globalid.md
Normal file
4
ruby/ql/lib/change-notes/2022-11-30-rails-globalid.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Calls to `GlobalID::Locator.locate` and its variants are now recognized as instances of `OrmInstantiation`.
|
||||
125
ruby/ql/lib/codeql/ruby/frameworks/GlobalId.qll
Normal file
125
ruby/ql/lib/codeql/ruby/frameworks/GlobalId.qll
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
* Provides modeling for `GlobalID`, a library for identifying model instances by URI.
|
||||
* Version: 1.0.0
|
||||
* https://github.com/rails/globalid
|
||||
*/
|
||||
|
||||
private import codeql.ruby.ApiGraphs
|
||||
private import codeql.ruby.Concepts
|
||||
private import codeql.ruby.DataFlow
|
||||
private import codeql.ruby.frameworks.ActiveRecord
|
||||
|
||||
/**
|
||||
* Provides modeling for `GlobalID`, a library for identifying model instances by URI.
|
||||
* Version: 1.0.0
|
||||
* https://github.com/rails/globalid
|
||||
*/
|
||||
module GlobalId {
|
||||
/** A call to `GlobalID::parse` */
|
||||
class ParseCall extends DataFlow::CallNode {
|
||||
ParseCall() { this = API::getTopLevelMember("GlobalID").getAMethodCall("parse") }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::find` */
|
||||
class FindCall extends DataFlow::CallNode, OrmInstantiation::Range {
|
||||
FindCall() { this = API::getTopLevelMember("GlobalID").getAMethodCall("find") }
|
||||
|
||||
override predicate methodCallMayAccessField(string methodName) { none() }
|
||||
}
|
||||
|
||||
/** `GlobalID::Locator` */
|
||||
module Locator {
|
||||
/** A call to `GlobalID::Locator.locate` */
|
||||
class LocateCall extends DataFlow::CallNode, OrmInstantiation::Range {
|
||||
LocateCall() {
|
||||
this = API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate")
|
||||
}
|
||||
|
||||
override predicate methodCallMayAccessField(string methodName) { none() }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Locator.locate_signed` */
|
||||
class LocateSignedCall extends DataFlow::CallNode, OrmInstantiation::Range {
|
||||
LocateSignedCall() {
|
||||
this =
|
||||
API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate_signed")
|
||||
}
|
||||
|
||||
override predicate methodCallMayAccessField(string methodName) { none() }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Locator.locate_many` */
|
||||
class LocateManyCall extends DataFlow::CallNode, OrmInstantiation::Range {
|
||||
LocateManyCall() {
|
||||
this = API::getTopLevelMember("GlobalID").getMember("Locator").getAMethodCall("locate_many")
|
||||
}
|
||||
|
||||
override predicate methodCallMayAccessField(string methodName) { none() }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Locator.locate_many_signed` */
|
||||
class LocateManySignedCall extends DataFlow::CallNode, OrmInstantiation::Range {
|
||||
LocateManySignedCall() {
|
||||
this =
|
||||
API::getTopLevelMember("GlobalID")
|
||||
.getMember("Locator")
|
||||
.getAMethodCall("locate_many_signed")
|
||||
}
|
||||
|
||||
override predicate methodCallMayAccessField(string methodName) { none() }
|
||||
}
|
||||
}
|
||||
|
||||
/** `GlobalID::Identification` */
|
||||
module Identification {
|
||||
/** A `DataFlow::CallNode` against an instance of a class that includes the `GlobalID::Identification` module */
|
||||
private class IdentificationInstanceCall extends DataFlow::CallNode {
|
||||
IdentificationInstanceCall() {
|
||||
this =
|
||||
DataFlow::getConstant("GlobalID")
|
||||
.getConstant("Identification")
|
||||
.getADescendentModule()
|
||||
.getAnImmediateReference()
|
||||
.getAMethodCall(["new", "find"])
|
||||
.getAMethodCall()
|
||||
or
|
||||
this instanceof ActiveRecordInstanceMethodCall
|
||||
}
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Identification.to_global_id` */
|
||||
class ToGlobalIdCall extends IdentificationInstanceCall {
|
||||
ToGlobalIdCall() { this.getMethodName() = ["to_global_id", "to_gid"] }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Identification.to_gid_param` */
|
||||
class ToGidParamCall extends DataFlow::CallNode {
|
||||
ToGidParamCall() { this.getMethodName() = "to_gid_param" }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Identification.to_signed_global_id` */
|
||||
class ToSignedGlobalIdCall extends DataFlow::CallNode {
|
||||
ToSignedGlobalIdCall() { this.getMethodName() = ["to_signed_global_id", "to_sgid"] }
|
||||
}
|
||||
|
||||
/** A call to `GlobalID::Identification.to_sgid_param` */
|
||||
class ToSgidParamCall extends DataFlow::CallNode {
|
||||
ToSgidParamCall() { this.getMethodName() = "to_sgid_param" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Provides modeling for `SignedGlobalID`, a module of the `rails/globalid` library. */
|
||||
module SignedGlobalId {
|
||||
/** A call to `SignedGlobalID::parse` */
|
||||
class ParseCall extends DataFlow::CallNode {
|
||||
ParseCall() { this = API::getTopLevelMember("SignedGlobalID").getAMethodCall("parse") }
|
||||
}
|
||||
|
||||
/** A call to `SignedGlobalID::find` */
|
||||
class FindCall extends DataFlow::CallNode, OrmInstantiation::Range {
|
||||
FindCall() { this = API::getTopLevelMember("SignedGlobalID").getAMethodCall("find") }
|
||||
|
||||
override predicate methodCallMayAccessField(string methodName) { none() }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
locateCalls
|
||||
| globalid.rb:6:3:6:30 | call to locate |
|
||||
| globalid.rb:11:3:11:30 | call to locate |
|
||||
| globalid.rb:70:3:70:30 | call to locate |
|
||||
locateSignedCalls
|
||||
| globalid.rb:16:3:16:38 | call to locate_signed |
|
||||
| globalid.rb:21:3:21:38 | call to locate_signed |
|
||||
| globalid.rb:89:3:89:38 | call to locate_signed |
|
||||
toGlobalIdCalls
|
||||
| globalid.rb:5:9:5:33 | call to to_global_id |
|
||||
| globalid.rb:10:9:10:27 | call to to_gid |
|
||||
| globalid.rb:56:9:56:16 | call to to_gid |
|
||||
| globalid.rb:62:9:62:22 | call to to_global_id |
|
||||
toGidParamCalls
|
||||
| globalid.rb:35:10:35:34 | call to to_gid_param |
|
||||
| globalid.rb:68:10:68:23 | call to to_gid_param |
|
||||
toSignedGlobalIdCalls
|
||||
| globalid.rb:15:10:15:41 | call to to_signed_global_id |
|
||||
| globalid.rb:20:10:20:29 | call to to_sgid |
|
||||
| globalid.rb:75:10:75:18 | call to to_sgid |
|
||||
| globalid.rb:81:10:81:30 | call to to_signed_global_id |
|
||||
toSgidParamCalls
|
||||
| globalid.rb:41:11:41:36 | call to to_sgid_param |
|
||||
| globalid.rb:87:11:87:25 | call to to_sgid_param |
|
||||
globalIdParseCalls
|
||||
| globalid.rb:36:9:36:27 | call to parse |
|
||||
| globalid.rb:69:9:69:27 | call to parse |
|
||||
globalIdFindCalls
|
||||
| globalid.rb:37:3:37:19 | call to find |
|
||||
| globalid.rb:57:3:57:19 | call to find |
|
||||
| globalid.rb:63:3:63:19 | call to find |
|
||||
signedGlobalIdParseCalls
|
||||
| globalid.rb:42:10:42:35 | call to parse |
|
||||
| globalid.rb:88:10:88:35 | call to parse |
|
||||
signedGlobalIdFindCalls
|
||||
| globalid.rb:43:3:43:26 | call to find |
|
||||
| globalid.rb:76:3:76:26 | call to find |
|
||||
| globalid.rb:82:3:82:26 | call to find |
|
||||
21
ruby/ql/test/library-tests/frameworks/globalid/GlobalId.ql
Normal file
21
ruby/ql/test/library-tests/frameworks/globalid/GlobalId.ql
Normal file
@@ -0,0 +1,21 @@
|
||||
import codeql.ruby.frameworks.GlobalId
|
||||
|
||||
query predicate locateCalls(GlobalId::Locator::LocateCall c) { any() }
|
||||
|
||||
query predicate locateSignedCalls(GlobalId::Locator::LocateSignedCall c) { any() }
|
||||
|
||||
query predicate toGlobalIdCalls(GlobalId::Identification::ToGlobalIdCall c) { any() }
|
||||
|
||||
query predicate toGidParamCalls(GlobalId::Identification::ToGidParamCall c) { any() }
|
||||
|
||||
query predicate toSignedGlobalIdCalls(GlobalId::Identification::ToSignedGlobalIdCall c) { any() }
|
||||
|
||||
query predicate toSgidParamCalls(GlobalId::Identification::ToSgidParamCall c) { any() }
|
||||
|
||||
query predicate globalIdParseCalls(GlobalId::ParseCall c) { any() }
|
||||
|
||||
query predicate globalIdFindCalls(GlobalId::FindCall c) { any() }
|
||||
|
||||
query predicate signedGlobalIdParseCalls(SignedGlobalId::ParseCall c) { any() }
|
||||
|
||||
query predicate signedGlobalIdFindCalls(SignedGlobalId::FindCall c) { any() }
|
||||
90
ruby/ql/test/library-tests/frameworks/globalid/globalid.rb
Normal file
90
ruby/ql/test/library-tests/frameworks/globalid/globalid.rb
Normal file
@@ -0,0 +1,90 @@
|
||||
class User < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def m1
|
||||
gid = User.find(1).to_global_id
|
||||
GlobalID::Locator.locate gid
|
||||
end
|
||||
|
||||
def m2
|
||||
gid = User.find(1).to_gid
|
||||
GlobalID::Locator.locate gid
|
||||
end
|
||||
|
||||
def m3
|
||||
sgid = User.find(1).to_signed_global_id
|
||||
GlobalID::Locator.locate_signed sgid
|
||||
end
|
||||
|
||||
def m4
|
||||
sgid = User.find(1).to_sgid
|
||||
GlobalID::Locator.locate_signed sgid
|
||||
end
|
||||
|
||||
def m5
|
||||
gids = User.all.map(&:to_gid)
|
||||
GlobalID::Locator.locate_many gids
|
||||
end
|
||||
|
||||
def m6
|
||||
sgids = User.all.map(&:to_sgid)
|
||||
GlobalID::Locator.locate_many_signed sgids
|
||||
end
|
||||
|
||||
def m7
|
||||
gidp = User.find(1).to_gid_param
|
||||
gid = GlobalID.parse gidp
|
||||
GlobalID.find gid
|
||||
end
|
||||
|
||||
def m8
|
||||
sgidp = User.find(1).to_sgid_param
|
||||
sgid = SignedGlobalID.parse sgidp
|
||||
SignedGlobalID.find sgid
|
||||
end
|
||||
|
||||
class Person
|
||||
include GlobalID::Identification
|
||||
|
||||
def self.find(id)
|
||||
# implementation goes here
|
||||
end
|
||||
end
|
||||
|
||||
def m9
|
||||
p = Person.find(1)
|
||||
gid = p.to_gid
|
||||
GlobalID.find gid
|
||||
end
|
||||
|
||||
def m10
|
||||
p = Person.find(1)
|
||||
gid = p.to_global_id
|
||||
GlobalID.find gid
|
||||
end
|
||||
|
||||
def m11
|
||||
p = Person.find(1)
|
||||
gidp = p.to_gid_param
|
||||
gid = GlobalID.parse gidp
|
||||
GlobalID::Locator.locate gid
|
||||
end
|
||||
|
||||
def m12
|
||||
p = Person.find(1)
|
||||
sgid = p.to_sgid
|
||||
SignedGlobalID.find sgid
|
||||
end
|
||||
|
||||
def m10
|
||||
p = Person.find(1)
|
||||
sgid = p.to_signed_global_id
|
||||
SignedGlobalID.find sgid
|
||||
end
|
||||
|
||||
def m11
|
||||
p = Person.find(1)
|
||||
sgidp = p.to_sgid_param
|
||||
sgid = SignedGlobalID.parse sgidp
|
||||
GlobalID::Locator.locate_signed sgid
|
||||
end
|
||||
Reference in New Issue
Block a user