QL: Merge pull request #125 from github/erik-krogh/fix-my-own-mistake

fixing the callgraph
This commit is contained in:
Erik Krogh Kristensen
2021-10-15 22:15:29 +02:00
committed by GitHub
9 changed files with 78 additions and 31 deletions

View File

@@ -0,0 +1,10 @@
import ql
private import codeql_ql.ast.internal.AstNodes as AstNodes
query AstNode nonTotalGetParent() {
exists(AstNodes::toQL(result).getParent()) and
not exists(result.getParent()) and
not result.getLocation().getStartColumn() = 1 and // startcolumn = 1 <=> top level in file <=> fine to have no parent
not result instanceof YAML::YAMLNode and // parents for YAML doens't work
not (result instanceof QLDoc and result.getLocation().getFile().getExtension() = "dbscheme") // qldoc in dbschemes are not hooked up
}

View File

@@ -56,7 +56,11 @@ class AstNode extends TAstNode {
* named `pred`.
*/
cached
AstNode getAChild(string pred) { none() }
AstNode getAChild(string pred) {
pred = directMember("getAnAnnotation") and result = getAnAnnotation()
or
pred = directMember("getQLDoc") and result = getQLDoc()
}
/**
* Gets the primary QL class for the ast node.
@@ -70,10 +74,7 @@ class AstNode extends TAstNode {
predicate hasAnnotation(string name) { this.getAnAnnotation().getName() = name }
/** Gets an annotation of this AST node. */
cached
Annotation getAnAnnotation() {
toQL(this).getParent() = pragma[only_bind_out](toQL(result)).getParent()
}
Annotation getAnAnnotation() { toQL(this).getParent() = toQL(result).getParent() }
/**
* Gets the predicate that contains this AST node.
@@ -119,8 +120,6 @@ class TopLevel extends TTopLevel, AstNode {
NewType getANewType() { result = this.getAMember() }
override ModuleMember getAChild(string pred) {
pred = directMember("getQLDoc") and result = this.getQLDoc()
or
pred = directMember("getAnImport") and result = this.getAnImport()
or
pred = directMember("getAClass") and result = this.getAClass()
@@ -214,7 +213,7 @@ class BuiltinPredicate extends PredicateOrBuiltin, TBuiltin {
override string getAPrimaryQlClass() { result = "BuiltinPredicate" }
}
private class BuiltinClassless extends BuiltinPredicate, TBuiltinClassless {
class BuiltinClassless extends BuiltinPredicate, TBuiltinClassless {
string name;
string ret;
string args;
@@ -228,7 +227,7 @@ private class BuiltinClassless extends BuiltinPredicate, TBuiltinClassless {
override PrimitiveType getParameterType(int i) { result.getName() = getArgType(args, i) }
}
private class BuiltinMember extends BuiltinPredicate, TBuiltinMember {
class BuiltinMember extends BuiltinPredicate, TBuiltinMember {
string name;
string qual;
string ret;
@@ -626,7 +625,7 @@ class TypeExpr extends TType, AstNode {
*/
Type getResolvedType() { resolveTypeExpr(this, result) }
override ModuleExpr getAChild(string pred) {
override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = directMember("getModule") and result = this.getModule()
@@ -691,11 +690,7 @@ class Declaration extends TDeclaration, AstNode {
result = any(Class c).getQLDocFor(this)
}
override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
pred = directMember("getQLDoc") and result = this.getQLDoc()
}
override AstNode getAChild(string pred) { result = super.getAChild(pred) }
}
/** An entity that can be declared in a module. */
@@ -784,6 +779,8 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration {
or
pred = directMember("getASuperType") and result = this.getASuperType()
or
pred = directMember("getAnInstanceofType") and result = this.getAnInstanceofType()
or
exists(string name |
pred = stringIndexedMember("getClassPredicate", name) and
result = this.getClassPredicate(name)
@@ -860,8 +857,6 @@ class NewTypeBranch extends TNewTypeBranch, PredicateOrBuiltin, TypeDeclaration
pred = directMember("getBody") and result = this.getBody()
or
exists(int i | pred = indexedMember("getField", i) and result = this.getField(i))
or
pred = directMember("getQLDoc") and result = this.getQLDoc()
}
}
@@ -2196,6 +2191,12 @@ class Annotation extends TAnnotation, AstNode {
/** Gets the node corresponding to the field `name`. */
string getName() { result = annot.getName().getValue() }
override AstNode getAChild(string pred) {
result = super.getAChild(pred)
or
exists(int i | pred = indexedMember("getArgs", i) and result = this.getArgs(i))
}
}
/** A `pragma[noinline]` annotation. */
@@ -2414,8 +2415,8 @@ module YAML {
/** Gets the database scheme of this qlpack */
File getDBScheme() {
result.getBaseName() = this.getProperty("dbscheme") and
result = file.getParentContainer().getFile(any(string s | s.matches("%.dbscheme")))
result.getAbsolutePath() =
file.getParentContainer().getAbsolutePath() + "/" + this.getProperty("dbscheme")
}
pragma[noinline]

View File

@@ -44,7 +44,9 @@ predicate isBuiltinMember(string sig) {
"string string.toLowerCase()", "string string.toUpperCase()", "string string.trim()",
"int date.daysTo(date)", "int date.getDay()", "int date.getHours()", "int date.getMinutes()",
"int date.getMonth()", "int date.getSeconds()", "int date.getYear()",
"string date.toString()", "string date.toISO()", "string int.toUnicode()"
"string date.toString()", "string date.toISO()", "string int.toUnicode()",
"string any.getAQlClass()"
/* getAQlClass is special , see Predicate.qll*/
]
}

View File

@@ -154,18 +154,13 @@ private predicate resolveSelectionName(Import imp, ContainerOrModule m, int i) {
cached
private module Cached {
private Module getEnclosingModule0(AstNode n) {
not n instanceof Module and
(
n = result.getAChild(_)
or
exists(AstNode prev |
result = getEnclosingModule0(prev) and
n = prev.getAChild(_)
)
)
private AstNode parent(AstNode n) {
result = n.getParent() and
not n instanceof Module
}
private Module getEnclosingModule0(AstNode n) { result = parent*(n.getParent()) }
cached
ContainerOrModule getEnclosingModule(AstNode n) {
result = TModule(getEnclosingModule0(n))

View File

@@ -81,7 +81,7 @@ private module Cached {
// super calls
exists(Super sup, ClassType type, Type supertype |
mc.getBase() = sup and
sup.getEnclosingPredicate().(ClassPredicate).getParent().getType() = type and
sup.getEnclosingPredicate().getParent().(Class).getType() = type and
supertype in [type.getASuperType(), type.getAnInstanceofType()] and
p = supertype.getClassPredicate(mc.getMemberName(), mc.getNumberOfArguments())
)
@@ -110,14 +110,26 @@ private module Cached {
)
}
private predicate resolveBuildinPredicateCall(PredicateCall call, BuiltinClassless pred) {
call.getNumberOfArguments() = pred.getArity() and
call.getPredicateName() = pred.getName()
}
cached
predicate resolveCall(Call c, PredicateOrBuiltin p) {
resolvePredicateCall(c, p)
or
not resolvePredicateCall(c, _) and
resolveBuildinPredicateCall(c, p)
or
resolveMemberCall(c, p)
or
not resolvePredicateCall(c, _) and
resolveDBRelation(c, p)
or
// getAQlClass() is special
c.(MemberCall).getMemberName() = "getAQlClass" and
p.(BuiltinMember).getName() = "getAQlClass"
}
}

View File

@@ -0,0 +1,9 @@
import ql
module Firebase {
module Database {
query predicate ref(int i) { i = snapshot() }
}
int snapshot() { result = 2 }
}

11
ql/test/callgraph/Baz.qll Normal file
View File

@@ -0,0 +1,11 @@
class Foo extends string {
Foo() { this = "Foo" }
string getImportedPath() { none() }
}
class Bar extends string, Foo {
Bar() { exists(Foo.super.getImportedPath()) }
override string getImportedPath() { none() }
}

View File

@@ -1,4 +1,6 @@
getTarget
| Bar.qll:5:38:5:47 | PredicateCall | Bar.qll:8:3:8:31 | ClasslessPredicate snapshot |
| Baz.qll:8:18:8:44 | MemberCall | Baz.qll:4:3:4:37 | ClassPredicate getImportedPath |
| Foo.qll:5:26:5:30 | PredicateCall | Foo.qll:3:1:3:26 | ClasslessPredicate foo |
| Foo.qll:10:21:10:25 | PredicateCall | Foo.qll:8:3:8:28 | ClassPredicate bar |
| Foo.qll:14:30:14:40 | MemberCall | Foo.qll:10:3:10:27 | ClassPredicate baz |

View File

@@ -196,6 +196,7 @@ nodes
| file://:0:0:0:0 | exp | semmle.label | [BuiltinPredicate] exp |
| file://:0:0:0:0 | floor | semmle.label | [BuiltinPredicate] floor |
| file://:0:0:0:0 | gcd | semmle.label | [BuiltinPredicate] gcd |
| file://:0:0:0:0 | getAQlClass | semmle.label | [BuiltinPredicate] getAQlClass |
| file://:0:0:0:0 | getDay | semmle.label | [BuiltinPredicate] getDay |
| file://:0:0:0:0 | getHours | semmle.label | [BuiltinPredicate] getHours |
| file://:0:0:0:0 | getMinutes | semmle.label | [BuiltinPredicate] getMinutes |
@@ -288,6 +289,10 @@ edges
| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:30:6:30 | ComparisonOp | semmle.order | 14 |
| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:32:6:36 | String | semmle.label | getRightOperand() |
| Foo.qll:6:23:6:36 | ComparisonFormula | Foo.qll:6:32:6:36 | String | semmle.order | 15 |
| Foo.qll:9:1:9:5 | annotation | Foo.qll:9:1:9:5 | annotation | semmle.label | getAnAnnotation() |
| Foo.qll:9:1:9:5 | annotation | Foo.qll:9:1:9:5 | annotation | semmle.order | 16 |
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:1:9:5 | annotation | semmle.label | getAnAnnotation() |
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:1:9:5 | annotation | semmle.order | 16 |
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:21:9:25 | f | semmle.label | getParameter(_) |
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:9:21:9:25 | f | semmle.order | 18 |
| Foo.qll:9:7:11:1 | ClasslessPredicate foo | Foo.qll:10:3:10:85 | ComparisonFormula | semmle.label | getBody() |