diff --git a/ruby/ql/lib/codeql/ruby/ast/Module.qll b/ruby/ql/lib/codeql/ruby/ast/Module.qll index e9752a02d5b..9e2ca31ee61 100644 --- a/ruby/ql/lib/codeql/ruby/ast/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/Module.qll @@ -173,6 +173,11 @@ class Module extends TModule { result.getParentModule() = this and result.getOwnModuleName() = name } + + /** + * Holds if this is a built-in module, e.g. `Object`. + */ + predicate isBuiltin() { isBuiltinModule(this) } } /** diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll index f6fa4ca1528..6905dd5ff2d 100644 --- a/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll +++ b/ruby/ql/lib/codeql/ruby/ast/internal/Module.qll @@ -42,6 +42,9 @@ private module Cached { result = getAnAssumedGlobalNamespacePrefix(n) } + cached + predicate isBuiltinModule(Module m) { m = TResolved(builtin()) } + cached Module getSuperClass(Module cls) { cls = TResolved("Object") and result = TResolved("BasicObject") diff --git a/ruby/ql/src/queries/modeling/internal/Types.qll b/ruby/ql/src/queries/modeling/internal/Types.qll index 6f83f2f524b..444bc2de929 100644 --- a/ruby/ql/src/queries/modeling/internal/Types.qll +++ b/ruby/ql/src/queries/modeling/internal/Types.qll @@ -6,6 +6,8 @@ private import ruby private import codeql.ruby.ApiGraphs private import Util as Util +private import codeql.ruby.ast.Module +private import codeql.ruby.ast.internal.Module /** * Contains predicates for generating `typeModel`s that contain typing @@ -42,5 +44,14 @@ module Types { valueHasTypeName(node.getAValueReachingSink(), type1) and Util::pathToNode(node, type2, path, true) ) + or + // class Type2 < Type1 + // class Type2; include Type1 + // class Type2; extend Type1 + exists(Module m1, Module m2 | + m2.getAnImmediateAncestor() = m1 and not m2.isBuiltin() and not m1.isBuiltin() + | + m1.getQualifiedName() = type1 and m2.getQualifiedName() = type2 and path = "" + ) } }