diff --git a/ql/src/semmle/go/Expr.qll b/ql/src/semmle/go/Expr.qll index 522567d35a4..3d3089ae161 100644 --- a/ql/src/semmle/go/Expr.qll +++ b/ql/src/semmle/go/Expr.qll @@ -595,10 +595,10 @@ class SelectorExpr extends @selectorexpr, Expr { /** * A selector expression that refers to a promoted field. These selectors may implicitly - * address an embedded struct of their base type (e.g. the selector `x.field` may implicitly - * address `x.Embedded.field`). Note they may also explicitly address `field`; being a - * `PromotedFieldSelector` only indicates the addressed field may be promoted, not that it - * is promoted in this particular context. + * address an embedded struct of their base type - for example, the selector `x.field` may + * implicitly address `x.Embedded.field`). Note they may also explicitly address `field`; + * being a `PromotedFieldSelector` only indicates the addressed field may be promoted, not + * that it is promoted in this particular context. */ class PromotedFieldSelector extends SelectorExpr { PromotedFieldSelector() { this.refersTo(any(PromotedField f)) } diff --git a/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll b/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll index 911e296f9d8..3f8b9f10218 100644 --- a/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll +++ b/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll @@ -48,6 +48,13 @@ private predicate isCond(Expr e) { e = any(ParenExpr par | isCond(par)).getExpr() } +/** + * Holds if `e` implicitly reads the embedded field `implicitField`. + * + * The `index` is the distance from the promoted field. For example, if `A` contains an embedded + * field `B`, `B` contains an embedded field `C` and `C` contains the non-embedded field `x`. + * Then `a.x` implicitly reads `C` with index 1 and `B` with index 2. + */ private predicate implicitFieldSelection(PromotedFieldSelector e, int index, Field implicitField) { exists(StructType baseType, PromotedField child, int implicitFieldDepth | baseType = e.getSelectedStructType() and @@ -326,7 +333,7 @@ newtype TControlFlowNode = * If that field has a pointer type then this control-flow node also * represents an implicit dereference of it. */ - MkImplicitFieldSelection(SelectorExpr e, int i, Field implicitField) { + MkImplicitFieldSelection(PromotedFieldSelector e, int i, Field implicitField) { implicitFieldSelection(e, i, implicitField) } or /** diff --git a/ql/src/semmle/go/controlflow/IR.qll b/ql/src/semmle/go/controlflow/IR.qll index 4789014c0fd..c6591c8a02c 100644 --- a/ql/src/semmle/go/controlflow/IR.qll +++ b/ql/src/semmle/go/controlflow/IR.qll @@ -243,8 +243,8 @@ module IR { * and implicit field reads into account. * * For a selector expression `b.f`, this could be the implicit dereference `*b`, or the implicit - * field access `b.Embedded.f` if the field `f` is promoted from an embedded type `Embedded`, or - * a combination of both, or simply `b` if neither case applies. + * field access `b.Embedded` if the field `f` is promoted from an embedded type `Embedded`, or a + * combination of both `*(b.Embedded)`, or simply `b` if neither case applies. */ private Instruction selectorBase(Expr e) { exists(ImplicitFieldReadInstruction fri | fri.getSelectorExpr() = e and fri.getIndex() = 1 | @@ -305,7 +305,7 @@ module IR { FieldReadInstruction() { e = this.(EvalInstruction).getExpr() and index = 0 and - field.getAReference() = this.(EvalInstruction).getExpr().(SelectorExpr).getSelector() + field.getAReference() = e.getSelector() or e = this.(ImplicitFieldReadInstruction).getSelectorExpr() and index = this.(ImplicitFieldReadInstruction).getIndex() and @@ -348,8 +348,8 @@ module IR { * An IR instruction for an implicit field read as part of reading a * promoted field. * - * If that field has a pointer type then this instruction also represents an - * implicit dereference of it. + * If the field that is being implicitly read has a pointer type then this + * instruction represents an implicit dereference of it. */ class ImplicitFieldReadInstruction extends Instruction, MkImplicitFieldSelection { SelectorExpr e;