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/local-unhandled-custom-error
*/
import cpp
import semmle.code.cpp.dataflow.TaintTracking
class IgnoredFile extends File {
IgnoredFile() {
this.getAbsolutePath().matches("%test%")
}
}
class CustomError extends FunctionCall {
CustomError() {
this.getUnderlyingType().getName() = "CustomErrorType"
}
// True if the return value is checked locally.
predicate isCheckedLocally() {
// The return value flows into the condition of an if-statement.
exists (IfStmt is |
TaintTracking::localTaint(
DataFlow::exprNode(this),
DataFlow::exprNode(is.getCondition().getAChild*())
)
) or
// The return value flows into the condition of a while-statement.
exists (WhileStmt ws |
TaintTracking::localTaint(
DataFlow::exprNode(this),
DataFlow::exprNode(ws.getCondition().getAChild*())
)
) or
// The return value flows into the condition of a switch-statement.
exists (SwitchStmt ss |
TaintTracking::localTaint(
DataFlow::exprNode(this),
DataFlow::exprNode(ss.getExpr().getAChild*())
)
)
}
// The return value is returned from the enclosing function.
predicate isReturnValue() {
exists (ReturnStmt rs |
TaintTracking::localTaint(
DataFlow::exprNode(this),
DataFlow::exprNode(rs.getExpr())
)
)
}
// The return value is passed as an argument to another function.
predicate isPassedToFunction() {
exists (FunctionCall fc |
TaintTracking::localTaint(
DataFlow::exprNode(this),
DataFlow::exprNode(fc.getAnArgument())
)
)
}
// Test if the return value is assigned to a member variable.
predicate isAssignedToMemberVar() {
exists (MemberVariable mv, MemberFunction mf |
mf = this.getEnclosingFunction() and
mf.canAccessMember(mv, mf.getDeclaringType()) and
TaintTracking::localTaint(
DataFlow::exprNode(this),
DataFlow::exprNode(mv.getAnAccess())
)
)
}
predicate isChecked() {
this.isReturnValue() or
this.isCheckedLocally() or
this.isPassedToFunction() or
this.isAssignedToMemberVar()
}
}
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