зеркало из https://github.com/github/codeql.git
Merge pull request #3947 from RasmusWL/python-fix-tests
Python: Make experimental/library-tests/CallGraph pass for Python 2
This commit is contained in:
Коммит
ee13e87f3b
|
@ -2,22 +2,22 @@ import python
|
|||
|
||||
/** Gets the comment on the line above `ast` */
|
||||
Comment commentFor(AstNode ast) {
|
||||
exists(int line | line = ast.getLocation().getStartLine() - 1 |
|
||||
result
|
||||
.getLocation()
|
||||
.hasLocationInfo(ast.getLocation().getFile().getAbsolutePath(), line, _, line, _)
|
||||
)
|
||||
exists(int line | line = ast.getLocation().getStartLine() - 1 |
|
||||
result
|
||||
.getLocation()
|
||||
.hasLocationInfo(ast.getLocation().getFile().getAbsolutePath(), line, _, line, _)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the value from `tag:value` in the comment for `ast` */
|
||||
string getAnnotation(AstNode ast, string tag) {
|
||||
exists(Comment comment, string match, string theRegex |
|
||||
theRegex = "([\\w]+):([\\w.]+)" and
|
||||
comment = commentFor(ast) and
|
||||
match = comment.getText().regexpFind(theRegex, _, _) and
|
||||
tag = match.regexpCapture(theRegex, 1) and
|
||||
result = match.regexpCapture(theRegex, 2)
|
||||
)
|
||||
exists(Comment comment, string match, string theRegex |
|
||||
theRegex = "([\\w]+):([\\w.]+)" and
|
||||
comment = commentFor(ast) and
|
||||
match = comment.getText().regexpFind(theRegex, _, _) and
|
||||
tag = match.regexpCapture(theRegex, 1) and
|
||||
result = match.regexpCapture(theRegex, 2)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a callable annotated with `name:name` */
|
||||
|
@ -27,121 +27,121 @@ Function annotatedCallable(string name) { name = getAnnotation(result, "name") }
|
|||
Call annotatedCall(string name) { name = getAnnotation(result, "calls") }
|
||||
|
||||
predicate missingAnnotationForCallable(string name, Call call) {
|
||||
call = annotatedCall(name) and
|
||||
not exists(annotatedCallable(name))
|
||||
call = annotatedCall(name) and
|
||||
not exists(annotatedCallable(name))
|
||||
}
|
||||
|
||||
predicate nonUniqueAnnotationForCallable(string name, Function callable) {
|
||||
strictcount(annotatedCallable(name)) > 1 and
|
||||
callable = annotatedCallable(name)
|
||||
strictcount(annotatedCallable(name)) > 1 and
|
||||
callable = annotatedCallable(name)
|
||||
}
|
||||
|
||||
predicate missingAnnotationForCall(string name, Function callable) {
|
||||
not exists(annotatedCall(name)) and
|
||||
callable = annotatedCallable(name)
|
||||
not exists(annotatedCall(name)) and
|
||||
callable = annotatedCallable(name)
|
||||
}
|
||||
|
||||
/** There is an obvious problem with the annotation `name` */
|
||||
predicate nameInErrorState(string name) {
|
||||
missingAnnotationForCallable(name, _)
|
||||
or
|
||||
nonUniqueAnnotationForCallable(name, _)
|
||||
or
|
||||
missingAnnotationForCall(name, _)
|
||||
missingAnnotationForCallable(name, _)
|
||||
or
|
||||
nonUniqueAnnotationForCallable(name, _)
|
||||
or
|
||||
missingAnnotationForCall(name, _)
|
||||
}
|
||||
|
||||
/** Source code has annotation with `name` showing that `call` will call `callable` */
|
||||
predicate annotatedCallEdge(string name, Call call, Function callable) {
|
||||
not nameInErrorState(name) and
|
||||
call = annotatedCall(name) and
|
||||
callable = annotatedCallable(name)
|
||||
not nameInErrorState(name) and
|
||||
call = annotatedCall(name) and
|
||||
callable = annotatedCallable(name)
|
||||
}
|
||||
|
||||
// ------------------------- Annotation debug query predicates -------------------------
|
||||
query predicate debug_missingAnnotationForCallable(Call call, string message) {
|
||||
exists(string name |
|
||||
message =
|
||||
"This call is annotated with '" + name +
|
||||
"', but no callable with that annotation was extracted. Please fix." and
|
||||
missingAnnotationForCallable(name, call)
|
||||
)
|
||||
exists(string name |
|
||||
message =
|
||||
"This call is annotated with '" + name +
|
||||
"', but no callable with that annotation was extracted. Please fix." and
|
||||
missingAnnotationForCallable(name, call)
|
||||
)
|
||||
}
|
||||
|
||||
query predicate debug_nonUniqueAnnotationForCallable(Function callable, string message) {
|
||||
exists(string name |
|
||||
message = "Multiple callables are annotated with '" + name + "'. Please fix." and
|
||||
nonUniqueAnnotationForCallable(name, callable)
|
||||
)
|
||||
exists(string name |
|
||||
message = "Multiple callables are annotated with '" + name + "'. Please fix." and
|
||||
nonUniqueAnnotationForCallable(name, callable)
|
||||
)
|
||||
}
|
||||
|
||||
query predicate debug_missingAnnotationForCall(Function callable, string message) {
|
||||
exists(string name |
|
||||
message =
|
||||
"This callable is annotated with '" + name +
|
||||
"', but no call with that annotation was extracted. Please fix." and
|
||||
missingAnnotationForCall(name, callable)
|
||||
)
|
||||
exists(string name |
|
||||
message =
|
||||
"This callable is annotated with '" + name +
|
||||
"', but no call with that annotation was extracted. Please fix." and
|
||||
missingAnnotationForCall(name, callable)
|
||||
)
|
||||
}
|
||||
|
||||
// ------------------------- Call Graph resolution -------------------------
|
||||
private newtype TCallGraphResolver =
|
||||
TPointsToResolver() or
|
||||
TTypeTrackerResolver()
|
||||
TPointsToResolver() or
|
||||
TTypeTrackerResolver()
|
||||
|
||||
/** Describes a method of call graph resolution */
|
||||
abstract class CallGraphResolver extends TCallGraphResolver {
|
||||
abstract predicate callEdge(Call call, Function callable);
|
||||
abstract predicate callEdge(Call call, Function callable);
|
||||
|
||||
/**
|
||||
* Holds if annotations show that `call` will call `callable`,
|
||||
* but our call graph resolver was not able to figure that out
|
||||
*/
|
||||
predicate expectedCallEdgeNotFound(Call call, Function callable) {
|
||||
annotatedCallEdge(_, call, callable) and
|
||||
not this.callEdge(call, callable)
|
||||
}
|
||||
/**
|
||||
* Holds if annotations show that `call` will call `callable`,
|
||||
* but our call graph resolver was not able to figure that out
|
||||
*/
|
||||
predicate expectedCallEdgeNotFound(Call call, Function callable) {
|
||||
annotatedCallEdge(_, call, callable) and
|
||||
not this.callEdge(call, callable)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there are no annotations that show that `call` will call `callable` (where at least one of these are annotated),
|
||||
* but the call graph resolver claims that `call` will call `callable`
|
||||
*/
|
||||
predicate unexpectedCallEdgeFound(Call call, Function callable, string message) {
|
||||
this.callEdge(call, callable) and
|
||||
not annotatedCallEdge(_, call, callable) and
|
||||
(
|
||||
exists(string name |
|
||||
message = "Call resolved to the callable named '" + name + "' but was not annotated as such" and
|
||||
callable = annotatedCallable(name) and
|
||||
not nameInErrorState(name)
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
message = "Annotated call resolved to unannotated callable" and
|
||||
call = annotatedCall(name) and
|
||||
not nameInErrorState(name) and
|
||||
not exists( | callable = annotatedCallable(_))
|
||||
)
|
||||
)
|
||||
}
|
||||
/**
|
||||
* Holds if there are no annotations that show that `call` will call `callable` (where at least one of these are annotated),
|
||||
* but the call graph resolver claims that `call` will call `callable`
|
||||
*/
|
||||
predicate unexpectedCallEdgeFound(Call call, Function callable, string message) {
|
||||
this.callEdge(call, callable) and
|
||||
not annotatedCallEdge(_, call, callable) and
|
||||
(
|
||||
exists(string name |
|
||||
message = "Call resolved to the callable named '" + name + "' but was not annotated as such" and
|
||||
callable = annotatedCallable(name) and
|
||||
not nameInErrorState(name)
|
||||
)
|
||||
or
|
||||
exists(string name |
|
||||
message = "Annotated call resolved to unannotated callable" and
|
||||
call = annotatedCall(name) and
|
||||
not nameInErrorState(name) and
|
||||
not exists( | callable = annotatedCallable(_))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
string toString() { result = "CallGraphResolver" }
|
||||
string toString() { result = "CallGraphResolver" }
|
||||
}
|
||||
|
||||
/** A call graph resolver based on the existing points-to analysis */
|
||||
class PointsToResolver extends CallGraphResolver, TPointsToResolver {
|
||||
override predicate callEdge(Call call, Function callable) {
|
||||
exists(PythonFunctionValue funcValue |
|
||||
funcValue.getScope() = callable and
|
||||
call = funcValue.getACall().getNode()
|
||||
)
|
||||
}
|
||||
override predicate callEdge(Call call, Function callable) {
|
||||
exists(PythonFunctionValue funcValue |
|
||||
funcValue.getScope() = callable and
|
||||
call = funcValue.getACall().getNode()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = "PointsToResolver" }
|
||||
override string toString() { result = "PointsToResolver" }
|
||||
}
|
||||
|
||||
/** A call graph resolved based on Type Trackers */
|
||||
class TypeTrackerResolver extends CallGraphResolver, TTypeTrackerResolver {
|
||||
override predicate callEdge(Call call, Function callable) { none() }
|
||||
override predicate callEdge(Call call, Function callable) { none() }
|
||||
|
||||
override string toString() { result = "TypeTrackerResolver" }
|
||||
override string toString() { result = "TypeTrackerResolver" }
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import python
|
|||
import CallGraphTest
|
||||
|
||||
query predicate expectedCallEdgeNotFound(Call call, Function callable) {
|
||||
any(PointsToResolver r).expectedCallEdgeNotFound(call, callable)
|
||||
any(PointsToResolver r).expectedCallEdgeNotFound(call, callable)
|
||||
}
|
||||
|
||||
query predicate unexpectedCallEdgeFound(Call call, Function callable, string message) {
|
||||
any(PointsToResolver r).unexpectedCallEdgeFound(call, callable, message)
|
||||
any(PointsToResolver r).unexpectedCallEdgeFound(call, callable, message)
|
||||
}
|
||||
|
|
|
@ -1,15 +1,14 @@
|
|||
import python
|
||||
|
||||
import CallGraphTest
|
||||
|
||||
query predicate pointsTo_found_typeTracker_notFound(Call call, Function callable) {
|
||||
annotatedCallEdge(_, call, callable) and
|
||||
any(PointsToResolver r).callEdge(call, callable) and
|
||||
not any(TypeTrackerResolver r).callEdge(call, callable)
|
||||
annotatedCallEdge(_, call, callable) and
|
||||
any(PointsToResolver r).callEdge(call, callable) and
|
||||
not any(TypeTrackerResolver r).callEdge(call, callable)
|
||||
}
|
||||
|
||||
query predicate pointsTo_notFound_typeTracker_found(Call call, Function callable) {
|
||||
annotatedCallEdge(_, call, callable) and
|
||||
not any(PointsToResolver r).callEdge(call, callable) and
|
||||
any(TypeTrackerResolver r).callEdge(call, callable)
|
||||
annotatedCallEdge(_, call, callable) and
|
||||
not any(PointsToResolver r).callEdge(call, callable) and
|
||||
any(TypeTrackerResolver r).callEdge(call, callable)
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@ import python
|
|||
import CallGraphTest
|
||||
|
||||
query predicate expectedCallEdgeNotFound(Call call, Function callable) {
|
||||
any(TypeTrackerResolver r).expectedCallEdgeNotFound(call, callable)
|
||||
any(TypeTrackerResolver r).expectedCallEdgeNotFound(call, callable)
|
||||
}
|
||||
|
||||
query predicate unexpectedCallEdgeFound(Call call, Function callable, string message) {
|
||||
any(TypeTrackerResolver r).unexpectedCallEdgeFound(call, callable, message)
|
||||
any(TypeTrackerResolver r).unexpectedCallEdgeFound(call, callable, message)
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче