mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
JS: Add call-graph test for accessor calls
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
spuriousCallee
|
||||
missingCallee
|
||||
| constructor-field.ts:40:5:40:14 | f3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 |
|
||||
| constructor-field.ts:71:1:71:11 | bf3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 |
|
||||
| constructor-field.ts:40:5:40:14 | f3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 | calls |
|
||||
| constructor-field.ts:71:1:71:11 | bf3.build() | constructor-field.ts:13:3:13:12 | build() {} | -1 | calls |
|
||||
badAnnotation
|
||||
|
||||
@@ -25,16 +25,28 @@ class AnnotatedFunction extends Function {
|
||||
}
|
||||
|
||||
/** A function annotated with `calls:NAME` */
|
||||
class AnnotatedCall extends InvokeExpr {
|
||||
class AnnotatedCall extends DataFlow::SourceNode {
|
||||
string calls;
|
||||
string kind;
|
||||
|
||||
AnnotatedCall() { calls = getAnnotation(this, "calls") }
|
||||
AnnotatedCall() {
|
||||
this instanceof DataFlow::InvokeNode and
|
||||
calls = getAnnotation(this.asExpr(), kind) and
|
||||
kind = "calls"
|
||||
or
|
||||
this instanceof DataFlow::PropRef and
|
||||
calls = getAnnotation(this.getAstNode(), kind) and
|
||||
kind = "callsAccessor"
|
||||
}
|
||||
|
||||
string getCallTargetName() { result = calls }
|
||||
|
||||
AnnotatedFunction getAnExpectedCallee() { result.getCalleeName() = getCallTargetName() }
|
||||
AnnotatedFunction getAnExpectedCallee(string kind_) {
|
||||
result.getCalleeName() = getCallTargetName() and
|
||||
kind = kind_
|
||||
}
|
||||
|
||||
int getBoundArgs() { result = getAnnotation(this, "boundArgs").toInt() }
|
||||
int getBoundArgs() { result = getAnnotation(this.getAstNode(), "boundArgs").toInt() }
|
||||
|
||||
int getBoundArgsOrMinusOne() {
|
||||
result = getBoundArgs()
|
||||
@@ -42,25 +54,31 @@ class AnnotatedCall extends InvokeExpr {
|
||||
not exists(getBoundArgs()) and
|
||||
result = -1
|
||||
}
|
||||
|
||||
string getKind() {
|
||||
result = kind
|
||||
}
|
||||
}
|
||||
|
||||
predicate callEdge(AnnotatedCall call, AnnotatedFunction target, int boundArgs) {
|
||||
FlowSteps::calls(call.flow(), target) and boundArgs = -1
|
||||
FlowSteps::calls(call, target) and boundArgs = -1
|
||||
or
|
||||
FlowSteps::callsBound(call.flow(), target, boundArgs)
|
||||
FlowSteps::callsBound(call, target, boundArgs)
|
||||
}
|
||||
|
||||
query predicate spuriousCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs) {
|
||||
query predicate spuriousCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs, string kind) {
|
||||
callEdge(call, target, boundArgs) and
|
||||
kind = call.getKind() and
|
||||
not (
|
||||
target = call.getAnExpectedCallee() and
|
||||
target = call.getAnExpectedCallee(kind) and
|
||||
boundArgs = call.getBoundArgsOrMinusOne()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate missingCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs) {
|
||||
query predicate missingCallee(AnnotatedCall call, AnnotatedFunction target, int boundArgs, string kind) {
|
||||
not callEdge(call, target, boundArgs) and
|
||||
target = call.getAnExpectedCallee() and
|
||||
kind = call.getKind() and
|
||||
target = call.getAnExpectedCallee(kind) and
|
||||
boundArgs = call.getBoundArgsOrMinusOne()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import 'dummy';
|
||||
|
||||
let obj = {
|
||||
/** name:obj.f.get */
|
||||
get f() {},
|
||||
|
||||
/** name:obj.f.set */
|
||||
set f(x) {}
|
||||
};
|
||||
|
||||
/** callsAccessor:obj.f.get */
|
||||
obj.f;
|
||||
|
||||
/** callsAccessor:obj.f.set */
|
||||
obj.f = 1;
|
||||
|
||||
class C {
|
||||
/** name:C.f.get */
|
||||
static get f() {}
|
||||
|
||||
/** name:C.f.set */
|
||||
static set f(x) {}
|
||||
}
|
||||
|
||||
/** callsAccessor:C.f.get */
|
||||
C.f;
|
||||
|
||||
/** callsAccessor:C.f.set */
|
||||
C.f = 1;
|
||||
|
||||
|
||||
class D {
|
||||
/** name:D.f.get */
|
||||
get f() {}
|
||||
|
||||
/** name:D.f.set */
|
||||
set f(x) {}
|
||||
}
|
||||
|
||||
/** callsAccessor:D.f.get */
|
||||
new D().f;
|
||||
|
||||
/** callsAccessor:D.f.set */
|
||||
new D().f = 1;
|
||||
Reference in New Issue
Block a user