diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll index 75ab4dbb2ebd5..68ffe57f5f59d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -341,6 +341,21 @@ module BarrierGuard { localFlow(pragma[only_bind_out](outp.getNode(c)), resNode) } + private predicate onlyPossibleReturnSatisfyingProperty( + FuncDecl fd, FunctionOutput outp, Node ret, DataFlow::Property p + ) { + exists(boolean b | + onlyPossibleReturnOfBool(fd, outp, ret, b) and + p.isBoolean(b) + ) + or + onlyPossibleReturnOfNonNil(fd, outp, ret) and + p.isNonNil() + or + onlyPossibleReturnOfNil(fd, outp, ret) and + p.isNil() + } + /** * Holds if whenever `p` holds of output `outp` of function `f`, this node * is known to validate the input `inp` of `f`. @@ -356,23 +371,13 @@ module BarrierGuard { exists(FuncDecl fd, Node arg, Node ret | fd.getFunction() = f and localFlow(inp.getExitNode(fd), pragma[only_bind_out](arg)) and - ret = outp.getEntryNode(fd) and ( // Case: a function like "if someBarrierGuard(arg) { return true } else { return false }" exists(ControlFlow::ConditionGuardNode guard | - guards(g, guard, arg) and - guard.dominates(ret.getBasicBlock()) + guards(g, pragma[only_bind_out](guard), arg) and + guard.dominates(pragma[only_bind_out](ret).getBasicBlock()) | - exists(boolean b | - onlyPossibleReturnOfBool(fd, outp, ret, b) and - p.isBoolean(b) - ) - or - onlyPossibleReturnOfNonNil(fd, outp, ret) and - p.isNonNil() - or - onlyPossibleReturnOfNil(fd, outp, ret) and - p.isNil() + onlyPossibleReturnSatisfyingProperty(fd, outp, ret, p) ) or // Case: a function like "return someBarrierGuard(arg)"