Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
/**
* @name Unhandled CustomError
* @description A CustomError is returned from this function but it is not handled by the calling code.
* @kind path-problem
* @problem.severity warning
* @precision medium
* @tags security
* @id tob/global-unhandled-custom-error
*/
import cpp
import semmle.code.cpp.dataflow.TaintTracking
class IgnoredFile extends File {
IgnoredFile() {
this.getAbsolutePath().matches("%test%")
}
}
class IgnoredFunctionCall extends FunctionCall {
IgnoredFunctionCall() {
this.getTarget().getName() in ["CreateUserResponse"]
}
}
class CustomError extends FunctionCall {
CustomError() {
this.getUnderlyingType().getName() = "CustomErrorType"
}
predicate isCheckedAt(Expr guard) {
exists (GuardConfiguration config |
config.hasFlow(
DataFlow::exprNode(this),
DataFlow::exprNode(guard)
)
)
}
predicate isChecked() {
exists (Expr guard | this.isCheckedAt(guard))
}
}
class GuardConfiguration extends TaintTracking::Configuration {
GuardConfiguration() { this = "GuardConfiguration" }
override predicate isSource(DataFlow::Node source) {
source.asExpr() instanceof CustomError
}
override predicate isSink(DataFlow::Node sink) {
exists (IfStmt is | sink.asExpr() = is.getCondition().getAChild*()) or
exists (WhileStmt ws | sink.asExpr() = ws.getCondition().getAChild*()) or
exists (SwitchStmt ss | sink.asExpr() = ss.getExpr().getAChild*()) or
exists (IgnoredFunctionCall fc | sink.asExpr() = fc.getAnArgument().getAChild*())
}
}
from
CustomError ce
where
not ce.isChecked() and
not ce.getFile() instanceof IgnoredFile
select
ce.getLocation(),
"Unhandled error code in ", ce.getEnclosingFunction().getName(),
"Error code returned by ", ce.getTarget().getName()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment