mirror of
https://github.com/github/codeql.git
synced 2026-05-02 20:25:13 +02:00
Add implicit field reads for promoted method calls
This commit is contained in:
@@ -401,6 +401,22 @@ class StructType extends @structtype, CompositeType {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a method of `embeddedParent`, which is then embedded into this struct type.
|
||||
*/
|
||||
Method getMethodOfEmbedded(Field embeddedParent, string name, int depth) {
|
||||
// embeddedParent is a field of 'this' at depth 'depth - 1'
|
||||
this.hasFieldCand(_, embeddedParent, depth - 1, true) and
|
||||
result.getName() = name and
|
||||
(
|
||||
result.getReceiverBaseType() = embeddedParent.getType()
|
||||
or
|
||||
result.getReceiverBaseType() = embeddedParent.getType().(PointerType).getBaseType()
|
||||
or
|
||||
methodhosts(result, embeddedParent.getType())
|
||||
)
|
||||
}
|
||||
|
||||
private predicate hasFieldCand(string name, Field f, int depth, boolean isEmbedded) {
|
||||
f = this.getOwnField(name, isEmbedded) and depth = 0
|
||||
or
|
||||
@@ -450,6 +466,11 @@ class StructType extends @structtype, CompositeType {
|
||||
strictcount(getFieldCand(name, depth, _)) = 1
|
||||
}
|
||||
|
||||
Method getMethodAtDepth(string name, int depth) {
|
||||
depth = min(int depthCand | hasMethodCand(name, _, depthCand)) and
|
||||
result = unique(Method m | hasMethodCand(name, m, depth))
|
||||
}
|
||||
|
||||
override predicate hasMethod(string name, SignatureType tp) {
|
||||
exists(int mindepth |
|
||||
mindepth = min(int depth | this.hasMethodCand(name, _, depth)) and
|
||||
|
||||
@@ -55,17 +55,17 @@ private predicate isCond(Expr e) {
|
||||
* 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) {
|
||||
private predicate implicitFieldSelectionForField(PromotedSelector e, int index, Field implicitField) {
|
||||
exists(StructType baseType, PromotedField child, int implicitFieldDepth |
|
||||
baseType = e.getSelectedStructType() and
|
||||
(
|
||||
e.refersTo(child)
|
||||
or
|
||||
implicitFieldSelection(e, implicitFieldDepth + 1, child)
|
||||
implicitFieldSelectionForField(e, implicitFieldDepth + 1, child)
|
||||
)
|
||||
|
|
||||
child = baseType.getFieldOfEmbedded(implicitField, _, implicitFieldDepth + 1, _) and
|
||||
exists(Field explicitField, int explicitFieldDepth |
|
||||
exists(PromotedField explicitField, int explicitFieldDepth |
|
||||
e.refersTo(explicitField) and baseType.getFieldAtDepth(_, explicitFieldDepth) = explicitField
|
||||
|
|
||||
index = explicitFieldDepth - implicitFieldDepth
|
||||
@@ -73,6 +73,22 @@ private predicate implicitFieldSelection(PromotedFieldSelector e, int index, Fie
|
||||
)
|
||||
}
|
||||
|
||||
private predicate implicitFieldSelectionForMethod(PromotedSelector e, int index, Field implicitField) {
|
||||
exists(StructType baseType, PromotedMethod method, int mDepth, int implicitFieldDepth |
|
||||
baseType = e.getSelectedStructType() and
|
||||
e.refersTo(method) and
|
||||
baseType.getMethodAtDepth(_, mDepth) = method and
|
||||
index = mDepth - implicitFieldDepth
|
||||
|
|
||||
method = baseType.getMethodOfEmbedded(implicitField, _, implicitFieldDepth + 1)
|
||||
or
|
||||
exists(PromotedField child |
|
||||
child = baseType.getFieldOfEmbedded(implicitField, _, implicitFieldDepth + 1, _) and
|
||||
implicitFieldSelectionForMethod(e, implicitFieldDepth + 1, child)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A node in the intra-procedural control-flow graph of a Go function or file.
|
||||
*
|
||||
@@ -333,8 +349,9 @@ newtype TControlFlowNode =
|
||||
* If that field has a pointer type then this control-flow node also
|
||||
* represents an implicit dereference of it.
|
||||
*/
|
||||
MkImplicitFieldSelection(PromotedFieldSelector e, int i, Field implicitField) {
|
||||
implicitFieldSelection(e, i, implicitField)
|
||||
MkImplicitFieldSelection(PromotedSelector e, int i, Field implicitField) {
|
||||
implicitFieldSelectionForField(e, i, implicitField) or
|
||||
implicitFieldSelectionForMethod(e, i, implicitField)
|
||||
} or
|
||||
/**
|
||||
* A control-flow node that represents the start of the execution of a function or file.
|
||||
|
||||
Reference in New Issue
Block a user