Merge pull request #8408 from erik-krogh/pathProblem

QL: make a query checking for `edges` relation in a path-problem query
This commit is contained in:
Erik Krogh Kristensen
2022-03-11 16:27:46 +01:00
committed by GitHub
2 changed files with 78 additions and 5 deletions

View File

@@ -20,7 +20,18 @@ private class TFileOrModule = TFile or TModule;
/** A file or a module. */
class FileOrModule extends TFileOrModule, ContainerOrModule {
abstract File getFile();
/** Gets the module for this imported module. */
Module asModule() { this = TModule(result) }
/** Gets the file for this file. */
File asFile() { this = TFile(result) }
/** Gets the file that contains this module/file. */
File getFile() {
result = this.asFile()
or
result = this.asModule().getLocation().getFile()
}
}
private class File_ extends FileOrModule, TFile {
@@ -43,8 +54,6 @@ private class File_ extends FileOrModule, TFile {
endline = 0 and
endcolumn = 0
}
override File getFile() { result = f }
}
private class Folder_ extends ContainerOrModule, TFolder {
@@ -94,8 +103,6 @@ class Module_ extends FileOrModule, TModule {
) {
m.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
}
override File getFile() { result = m.getLocation().getFile() }
}
private predicate resolveQualifiedName(Import imp, ContainerOrModule m, int i) {

View File

@@ -0,0 +1,66 @@
/**
* @name Missing edges query predicate in path-problem
* @description A path-problem query should have a edges relation, and a problem query should not.
* @kind problem
* @problem.severity warning
* @id ql/path-problem-query
* @tags correctness
* maintainability
* @precision medium
*/
import ql
import codeql_ql.ast.internal.Module
FileOrModule hasEdgesRelation(ClasslessPredicate pred) {
pred.getName() = "edges" and
pred.hasAnnotation("query") and
(
result.asModule().getAMember() = pred
or
any(TopLevel top | top.getLocation().getFile() = result.asFile()).getAMember() = pred
)
}
FileOrModule importsEdges(ClasslessPredicate pred) {
result = hasEdgesRelation(pred)
or
exists(Import i |
not (i.hasAnnotation("private") and i.getLocation().getFile().getExtension() = "qll") and
importsEdges(pred) = i.getResolvedModule()
|
i = result.asModule().getAMember()
or
i = any(TopLevel top | top.getLocation().getFile() = result.asFile()).getAMember()
)
}
class Query extends File {
Query() { this.getExtension() = "ql" }
predicate isPathProblem() {
exists(QLDoc doc | doc.getLocation().getFile() = this |
doc.getContents().matches("%@kind path-problem%")
)
}
predicate isProblem() {
exists(QLDoc doc | doc.getLocation().getFile() = this |
doc.getContents().matches("%@kind problem%")
)
}
predicate hasEdgesRelation(ClasslessPredicate pred) { importsEdges(pred).asFile() = this }
}
from Query query, string msg, AstNode pred
where
query.isPathProblem() and
not query.hasEdgesRelation(_) and
pred = any(TopLevel top | top.getLocation().getFile() = query) and // <- dummy value
msg = "A path-problem query should have a edges relation."
or
query.isProblem() and
query.hasEdgesRelation(pred) and
msg = "A problem query should not have a $@."
select query, msg, pred, "edges relation"