diff --git a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll index 310dd496518..439e1c0d40d 100644 --- a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -392,6 +392,10 @@ class PostUpdateNode extends Node { ( preupd instanceof AddressOperationNode or + preupd = any(AddressOperationNode addr).getOperand() + or + preupd = any(PointerDereferenceNode deref).getOperand() + or exists(Write w, DataFlow::Node base | w.writesField(base, _, _) | preupd = base or diff --git a/ql/src/semmle/go/dataflow/internal/TaintTrackingUtil.qll b/ql/src/semmle/go/dataflow/internal/TaintTrackingUtil.qll index 23ec8757d10..772294a6f11 100644 --- a/ql/src/semmle/go/dataflow/internal/TaintTrackingUtil.qll +++ b/ql/src/semmle/go/dataflow/internal/TaintTrackingUtil.qll @@ -59,11 +59,32 @@ predicate localAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { any(AdditionalTaintStep a).step(pred, succ) } -/** Holds if taint flows from `pred` to `succ` via a reference or dereference. */ +/** + * Holds if taint flows from `pred` to `succ` via a reference or dereference. + * + * The taint-tracking library does not distinguish between a reference and its referent, + * treating one as tainted if the other is. + */ predicate referenceStep(DataFlow::Node pred, DataFlow::Node succ) { - succ.(DataFlow::AddressOperationNode).getOperand() = pred + exists(DataFlow::AddressOperationNode addr | + // from `x` to `&x` + pred = addr.getOperand() and + succ = addr + or + // from `&x` to `x` + pred = addr and + succ.(DataFlow::PostUpdateNode).getPreUpdateNode() = addr.getOperand() + ) or - succ.(DataFlow::PointerDereferenceNode).getOperand() = pred + exists(DataFlow::PointerDereferenceNode deref | + // from `x` to `*x` + pred = deref.getOperand() and + succ = deref + or + // from `*x` to `x` + pred = deref and + succ.(DataFlow::PostUpdateNode).getPreUpdateNode() = deref.getOperand() + ) } /** Holds if taint flows from `pred` to `succ` via a field read. */