mirror of
https://github.com/github/codeql.git
synced 2026-01-30 14:52:57 +01:00
Add implicit field reads for promoted fields
This may not work when the embedded fields are pointer types, as we don't have anything corresponding to MkImplicitDeref
This commit is contained in:
@@ -301,6 +301,22 @@ newtype TControlFlowNode =
|
||||
e = any(SliceExpr se).getBase()
|
||||
)
|
||||
} or
|
||||
/**
|
||||
* A control-flow node that represents the implicit selection of a field when accessing a
|
||||
* promoted field.
|
||||
*/
|
||||
MkImplicitFieldSelection(SelectorExpr e, int i, Field implicitField) {
|
||||
exists(Type baseType, StructType baseStructType, Field eField, int minDepth |
|
||||
eField.getAReference() = e.getSelector() and
|
||||
baseType = e.getBase().getType().getUnderlyingType() and
|
||||
baseStructType = [baseType, baseType.(PointerType).getBaseType().getUnderlyingType()] and
|
||||
baseStructType.getFieldAtDepth(_, minDepth) = eField
|
||||
|
|
||||
baseStructType.getFieldAtDepth(_, i) = implicitField and
|
||||
implicitField.getType().getUnderlyingType().(StructType).getFieldAtDepth(_, minDepth - i - 1) =
|
||||
eField
|
||||
)
|
||||
} or
|
||||
/**
|
||||
* A control-flow node that represents the start of the execution of a function or file.
|
||||
*/
|
||||
@@ -1708,16 +1724,25 @@ module CFG {
|
||||
}
|
||||
|
||||
override predicate succ(ControlFlow::Node pred, ControlFlow::Node succ) {
|
||||
lastNode(getBase(), pred, normalCompletion()) and
|
||||
(
|
||||
succ = MkImplicitDeref(this.getBase())
|
||||
or
|
||||
not exists(MkImplicitDeref(this.getBase())) and
|
||||
succ = mkExprOrSkipNode(this)
|
||||
)
|
||||
exists(int i | pred = this.getStepWithRank(i) and succ = this.getStepWithRank(i + 1))
|
||||
}
|
||||
|
||||
private ControlFlow::Node getStepOrdered(int i) {
|
||||
i = -2 and lastNode(this.getBase(), result, normalCompletion())
|
||||
or
|
||||
pred = MkImplicitDeref(this.getBase()) and
|
||||
succ = mkExprOrSkipNode(this)
|
||||
i = -1 and result = MkImplicitDeref(this.getBase())
|
||||
or
|
||||
result = MkImplicitFieldSelection(this, i, _)
|
||||
or
|
||||
i = max(int k | k = -1 or exists(MkImplicitFieldSelection(this, k, _))) + 1 and
|
||||
result = mkExprOrSkipNode(this)
|
||||
}
|
||||
|
||||
private ControlFlow::Node getStepWithRank(int i) {
|
||||
exists(int j |
|
||||
result = this.getStepOrdered(j) and
|
||||
j = rank[i + 1](int k | exists(this.getStepOrdered(k)))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,8 @@ module IR {
|
||||
this instanceof MkImplicitLowerSliceBound or
|
||||
this instanceof MkImplicitUpperSliceBound or
|
||||
this instanceof MkImplicitMaxSliceBound or
|
||||
this instanceof MkImplicitDeref
|
||||
this instanceof MkImplicitDeref or
|
||||
this instanceof MkImplicitFieldSelection
|
||||
}
|
||||
|
||||
/** Holds if this instruction reads the value of variable or constant `v`. */
|
||||
@@ -173,6 +174,8 @@ module IR {
|
||||
this instanceof MkImplicitMaxSliceBound and result = "implicit maximum"
|
||||
or
|
||||
this instanceof MkImplicitDeref and result = "implicit dereference"
|
||||
or
|
||||
this instanceof MkImplicitFieldSelection and result = "implicit field selection"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,6 +233,8 @@ module IR {
|
||||
)
|
||||
or
|
||||
this instanceof ReadResultInstruction
|
||||
or
|
||||
this instanceof ImplicitFieldReadInstruction
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,9 +246,16 @@ module IR {
|
||||
* `b` if there is no implicit dereferencing.
|
||||
*/
|
||||
private Instruction selectorBase(Expr e) {
|
||||
exists(Field field | field.getAReference() = e.(SelectorExpr).getSelector() |
|
||||
result = selectorBase(e, field)
|
||||
)
|
||||
or
|
||||
exists(Expr base |
|
||||
base = e.(SelectorExpr).getBase() or
|
||||
base = e.(IndexExpr).getBase() or
|
||||
base = e.(SelectorExpr).getBase() and
|
||||
e.(SelectorExpr).getSelector() = any(Method m).getAReference()
|
||||
or
|
||||
base = e.(IndexExpr).getBase()
|
||||
or
|
||||
base = e.(SliceExpr).getBase()
|
||||
|
|
||||
result = MkImplicitDeref(base)
|
||||
@@ -253,21 +265,51 @@ module IR {
|
||||
)
|
||||
}
|
||||
|
||||
private Instruction selectorBase(SelectorExpr se, Field field) {
|
||||
exists(Type baseType, StructType baseStructType |
|
||||
baseType = se.getBase().getType().getUnderlyingType() and
|
||||
baseStructType = [baseType, baseType.(PointerType).getBaseType().getUnderlyingType()]
|
||||
|
|
||||
if field = baseStructType.getOwnField(_, _)
|
||||
then
|
||||
result = MkImplicitDeref(se.getBase())
|
||||
or
|
||||
not exists(MkImplicitDeref(se.getBase())) and
|
||||
result = evalExprInstruction(se.getBase())
|
||||
else
|
||||
exists(ImplicitFieldReadInstruction ifri |
|
||||
ifri.getSelectorExpr() = se and
|
||||
ifri.getField().getType().getUnderlyingType().(StructType).getOwnField(_, _) = field
|
||||
|
|
||||
result = ifri
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* An IR instruction that reads a component from a composite object.
|
||||
*
|
||||
* This is either a field of a struct, or an element of an array, map, slice or string.
|
||||
*/
|
||||
class ComponentReadInstruction extends ReadInstruction, EvalInstruction {
|
||||
class ComponentReadInstruction extends ReadInstruction {
|
||||
ComponentReadInstruction() {
|
||||
e instanceof IndexExpr
|
||||
exists(Expr e | e = this.(EvalInstruction).getExpr() |
|
||||
e instanceof IndexExpr
|
||||
or
|
||||
e.(SelectorExpr).getBase() instanceof ValueExpr and
|
||||
not e.(SelectorExpr).getSelector() = any(Method method).getAReference()
|
||||
)
|
||||
or
|
||||
e.(SelectorExpr).getBase() instanceof ValueExpr and
|
||||
not e.(SelectorExpr).getSelector() = any(Method method).getAReference()
|
||||
this instanceof ImplicitFieldReadInstruction
|
||||
}
|
||||
|
||||
/** Gets the instruction computing the base value on which the field or element is read. */
|
||||
Instruction getBase() { result = selectorBase(e) }
|
||||
Instruction getBase() {
|
||||
result = selectorBase(this.(EvalInstruction).getExpr()) or
|
||||
result =
|
||||
selectorBase(this.(ImplicitFieldReadInstruction).getSelectorExpr(),
|
||||
this.(ImplicitFieldReadInstruction).getField())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,12 +319,51 @@ module IR {
|
||||
* misclassified as field reads.
|
||||
*/
|
||||
class FieldReadInstruction extends ComponentReadInstruction {
|
||||
override SelectorExpr e;
|
||||
SelectorExpr e;
|
||||
Field field;
|
||||
|
||||
FieldReadInstruction() {
|
||||
e = this.(EvalInstruction).getExpr() and
|
||||
field.getAReference() = this.(EvalInstruction).getExpr().(SelectorExpr).getSelector()
|
||||
or
|
||||
e = this.(ImplicitFieldReadInstruction).getSelectorExpr() and
|
||||
field = this.(ImplicitFieldReadInstruction).getField()
|
||||
}
|
||||
|
||||
/** Gets the field being read. */
|
||||
Field getField() { e.getSelector() = result.getAReference() }
|
||||
Field getField() { result = field }
|
||||
|
||||
override predicate readsField(Instruction base, Field f) { base = getBase() and f = getField() }
|
||||
override predicate readsField(Instruction base, Field f) {
|
||||
base = selectorBase(e, f) and f = field
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An IR instruction for an implicit field read as part of reading a promoted field.
|
||||
*/
|
||||
class ImplicitFieldReadInstruction extends Instruction, MkImplicitFieldSelection {
|
||||
SelectorExpr e;
|
||||
Field implicitField;
|
||||
|
||||
ImplicitFieldReadInstruction() { this = MkImplicitFieldSelection(e, _, implicitField) }
|
||||
|
||||
SelectorExpr getSelectorExpr() { result = e }
|
||||
|
||||
Field getField() { result = implicitField }
|
||||
|
||||
override predicate reads(ValueEntity v) { v = implicitField }
|
||||
|
||||
override Type getResultType() { result = implicitField.getType() }
|
||||
|
||||
override ControlFlow::Root getRoot() { result.isRootOf(e) }
|
||||
|
||||
override string toString() { result = "implicit read of field " + implicitField.toString() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
e.getBase().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,7 +389,7 @@ module IR {
|
||||
/**
|
||||
* An IR instruction that reads an element of an array, slice, map or string.
|
||||
*/
|
||||
class ElementReadInstruction extends ComponentReadInstruction {
|
||||
class ElementReadInstruction extends ComponentReadInstruction, EvalInstruction {
|
||||
override IndexExpr e;
|
||||
|
||||
/** Gets the instruction computing the index of the element being looked up. */
|
||||
|
||||
@@ -319,9 +319,9 @@ private TSsaWithFields accessPath(IR::Instruction insn) {
|
||||
* by ssa-with-fields value `base`.
|
||||
*/
|
||||
private IR::Instruction accessPathAux(TSsaWithFields base, Field f) {
|
||||
exists(IR::FieldReadInstruction fr, IR::EvalInstruction frb |
|
||||
exists(IR::FieldReadInstruction fr, IR::Instruction frb |
|
||||
fr.getBase() = frb or
|
||||
fr.getBase() = IR::implicitDerefInstruction(frb.getExpr())
|
||||
fr.getBase() = IR::implicitDerefInstruction(frb.(IR::EvalInstruction).getExpr())
|
||||
|
|
||||
base = accessPath(frb) and
|
||||
f = fr.getField() and
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
import go
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class SourceFunction extends Function {
|
||||
SourceFunction() { this.getName() = "source" }
|
||||
}
|
||||
|
||||
class SinkFunction extends Function {
|
||||
SinkFunction() { this.getName() = "sink" }
|
||||
}
|
||||
|
||||
class TestConfig extends DataFlow::Configuration {
|
||||
TestConfig() { this = "testconfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
source = any(SourceFunction f).getACall().getAResult()
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink = any(SinkFunction f).getACall().getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
class PromotedFieldsTest extends InlineExpectationsTest {
|
||||
PromotedFieldsTest() { this = "PromotedFieldsTest" }
|
||||
|
||||
override string getARelevantTag() { result = "promotedfields" }
|
||||
|
||||
override predicate hasActualResult(string file, int line, string element, string tag, string value) {
|
||||
exists(TestConfig config, DataFlow::PathNode source, DataFlow::PathNode sink |
|
||||
config.hasFlowPath(source, sink) and
|
||||
sink.hasLocationInfo(file, line, _, _, _) and
|
||||
element = sink.toString() and
|
||||
value = "" and
|
||||
tag = "promotedfields"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
| main.go:3:6:3:11 | function source | main.go:23:31:23:36 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:31:31:31:36 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:40:30:40:35 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:46:32:46:37 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:54:17:54:22 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:62:18:62:23 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:72:17:72:22 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:80:18:80:23 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:91:16:91:21 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:98:17:98:22 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:107:22:107:27 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:114:23:114:28 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:123:23:123:28 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:130:24:130:29 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:139:29:139:34 | source |
|
||||
| main.go:3:6:3:11 | function source | main.go:146:30:146:35 | source |
|
||||
| main.go:7:6:7:9 | function sink | main.go:25:2:25:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:26:2:26:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:27:2:27:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:28:2:28:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:33:2:33:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:34:2:34:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:35:2:35:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:36:2:36:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:41:2:41:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:42:2:42:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:43:2:43:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:44:2:44:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:47:2:47:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:48:2:48:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:49:2:49:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:50:2:50:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:57:2:57:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:58:2:58:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:59:2:59:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:60:2:60:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:65:2:65:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:66:2:66:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:67:2:67:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:68:2:68:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:75:2:75:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:76:2:76:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:77:2:77:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:78:2:78:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:83:2:83:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:84:2:84:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:85:2:85:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:86:2:86:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:92:2:92:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:93:2:93:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:94:2:94:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:95:2:95:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:99:2:99:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:100:2:100:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:101:2:101:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:102:2:102:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:108:2:108:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:109:2:109:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:110:2:110:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:111:2:111:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:115:2:115:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:116:2:116:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:117:2:117:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:118:2:118:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:124:2:124:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:125:2:125:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:126:2:126:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:127:2:127:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:131:2:131:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:132:2:132:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:133:2:133:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:134:2:134:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:140:2:140:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:141:2:141:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:142:2:142:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:143:2:143:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:147:2:147:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:148:2:148:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:149:2:149:5 | sink |
|
||||
| main.go:7:6:7:9 | function sink | main.go:150:2:150:5 | sink |
|
||||
| main.go:22:2:22:6 | definition of outer | main.go:25:7:25:11 | outer |
|
||||
| main.go:22:2:22:6 | definition of outer | main.go:26:7:26:11 | outer |
|
||||
| main.go:22:2:22:6 | definition of outer | main.go:27:7:27:11 | outer |
|
||||
| main.go:22:2:22:6 | definition of outer | main.go:28:7:28:11 | outer |
|
||||
| main.go:22:11:24:2 | struct literal | main.go:22:2:22:6 | definition of outer |
|
||||
| main.go:30:2:30:7 | definition of outerp | main.go:33:7:33:12 | outerp |
|
||||
| main.go:30:2:30:7 | definition of outerp | main.go:34:7:34:12 | outerp |
|
||||
| main.go:30:2:30:7 | definition of outerp | main.go:35:7:35:12 | outerp |
|
||||
| main.go:30:2:30:7 | definition of outerp | main.go:36:7:36:12 | outerp |
|
||||
| main.go:30:12:32:2 | &... | main.go:30:2:30:7 | definition of outerp |
|
||||
| main.go:40:2:40:6 | definition of outer | main.go:41:7:41:11 | outer |
|
||||
| main.go:40:2:40:6 | definition of outer | main.go:42:7:42:11 | outer |
|
||||
| main.go:40:2:40:6 | definition of outer | main.go:43:7:43:11 | outer |
|
||||
| main.go:40:2:40:6 | definition of outer | main.go:44:7:44:11 | outer |
|
||||
| main.go:40:11:40:40 | struct literal | main.go:40:2:40:6 | definition of outer |
|
||||
| main.go:46:2:46:7 | definition of outerp | main.go:47:7:47:12 | outerp |
|
||||
| main.go:46:2:46:7 | definition of outerp | main.go:48:7:48:12 | outerp |
|
||||
| main.go:46:2:46:7 | definition of outerp | main.go:49:7:49:12 | outerp |
|
||||
| main.go:46:2:46:7 | definition of outerp | main.go:50:7:50:12 | outerp |
|
||||
| main.go:46:12:46:42 | &... | main.go:46:2:46:7 | definition of outerp |
|
||||
| main.go:54:2:54:6 | definition of inner | main.go:55:19:55:23 | inner |
|
||||
| main.go:54:11:54:25 | struct literal | main.go:54:2:54:6 | definition of inner |
|
||||
| main.go:55:2:55:7 | definition of middle | main.go:56:17:56:22 | middle |
|
||||
| main.go:55:12:55:24 | struct literal | main.go:55:2:55:7 | definition of middle |
|
||||
| main.go:56:2:56:6 | definition of outer | main.go:57:7:57:11 | outer |
|
||||
| main.go:56:2:56:6 | definition of outer | main.go:58:7:58:11 | outer |
|
||||
| main.go:56:2:56:6 | definition of outer | main.go:59:7:59:11 | outer |
|
||||
| main.go:56:2:56:6 | definition of outer | main.go:60:7:60:11 | outer |
|
||||
| main.go:56:11:56:23 | struct literal | main.go:56:2:56:6 | definition of outer |
|
||||
| main.go:62:2:62:7 | definition of innerp | main.go:63:20:63:25 | innerp |
|
||||
| main.go:62:12:62:26 | struct literal | main.go:62:2:62:7 | definition of innerp |
|
||||
| main.go:63:2:63:8 | definition of middlep | main.go:64:18:64:24 | middlep |
|
||||
| main.go:63:13:63:26 | struct literal | main.go:63:2:63:8 | definition of middlep |
|
||||
| main.go:64:2:64:7 | definition of outerp | main.go:65:7:65:12 | outerp |
|
||||
| main.go:64:2:64:7 | definition of outerp | main.go:66:7:66:12 | outerp |
|
||||
| main.go:64:2:64:7 | definition of outerp | main.go:67:7:67:12 | outerp |
|
||||
| main.go:64:2:64:7 | definition of outerp | main.go:68:7:68:12 | outerp |
|
||||
| main.go:64:12:64:25 | struct literal | main.go:64:2:64:7 | definition of outerp |
|
||||
| main.go:72:2:72:6 | definition of inner | main.go:73:26:73:30 | inner |
|
||||
| main.go:72:11:72:25 | struct literal | main.go:72:2:72:6 | definition of inner |
|
||||
| main.go:73:2:73:7 | definition of middle | main.go:74:25:74:30 | middle |
|
||||
| main.go:73:12:73:31 | struct literal | main.go:73:2:73:7 | definition of middle |
|
||||
| main.go:74:2:74:6 | definition of outer | main.go:75:7:75:11 | outer |
|
||||
| main.go:74:2:74:6 | definition of outer | main.go:76:7:76:11 | outer |
|
||||
| main.go:74:2:74:6 | definition of outer | main.go:77:7:77:11 | outer |
|
||||
| main.go:74:2:74:6 | definition of outer | main.go:78:7:78:11 | outer |
|
||||
| main.go:74:11:74:31 | struct literal | main.go:74:2:74:6 | definition of outer |
|
||||
| main.go:80:2:80:7 | definition of innerp | main.go:81:27:81:32 | innerp |
|
||||
| main.go:80:12:80:26 | struct literal | main.go:80:2:80:7 | definition of innerp |
|
||||
| main.go:81:2:81:8 | definition of middlep | main.go:82:26:82:32 | middlep |
|
||||
| main.go:81:13:81:33 | struct literal | main.go:81:2:81:8 | definition of middlep |
|
||||
| main.go:82:2:82:7 | definition of outerp | main.go:83:7:83:12 | outerp |
|
||||
| main.go:82:2:82:7 | definition of outerp | main.go:84:7:84:12 | outerp |
|
||||
| main.go:82:2:82:7 | definition of outerp | main.go:85:7:85:12 | outerp |
|
||||
| main.go:82:2:82:7 | definition of outerp | main.go:86:7:86:12 | outerp |
|
||||
| main.go:82:12:82:33 | struct literal | main.go:82:2:82:7 | definition of outerp |
|
||||
| main.go:90:6:90:10 | definition of outer | main.go:91:2:91:6 | outer |
|
||||
| main.go:90:6:90:10 | definition of outer | main.go:92:7:92:11 | outer |
|
||||
| main.go:90:6:90:10 | definition of outer | main.go:93:7:93:11 | outer |
|
||||
| main.go:90:6:90:10 | definition of outer | main.go:94:7:94:11 | outer |
|
||||
| main.go:90:6:90:10 | definition of outer | main.go:95:7:95:11 | outer |
|
||||
| main.go:90:6:90:10 | zero value for outer | main.go:90:6:90:10 | definition of outer |
|
||||
| main.go:97:6:97:11 | definition of outerp | main.go:98:2:98:7 | outerp |
|
||||
| main.go:97:6:97:11 | definition of outerp | main.go:99:7:99:12 | outerp |
|
||||
| main.go:97:6:97:11 | definition of outerp | main.go:100:7:100:12 | outerp |
|
||||
| main.go:97:6:97:11 | definition of outerp | main.go:101:7:101:12 | outerp |
|
||||
| main.go:97:6:97:11 | definition of outerp | main.go:102:7:102:12 | outerp |
|
||||
| main.go:97:6:97:11 | zero value for outerp | main.go:97:6:97:11 | definition of outerp |
|
||||
| main.go:106:6:106:10 | definition of outer | main.go:107:2:107:6 | outer |
|
||||
| main.go:106:6:106:10 | definition of outer | main.go:108:7:108:11 | outer |
|
||||
| main.go:106:6:106:10 | definition of outer | main.go:109:7:109:11 | outer |
|
||||
| main.go:106:6:106:10 | definition of outer | main.go:110:7:110:11 | outer |
|
||||
| main.go:106:6:106:10 | definition of outer | main.go:111:7:111:11 | outer |
|
||||
| main.go:106:6:106:10 | zero value for outer | main.go:106:6:106:10 | definition of outer |
|
||||
| main.go:113:6:113:11 | definition of outerp | main.go:114:2:114:7 | outerp |
|
||||
| main.go:113:6:113:11 | definition of outerp | main.go:115:7:115:12 | outerp |
|
||||
| main.go:113:6:113:11 | definition of outerp | main.go:116:7:116:12 | outerp |
|
||||
| main.go:113:6:113:11 | definition of outerp | main.go:117:7:117:12 | outerp |
|
||||
| main.go:113:6:113:11 | definition of outerp | main.go:118:7:118:12 | outerp |
|
||||
| main.go:113:6:113:11 | zero value for outerp | main.go:113:6:113:11 | definition of outerp |
|
||||
| main.go:122:6:122:10 | definition of outer | main.go:123:2:123:6 | outer |
|
||||
| main.go:122:6:122:10 | definition of outer | main.go:124:7:124:11 | outer |
|
||||
| main.go:122:6:122:10 | definition of outer | main.go:125:7:125:11 | outer |
|
||||
| main.go:122:6:122:10 | definition of outer | main.go:126:7:126:11 | outer |
|
||||
| main.go:122:6:122:10 | definition of outer | main.go:127:7:127:11 | outer |
|
||||
| main.go:122:6:122:10 | zero value for outer | main.go:122:6:122:10 | definition of outer |
|
||||
| main.go:129:6:129:11 | definition of outerp | main.go:130:2:130:7 | outerp |
|
||||
| main.go:129:6:129:11 | definition of outerp | main.go:131:7:131:12 | outerp |
|
||||
| main.go:129:6:129:11 | definition of outerp | main.go:132:7:132:12 | outerp |
|
||||
| main.go:129:6:129:11 | definition of outerp | main.go:133:7:133:12 | outerp |
|
||||
| main.go:129:6:129:11 | definition of outerp | main.go:134:7:134:12 | outerp |
|
||||
| main.go:129:6:129:11 | zero value for outerp | main.go:129:6:129:11 | definition of outerp |
|
||||
| main.go:138:6:138:10 | definition of outer | main.go:139:2:139:6 | outer |
|
||||
| main.go:138:6:138:10 | definition of outer | main.go:140:7:140:11 | outer |
|
||||
| main.go:138:6:138:10 | definition of outer | main.go:141:7:141:11 | outer |
|
||||
| main.go:138:6:138:10 | definition of outer | main.go:142:7:142:11 | outer |
|
||||
| main.go:138:6:138:10 | definition of outer | main.go:143:7:143:11 | outer |
|
||||
| main.go:138:6:138:10 | zero value for outer | main.go:138:6:138:10 | definition of outer |
|
||||
| main.go:145:6:145:11 | definition of outerp | main.go:146:2:146:7 | outerp |
|
||||
| main.go:145:6:145:11 | definition of outerp | main.go:147:7:147:12 | outerp |
|
||||
| main.go:145:6:145:11 | definition of outerp | main.go:148:7:148:12 | outerp |
|
||||
| main.go:145:6:145:11 | definition of outerp | main.go:149:7:149:12 | outerp |
|
||||
| main.go:145:6:145:11 | definition of outerp | main.go:150:7:150:12 | outerp |
|
||||
| main.go:145:6:145:11 | zero value for outerp | main.go:145:6:145:11 | definition of outerp |
|
||||
@@ -0,0 +1,5 @@
|
||||
import go
|
||||
|
||||
from DataFlow::Node nd, DataFlow::Node succ
|
||||
where DataFlow::localFlowStep(nd, succ)
|
||||
select nd, succ
|
||||
151
ql/test/library-tests/semmle/go/dataflow/PromotedFields/main.go
Normal file
151
ql/test/library-tests/semmle/go/dataflow/PromotedFields/main.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package main
|
||||
|
||||
func source() string {
|
||||
return "hello world"
|
||||
}
|
||||
|
||||
func sink(s string) {}
|
||||
|
||||
type Inner struct {
|
||||
field string
|
||||
}
|
||||
|
||||
type Middle struct {
|
||||
Inner
|
||||
}
|
||||
|
||||
type Outer struct {
|
||||
Middle
|
||||
}
|
||||
|
||||
func testPromotedFieldNamedInitialization() {
|
||||
outer := Outer{
|
||||
Middle: Middle{Inner: Inner{source()}},
|
||||
}
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
outerp := &Outer{
|
||||
Middle: Middle{Inner: Inner{source()}},
|
||||
}
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldUnnamedInitialization() {
|
||||
outer := Outer{Middle{Inner{source()}}}
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
outerp := &Outer{Middle{Inner{source()}}}
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldUnnamedInitializationFromVariable() {
|
||||
inner := Inner{source()}
|
||||
middle := Middle{inner}
|
||||
outer := Outer{middle}
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
innerp := Inner{source()}
|
||||
middlep := Middle{innerp}
|
||||
outerp := Outer{middlep}
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldNamedInitializationFromVariable() {
|
||||
inner := Inner{source()}
|
||||
middle := Middle{Inner: inner}
|
||||
outer := Outer{Middle: middle}
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
innerp := Inner{source()}
|
||||
middlep := Middle{Inner: innerp}
|
||||
outerp := Outer{Middle: middlep}
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldDirectAssignment() {
|
||||
var outer Outer
|
||||
outer.field = source()
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
var outerp Outer
|
||||
outerp.field = source()
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldIndirectAssignment1() {
|
||||
var outer Outer
|
||||
outer.Inner.field = source()
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
var outerp Outer
|
||||
outerp.Inner.field = source()
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldIndirectAssignment2() {
|
||||
var outer Outer
|
||||
outer.Middle.field = source()
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
var outerp Outer
|
||||
outerp.Middle.field = source()
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
|
||||
func testPromotedFieldIndirectAssignment3() {
|
||||
var outer Outer
|
||||
outer.Middle.Inner.field = source()
|
||||
sink(outer.field) // $promotedfields
|
||||
sink(outer.Inner.field) // $promotedfields
|
||||
sink(outer.Middle.field) // $promotedfields
|
||||
sink(outer.Middle.Inner.field) // $promotedfields
|
||||
|
||||
var outerp Outer
|
||||
outerp.Middle.Inner.field = source()
|
||||
sink(outerp.field) // $promotedfields
|
||||
sink(outerp.Inner.field) // $promotedfields
|
||||
sink(outerp.Middle.field) // $promotedfields
|
||||
sink(outerp.Middle.Inner.field) // $promotedfields
|
||||
}
|
||||
Reference in New Issue
Block a user