Skip to content

Commit 43109f5

Browse files
committed
Refactor call graph predicates for vulnerable method detection
Introduces materialized predicates for static and external function calls, and for mapping functions to fully qualified names. Refactors the transitive vulnerable method detection logic to use these new predicates, improving clarity and maintainability.
1 parent b9ccfee commit 43109f5

1 file changed

Lines changed: 37 additions & 15 deletions

File tree

binary/ql/src/VulnerableCalls/VulnerableCalls.qll

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,35 @@ Function getStateMachineImplementation(Function stub) {
8080
isStateMachineImplementation(stub, result)
8181
}
8282

83+
/**
84+
* Materialized: holds if function `caller` contains a call to function `callee`
85+
* via a static target (direct call).
86+
*/
87+
pragma[nomagic]
88+
private predicate callsViaStaticTarget(Function caller, Function callee) {
89+
callee = any(CallInstruction call | call.getEnclosingFunction() = caller).getStaticTarget()
90+
}
91+
92+
/**
93+
* Materialized: holds if function `caller` contains a call to a function
94+
* with fully qualified name `calleeFqn` via an external reference.
95+
*/
96+
pragma[nomagic]
97+
private predicate callsViaExternalRef(Function caller, string calleeFqn) {
98+
exists(CallInstruction call |
99+
call.getEnclosingFunction() = caller and
100+
calleeFqn = call.getTargetOperand().getAnyDef().(ExternalRefInstruction).getFullyQualifiedName()
101+
)
102+
}
103+
104+
/**
105+
* Materialized: maps functions to their fully qualified names.
106+
*/
107+
pragma[nomagic]
108+
private predicate functionFqn(Function f, string fqn) {
109+
fqn = f.getFullyQualifiedName()
110+
}
111+
83112
/**
84113
* Gets a method that transitively calls a vulnerable method.
85114
* This computes the transitive closure of the call graph.
@@ -91,26 +120,19 @@ Function getAVulnerableMethod(string id) {
91120
// Direct call to vulnerable method
92121
result = getADirectlyVulnerableMethod(id)
93122
or
94-
// Transitive: method calls another method that is vulnerable (via ExternalRef for external calls)
95-
exists(CallInstruction call, Function callee |
96-
call.getEnclosingFunction() = result and
97-
callee = getAVulnerableMethod(id) and
98-
call.getTargetOperand().getAnyDef().(ExternalRefInstruction).getFullyQualifiedName() =
99-
callee.getFullyQualifiedName()
100-
)
123+
// Transitive: method calls a vulnerable method via static target
124+
callsViaStaticTarget(result, getAVulnerableMethod(id))
101125
or
102-
// Transitive: method calls another method that is vulnerable (via static target for direct calls)
103-
exists(CallInstruction call |
104-
call.getEnclosingFunction() = result and
105-
call.getStaticTarget() = getAVulnerableMethod(id)
126+
// Transitive: method calls a vulnerable method via external reference
127+
exists(Function callee, string calleeFqn |
128+
callee = getAVulnerableMethod(id) and
129+
functionFqn(callee, calleeFqn) and
130+
callsViaExternalRef(result, calleeFqn)
106131
)
107132
or
108133
// Iterator/async: if a state machine's MoveNext is vulnerable,
109134
// the stub method that creates it is also vulnerable
110-
exists(Function stateMachine |
111-
stateMachine = getAVulnerableMethod(id) and
112-
isStateMachineImplementation(result, stateMachine)
113-
)
135+
isStateMachineImplementation(result, getAVulnerableMethod(id))
114136
}
115137

116138
/**

0 commit comments

Comments
 (0)