From 9957cbe65602b14938ca9fef09b754213f661e54 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 29 Jul 2025 15:04:22 +0200 Subject: [PATCH] Java/Guards: Improve BarrierGuards to include `validate(x = ...)` checks. --- .../code/java/dataflow/internal/SsaImpl.qll | 8 ++++--- .../controlflow/codeql/controlflow/Guards.qll | 22 ++++++++++++++----- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll index deb42d045bf..51da69e9d64 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll @@ -567,13 +567,15 @@ private module Cached { } private predicate guardChecksWithWrappers( - DataFlowIntegrationInput::Guard g, DataFlowIntegrationInput::Expr e, Guards::GuardValue val + DataFlowIntegrationInput::Guard g, Definition def, Guards::GuardValue val, Unit state ) { - Guards::Guards_v3::ValidationWrapper::guardChecks(g, e, val) + Guards::Guards_v3::ValidationWrapper::guardChecksDef(g, def, val) and + exists(state) } private Node getABarrierNodeImpl() { - result = DataFlowIntegrationImpl::BarrierGuard::getABarrierNode() + result = + DataFlowIntegrationImpl::BarrierGuardDefWithState::getABarrierNode(_) } predicate getABarrierNode = getABarrierNodeImpl/0; diff --git a/shared/controlflow/codeql/controlflow/Guards.qll b/shared/controlflow/codeql/controlflow/Guards.qll index 34f42036292..7a643fce9e7 100644 --- a/shared/controlflow/codeql/controlflow/Guards.qll +++ b/shared/controlflow/codeql/controlflow/Guards.qll @@ -1130,10 +1130,10 @@ module Make Input> { private module StatefulWrapper = ValidationWrapperWithState; /** - * Holds if the guard `g` validates the expression `e` upon evaluating to `val`. + * Holds if the guard `g` validates the SSA definition `def` upon evaluating to `val`. */ - predicate guardChecks(Guard g, Expr e, GuardValue val) { - StatefulWrapper::guardChecks(g, e, val, _) + predicate guardChecksDef(Guard g, SsaDefinition def, GuardValue val) { + StatefulWrapper::guardChecksDef(g, def, val, _) } } @@ -1156,7 +1156,7 @@ module Make Input> { exists(NonOverridableMethod m, SsaDefinition param, Guard guard, GuardValue val | m.getAReturnExpr() = ret and parameterDefinition(m.getParameter(ppos), param) and - guardChecks(guard, param.getARead(), val, state) + guardChecksDef(guard, param, val, state) | guard.valueControls(ret.getBasicBlock(), val) and relevantReturnValue(m, retval) @@ -1185,7 +1185,7 @@ module Make Input> { or exists(SsaDefinition param, BasicBlock bb, Guard guard, GuardValue val | parameterDefinition(result.getParameter(ppos), param) and - guardChecks(guard, param.getARead(), val, state) and + guardChecksDef(guard, param, val, state) and guard.valueControls(bb, val) and normalExitBlock(bb) and retval = TException(false) @@ -1195,7 +1195,7 @@ module Make Input> { /** * Holds if the guard `g` validates the expression `e` upon evaluating to `val`. */ - predicate guardChecks(Guard g, Expr e, GuardValue val, State state) { + private predicate guardChecks(Guard g, Expr e, GuardValue val, State state) { guardChecks0(g, e, val.asBooleanValue(), state) or exists(NonOverridableMethodCall call, ParameterPosition ppos, ArgumentPosition apos | @@ -1205,6 +1205,16 @@ module Make Input> { parameterMatch(pragma[only_bind_out](ppos), pragma[only_bind_out](apos)) ) } + + /** + * Holds if the guard `g` validates the SSA definition `def` upon evaluating to `val`. + */ + predicate guardChecksDef(Guard g, SsaDefinition def, GuardValue val, State state) { + exists(Expr e | + guardChecks(g, e, val, state) and + guardReadsSsaVar(e, def) + ) + } } /**