diff --git a/ql/src/codeql_ql/ast/internal/Module.qll b/ql/src/codeql_ql/ast/internal/Module.qll index 12ed38267d1..0df304ba6c8 100644 --- a/ql/src/codeql_ql/ast/internal/Module.qll +++ b/ql/src/codeql_ql/ast/internal/Module.qll @@ -2,11 +2,6 @@ import ql private import codeql_ql.ast.internal.AstNodes as AstNodes private import codeql_ql.ast.internal.TreeSitter -private newtype TContainerOrModule = - TFile(File f) or - TFolder(Folder f) or - TModule(Module m) - private class ContainerOrModule extends TContainerOrModule { string getName() { none() } @@ -146,25 +141,42 @@ private predicate resolveSelectionName(Import imp, ContainerOrModule m, int i) { ) } -/** Holds if import statement `imp` resolves to `m`. */ -predicate resolve(Import imp, FileOrModule m) { - exists(int last | - resolveSelectionName(imp, m, last) and - last = count(int j | exists(imp.getSelectionName(j))) - 1 - ) +cached +private module Cached { + cached + module NewType { + cached + newtype TContainerOrModule = + TFile(File f) or + TFolder(Folder f) or + TModule(Module m) + } + + /** Holds if import statement `imp` resolves to `m`. */ + cached + predicate resolve(Import imp, FileOrModule m) { + exists(int last | + resolveSelectionName(imp, m, last) and + last = count(int j | exists(imp.getSelectionName(j))) - 1 + ) + } + + /** Holds if module expression `me` resolves to `m`. */ + cached + predicate resolveModuleExpr(ModuleExpr me, FileOrModule m) { + not m = TFile(any(File f | f.getExtension() = "ql")) and + not exists(me.getQualifier()) and + definesModule(getEnclosingModule(me).getEnclosing*(), me.getName(), m, _) + or + exists(FileOrModule mid | + resolveModuleExpr(me.getQualifier(), mid) and + definesModule(mid, me.getName(), m, true) + ) + } } -/** Holds if module expression `me` resolves to `m`. */ -predicate resolveModuleExpr(ModuleExpr me, FileOrModule m) { - not m = TFile(any(File f | f.getExtension() = "ql")) and - not exists(me.getQualifier()) and - definesModule(getEnclosingModule(me).getEnclosing*(), me.getName(), m, _) - or - exists(FileOrModule mid | - resolveModuleExpr(me.getQualifier(), mid) and - definesModule(mid, me.getName(), m, true) - ) -} +import Cached +private import NewType boolean getPublicBool(AstNode n) { if n.(ModuleMember).isPrivate() or n.(NewTypeBranch).getNewType().isPrivate() diff --git a/ql/src/codeql_ql/ast/internal/Predicate.qll b/ql/src/codeql_ql/ast/internal/Predicate.qll index 473600bfb9f..069dd69974c 100644 --- a/ql/src/codeql_ql/ast/internal/Predicate.qll +++ b/ql/src/codeql_ql/ast/internal/Predicate.qll @@ -38,59 +38,74 @@ private predicate definesPredicate( ) } -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.getDeclaration(), public) - ) -} - -private predicate resolveMemberCall(MemberCall mc, PredicateOrBuiltin p) { - exists(Type t | - t = mc.getBase().getType() and - p = t.getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments()) - ) -} - -predicate resolveCall(Call c, PredicateOrBuiltin p) { - resolvePredicateCall(c, p) - or - resolveMemberCall(c, p) -} - -private newtype TPredOrBuiltin = - TPred(Predicate p) or - TNewTypeBranch(NewTypeBranch b) or - TBuiltinClassless(string ret, string name, string args) { isBuiltinClassless(ret, name, args) } or - TBuiltinMember(string qual, string ret, string name, string args) { - isBuiltinMember(qual, ret, name, args) +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.getDeclaration(), + public) + ) + } + + private predicate resolveMemberCall(MemberCall mc, PredicateOrBuiltin p) { + exists(Type t | + t = mc.getBase().getType() and + p = t.getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments()) + ) + } + + cached + predicate resolveCall(Call c, PredicateOrBuiltin p) { + resolvePredicateCall(c, p) + or + resolveMemberCall(c, p) + } + + cached + module NewTypeDef { + cached + newtype TPredOrBuiltin = + TPred(Predicate p) or + TNewTypeBranch(NewTypeBranch b) or + TBuiltinClassless(string ret, string name, string args) { + isBuiltinClassless(ret, name, args) + } or + TBuiltinMember(string qual, string ret, string name, string args) { + isBuiltinMember(qual, ret, name, args) + } + } +} + +import Cached +private import NewTypeDef + class PredicateOrBuiltin extends TPredOrBuiltin { string getName() { none() } diff --git a/ql/src/codeql_ql/ast/internal/Type.qll b/ql/src/codeql_ql/ast/internal/Type.qll index 804c0eb53bf..3de6e420144 100644 --- a/ql/src/codeql_ql/ast/internal/Type.qll +++ b/ql/src/codeql_ql/ast/internal/Type.qll @@ -4,6 +4,7 @@ private import codeql_ql.ast.internal.TreeSitter private import codeql_ql.ast.internal.Module private import codeql_ql.ast.internal.Predicate +cached private newtype TType = TClass(Class c) { isActualClass(c) } or TNewType(NewType n) or @@ -257,6 +258,7 @@ class DatabaseType extends Type, TDatabase { override string getName() { result = name } } +cached predicate resolveTypeExpr(TypeExpr te, Type t) { if te.isDBType() then t = TDatabase(te.getClassName()) diff --git a/ql/src/codeql_ql/ast/internal/Variable.qll b/ql/src/codeql_ql/ast/internal/Variable.qll index 379196d6faa..89ff1288949 100644 --- a/ql/src/codeql_ql/ast/internal/Variable.qll +++ b/ql/src/codeql_ql/ast/internal/Variable.qll @@ -65,9 +65,16 @@ private string getName(Identifier i) { ) } -predicate resolveVariable(Identifier i, VarDef decl) { scopeOf(i).containsVar(decl, getName(i)) } +cached +private module Cached { + cached + predicate resolveVariable(Identifier i, VarDef decl) { scopeOf(i).containsVar(decl, getName(i)) } -predicate resolveField(Identifier i, VarDef decl) { scopeOf(i).containsField(decl, getName(i)) } + cached + predicate resolveField(Identifier i, VarDef decl) { scopeOf(i).containsField(decl, getName(i)) } +} + +import Cached module VarConsistency { query predicate multipleVarDefs(VarAccess v, VarDef decl) {