mirror of
https://github.com/github/codeql.git
synced 2025-12-18 09:43:15 +01:00
84 lines
3.1 KiB
Plaintext
84 lines
3.1 KiB
Plaintext
/**
|
|
* Provides classes for different types of handler.
|
|
*/
|
|
|
|
private import CIL
|
|
|
|
/**
|
|
* A handler is a piece of code that can be executed out of sequence, for example
|
|
* when an instruction generates an exception or leaves a `finally` block.
|
|
*
|
|
* Each handler has a scope representing the block of instructions guarded by
|
|
* this handler (corresponding to a C# `try { ... }` block), and a block of instructions
|
|
* to execute when the handler is triggered (corresponding to a `catch` or `finally` block).
|
|
*
|
|
* Handlers are entry points (`EntryPoint`) so that they can
|
|
* provide values on the stack, for example the value of the current exception. This is why
|
|
* some handlers have a push count of 1.
|
|
*
|
|
* Either a finally handler (`FinallyHandler`), filter handler (`FilterHandler`),
|
|
* catch handler (`CatchHandler`), or a fault handler (`FaultHandler`).
|
|
*/
|
|
class Handler extends Element, EntryPoint, @cil_handler {
|
|
override MethodImplementation getImplementation() { cil_handler(this, result, _, _, _, _, _) }
|
|
|
|
/** Gets the 0-based index of this handler. Handlers are evaluated in this sequence. */
|
|
int getIndex() { cil_handler(this, _, result, _, _, _, _) }
|
|
|
|
/** Gets the first instruction in the `try` block of this handler. */
|
|
Instruction getTryStart() { cil_handler(this, _, _, _, result, _, _) }
|
|
|
|
/** Gets the last instruction in the `try` block of this handler. */
|
|
Instruction getTryEnd() { cil_handler(this, _, _, _, _, result, _) }
|
|
|
|
/** Gets the first instruction in the `catch`/`finally` block. */
|
|
Instruction getHandlerStart() { cil_handler(this, _, _, _, _, _, result) }
|
|
|
|
/**
|
|
* Holds if the instruction `i` is in the scope of this handler.
|
|
*/
|
|
predicate isInScope(Instruction i) {
|
|
i.getImplementation() = getImplementation() and
|
|
i.getIndex() in [getTryStart().getIndex() .. getTryEnd().getIndex()]
|
|
}
|
|
|
|
override string toString() { none() }
|
|
|
|
override Instruction getASuccessorType(FlowType t) {
|
|
result = getHandlerStart() and
|
|
t instanceof NormalFlow
|
|
}
|
|
|
|
/** Gets the type of the caught exception, if any. */
|
|
Type getCaughtType() { cil_handler_type(this, result) }
|
|
|
|
override Location getLocation() { result = getTryStart().getLocation() }
|
|
}
|
|
|
|
/** A handler corresponding to a `finally` block. */
|
|
class FinallyHandler extends Handler, @cil_finally_handler {
|
|
override string toString() { result = "finally {...}" }
|
|
}
|
|
|
|
/** A handler corresponding to a `where()` clause. */
|
|
class FilterHandler extends Handler, @cil_filter_handler {
|
|
override string toString() { result = "where (...)" }
|
|
|
|
/** Gets the filter clause - the start of a sequence of instructions to evaluate the filter function. */
|
|
Instruction getFilterClause() { cil_handler_filter(this, result) }
|
|
|
|
override int getPushCount() { result = 1 }
|
|
}
|
|
|
|
/** A handler corresponding to a `catch` clause. */
|
|
class CatchHandler extends Handler, @cil_catch_handler {
|
|
override string toString() { result = "catch(" + getCaughtType().getName() + ") {...}" }
|
|
|
|
override int getPushCount() { result = 1 }
|
|
}
|
|
|
|
/** A handler for memory faults. */
|
|
class FaultHandler extends Handler, @cil_fault_handler {
|
|
override string toString() { result = "fault {...}" }
|
|
}
|