mirror of
https://github.com/github/codeql.git
synced 2026-02-10 20:21:10 +01:00
214 lines
6.2 KiB
Plaintext
214 lines
6.2 KiB
Plaintext
import ql
|
|
private import Builtins
|
|
private import codeql_ql.ast.internal.Module
|
|
private import codeql_ql.ast.internal.AstNodes
|
|
|
|
private class TClasslessPredicateOrNewTypeBranch = TClasslessPredicate or TNewTypeBranch;
|
|
|
|
private string getPredicateName(TClasslessPredicateOrNewTypeBranch p) {
|
|
result = p.(ClasslessPredicate).getName() or
|
|
result = p.(NewTypeBranch).getName()
|
|
}
|
|
|
|
private predicate definesPredicate(
|
|
FileOrModule m, string name, int arity, TClasslessPredicateOrNewTypeBranch p, boolean public
|
|
) {
|
|
m = getEnclosingModule(p) and
|
|
name = getPredicateName(p) and
|
|
public = getPublicBool(p) and
|
|
arity = [p.(ClasslessPredicate).getArity(), count(p.(NewTypeBranch).getField(_))]
|
|
or
|
|
// import X
|
|
exists(Import imp, FileOrModule m0 |
|
|
m = getEnclosingModule(imp) and
|
|
m0 = imp.getResolvedModule() and
|
|
not exists(imp.importedAs()) and
|
|
definesPredicate(m0, name, arity, p, true) and
|
|
public = getPublicBool(imp)
|
|
)
|
|
or
|
|
// predicate X = Y
|
|
exists(ClasslessPredicate alias |
|
|
m = getEnclosingModule(alias) and
|
|
name = alias.getName() and
|
|
resolvePredicateExpr(alias.getAlias(), p) and
|
|
public = getPublicBool(alias) and
|
|
arity = alias.getArity()
|
|
)
|
|
}
|
|
|
|
cached
|
|
private module Cached {
|
|
cached
|
|
predicate resolvePredicateExpr(PredicateExpr pe, ClasslessPredicate p) {
|
|
exists(FileOrModule m, boolean public |
|
|
not exists(pe.getQualifier()) and
|
|
m = getEnclosingModule(pe).getEnclosing*() and
|
|
public = [false, true]
|
|
or
|
|
m = pe.getQualifier().getResolvedModule() and
|
|
public = true
|
|
|
|
|
definesPredicate(m, pe.getName(), count(p.getParameter(_)), p, public)
|
|
)
|
|
}
|
|
|
|
private predicate resolvePredicateCall(PredicateCall pc, PredicateOrBuiltin p) {
|
|
exists(Class c, ClassType t |
|
|
c = pc.getParent*() and
|
|
t = c.getType() and
|
|
p = t.getClassPredicate(pc.getPredicateName(), pc.getNumberOfArguments())
|
|
)
|
|
or
|
|
exists(FileOrModule m, boolean public |
|
|
not exists(pc.getQualifier()) and
|
|
m = getEnclosingModule(pc).getEnclosing*() and
|
|
public = [false, true]
|
|
or
|
|
m = pc.getQualifier().getResolvedModule() and
|
|
public = true
|
|
|
|
|
definesPredicate(m, pc.getPredicateName(), pc.getNumberOfArguments(), p, public)
|
|
)
|
|
}
|
|
|
|
private predicate resolveMemberCall(MemberCall mc, PredicateOrBuiltin p) {
|
|
exists(Type t |
|
|
t = mc.getBase().getType() and
|
|
p = t.getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments())
|
|
)
|
|
or
|
|
// super calls
|
|
exists(Super sup, ClassType type |
|
|
mc.getBase() = sup and
|
|
sup.getEnclosingPredicate().(ClassPredicate).getParent().getType() = type and
|
|
p = type.getASuperType().getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments())
|
|
)
|
|
}
|
|
|
|
pragma[noinline]
|
|
private predicate candidate(Relation rel, PredicateCall pc) {
|
|
rel.getName() = pc.getPredicateName()
|
|
}
|
|
|
|
private predicate resolveDBRelation(PredicateCall pc, DefinedPredicate p) {
|
|
exists(Relation rel | p = TPred(rel) |
|
|
candidate(rel, pc) and
|
|
rel.getArity() = pc.getNumberOfArguments() and
|
|
(
|
|
exists(YAML::QLPack libPack, YAML::QLPack qlPack |
|
|
rel.getLocation().getFile() = libPack.getDBScheme() and
|
|
qlPack.getADependency*() = libPack and
|
|
qlPack.getAFileInPack() = pc.getLocation().getFile()
|
|
)
|
|
or
|
|
// upgrade scripts don't have a qlpack
|
|
rel.getLocation().getFile().getParentContainer() =
|
|
pc.getLocation().getFile().getParentContainer()
|
|
)
|
|
)
|
|
}
|
|
|
|
cached
|
|
predicate resolveCall(Call c, PredicateOrBuiltin p) {
|
|
resolvePredicateCall(c, p)
|
|
or
|
|
resolveMemberCall(c, p)
|
|
or
|
|
not resolvePredicateCall(c, _) and
|
|
resolveDBRelation(c, p)
|
|
}
|
|
}
|
|
|
|
import Cached
|
|
|
|
class PredicateOrBuiltin extends TPredOrBuiltin, AstNode {
|
|
string getName() { none() }
|
|
|
|
Type getDeclaringType() { none() }
|
|
|
|
Type getParameterType(int i) { none() }
|
|
|
|
Type getReturnType() { none() }
|
|
|
|
int getArity() { result = count(getParameterType(_)) }
|
|
|
|
predicate isPrivate() { none() }
|
|
}
|
|
|
|
private class TBuiltin = TBuiltinClassless or TBuiltinMember;
|
|
|
|
class BuiltinPredicate extends PredicateOrBuiltin, TBuiltin {
|
|
override string toString() { result = getName() }
|
|
|
|
override string getAPrimaryQlClass() { result = "BuiltinPredicate" }
|
|
}
|
|
|
|
private class BuiltinClassless extends BuiltinPredicate, TBuiltinClassless {
|
|
string name;
|
|
string ret;
|
|
string args;
|
|
|
|
BuiltinClassless() { this = TBuiltinClassless(ret, name, args) }
|
|
|
|
override string getName() { result = name }
|
|
|
|
override PrimitiveType getReturnType() { result.getName() = ret }
|
|
|
|
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
|
|
}
|
|
|
|
private class BuiltinMember extends BuiltinPredicate, TBuiltinMember {
|
|
string name;
|
|
string qual;
|
|
string ret;
|
|
string args;
|
|
|
|
BuiltinMember() { this = TBuiltinMember(qual, ret, name, args) }
|
|
|
|
override string getName() { result = name }
|
|
|
|
override PrimitiveType getReturnType() { result.getName() = ret }
|
|
|
|
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
|
|
|
|
override PrimitiveType getDeclaringType() { result.getName() = qual }
|
|
}
|
|
|
|
module PredConsistency {
|
|
query predicate noResolvePredicateExpr(PredicateExpr pe) {
|
|
not resolvePredicateExpr(pe, _) and
|
|
not pe.getLocation()
|
|
.getFile()
|
|
.getAbsolutePath()
|
|
.regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*")
|
|
}
|
|
|
|
query predicate noResolveCall(Call c) {
|
|
not resolveCall(c, _) and
|
|
not c instanceof NoneCall and
|
|
not c instanceof AnyCall and
|
|
not c.getLocation()
|
|
.getFile()
|
|
.getAbsolutePath()
|
|
.regexpMatch(".*/(test|examples|ql-training|recorded-call-graph-metrics)/.*")
|
|
}
|
|
|
|
query predicate multipleResolvePredicateExpr(PredicateExpr pe, int c, ClasslessPredicate p) {
|
|
c = strictcount(ClasslessPredicate p0 | resolvePredicateExpr(pe, p0)) and
|
|
c > 1 and
|
|
resolvePredicateExpr(pe, p)
|
|
}
|
|
|
|
query predicate multipleResolveCall(Call call, int c, PredicateOrBuiltin p) {
|
|
c =
|
|
strictcount(PredicateOrBuiltin p0 |
|
|
resolveCall(call, p0) and
|
|
// aliases are expected to resolve to multiple.
|
|
not exists(p0.(ClasslessPredicate).getAlias())
|
|
) and
|
|
c > 1 and
|
|
resolveCall(call, p)
|
|
}
|
|
}
|