Skip to content

Commit 05a7a7c

Browse files
Add STATIC_BASE_TYPE property to calls (#1830)
* Add STATIC_BASE_TYPE property to calls * Generate code * Rename property to STATIC_RECEIVER * Generate code
1 parent 37a274a commit 05a7a7c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+417
-156
lines changed

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/GraphSchema.scala

Lines changed: 80 additions & 74 deletions
Large diffs are not rendered by default.

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/Properties.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -242,23 +242,31 @@ object Properties {
242242
*/
243243
val Signature = flatgraph.SinglePropertyKey[String](kind = 45, name = "SIGNATURE", default = "")
244244

245+
/** The `STATIC_RECEIVER` field is used to keep track of the type on which a static method is called for static
246+
* methods which may be inherited. This information can then be used to find the true `METHOD_FULL_NAME` of the
247+
* method being called during call linking. For example, if a class `Foo` defines a static method `foo` and a class
248+
* `Bar extends Foo`, then the `STATIC_RECEIVER` of a`Bar.foo()` call is `Bar` and the `METHOD_FULL_NAME` of the
249+
* `foo` call is rewritten to `Foo.foo:<signature>`.
250+
*/
251+
val StaticReceiver = flatgraph.OptionalPropertyKey[String](kind = 46, name = "STATIC_RECEIVER")
252+
245253
/** The static type decl of a TYPE. This property is matched against the FULL_NAME of TYPE_DECL nodes. It is required
246254
* to have exactly one TYPE_DECL for each different TYPE_DECL_FULL_NAME
247255
*/
248256
val TypeDeclFullName =
249-
flatgraph.SinglePropertyKey[String](kind = 46, name = "TYPE_DECL_FULL_NAME", default = "<empty>")
257+
flatgraph.SinglePropertyKey[String](kind = 47, name = "TYPE_DECL_FULL_NAME", default = "<empty>")
250258

251259
/** This field contains the fully-qualified static type name of the program construct represented by a node. It is the
252260
* name of an instantiated type, e.g., `java.util.List<Integer>`, rather than `java.util.List[T]`. If the type cannot
253261
* be determined, this field should be set to the empty string.
254262
*/
255-
val TypeFullName = flatgraph.SinglePropertyKey[String](kind = 47, name = "TYPE_FULL_NAME", default = "<empty>")
263+
val TypeFullName = flatgraph.SinglePropertyKey[String](kind = 48, name = "TYPE_FULL_NAME", default = "<empty>")
256264

257265
/** This property denotes a string value as used in a key-value pair. */
258-
val Value = flatgraph.SinglePropertyKey[String](kind = 48, name = "VALUE", default = "")
266+
val Value = flatgraph.SinglePropertyKey[String](kind = 49, name = "VALUE", default = "")
259267

260268
/** A version, given as a string. Used, for example, in the META_DATA node to indicate which version of the CPG spec
261269
* this CPG conforms to
262270
*/
263-
val Version = flatgraph.SinglePropertyKey[String](kind = 49, name = "VERSION", default = "<empty>")
271+
val Version = flatgraph.SinglePropertyKey[String](kind = 50, name = "VERSION", default = "<empty>")
264272
}

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/PropertyNames.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,14 @@ object PropertyNames {
247247
*/
248248
val Signature: String = "SIGNATURE"
249249

250+
/** The `STATIC_RECEIVER` field is used to keep track of the type on which a static method is called for static
251+
* methods which may be inherited. This information can then be used to find the true `METHOD_FULL_NAME` of the
252+
* method being called during call linking. For example, if a class `Foo` defines a static method `foo` and a class
253+
* `Bar extends Foo`, then the `STATIC_RECEIVER` of a`Bar.foo()` call is `Bar` and the `METHOD_FULL_NAME` of the
254+
* `foo` call is rewritten to `Foo.foo:<signature>`.
255+
*/
256+
val StaticReceiver: String = "STATIC_RECEIVER"
257+
250258
/** The static type decl of a TYPE. This property is matched against the FULL_NAME of TYPE_DECL nodes. It is required
251259
* to have exactly one TYPE_DECL for each different TYPE_DECL_FULL_NAME
252260
*/
@@ -330,6 +338,7 @@ object PropertyNames {
330338
Root,
331339
SecondaryId,
332340
Signature,
341+
StaticReceiver,
333342
TypeDeclFullName,
334343
TypeFullName,
335344
Value,

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/accessors/Accessors.scala

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,11 +316,15 @@ object Accessors {
316316
default = "": String
317317
)
318318
}
319+
final class AccessPropertyStaticReceiver(val node: nodes.StoredNode) extends AnyVal {
320+
def staticReceiver: Option[String] = flatgraph.Accessors
321+
.getNodePropertyOption[String](node.graph, nodeKind = node.nodeKind, propertyKind = 46, seq = node.seq)
322+
}
319323
final class AccessPropertyTypeDeclFullName(val node: nodes.StoredNode) extends AnyVal {
320324
def typeDeclFullName: String = flatgraph.Accessors.getNodePropertySingle(
321325
node.graph,
322326
nodeKind = node.nodeKind,
323-
propertyKind = 46,
327+
propertyKind = 47,
324328
seq = node.seq(),
325329
default = "<empty>": String
326330
)
@@ -329,7 +333,7 @@ object Accessors {
329333
def typeFullName: String = flatgraph.Accessors.getNodePropertySingle(
330334
node.graph,
331335
nodeKind = node.nodeKind,
332-
propertyKind = 47,
336+
propertyKind = 48,
333337
seq = node.seq(),
334338
default = "<empty>": String
335339
)
@@ -338,7 +342,7 @@ object Accessors {
338342
def value: String = flatgraph.Accessors.getNodePropertySingle(
339343
node.graph,
340344
nodeKind = node.nodeKind,
341-
propertyKind = 48,
345+
propertyKind = 49,
342346
seq = node.seq(),
343347
default = "": String
344348
)
@@ -347,7 +351,7 @@ object Accessors {
347351
def version: String = flatgraph.Accessors.getNodePropertySingle(
348352
node.graph,
349353
nodeKind = node.nodeKind,
350-
propertyKind = 49,
354+
propertyKind = 50,
351355
seq = node.seq(),
352356
default = "<empty>": String
353357
)
@@ -419,6 +423,10 @@ object Accessors {
419423
case stored: nodes.StoredNode => new AccessPropertyPossibleTypes(stored).possibleTypes
420424
case newNode: nodes.NewCall => newNode.possibleTypes
421425
}
426+
def staticReceiver: Option[String] = node match {
427+
case stored: nodes.StoredNode => new AccessPropertyStaticReceiver(stored).staticReceiver
428+
case newNode: nodes.NewCall => newNode.staticReceiver
429+
}
422430
def typeFullName: String = node match {
423431
case stored: nodes.StoredNode => new AccessPropertyTypeFullName(stored).typeFullName
424432
case newNode: nodes.NewCall => newNode.typeFullName
@@ -1112,6 +1120,9 @@ trait ConcreteStoredConversions extends ConcreteBaseConversions {
11121120
implicit def accessPropertySignature(
11131121
node: nodes.StoredNode & nodes.StaticType[nodes.HasSignatureEMT]
11141122
): AccessPropertySignature = new AccessPropertySignature(node)
1123+
implicit def accessPropertyStaticReceiver(
1124+
node: nodes.StoredNode & nodes.StaticType[nodes.HasStaticReceiverEMT]
1125+
): AccessPropertyStaticReceiver = new AccessPropertyStaticReceiver(node)
11151126
implicit def accessPropertyTypeDeclFullName(
11161127
node: nodes.StoredNode & nodes.StaticType[nodes.HasTypeDeclFullNameEMT]
11171128
): AccessPropertyTypeDeclFullName = new AccessPropertyTypeDeclFullName(node)

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/nodes/BaseTypes.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,11 @@ trait HasRootEMT
334334
*/
335335
trait HasSignatureEMT
336336

337+
/** Node types with this marker trait are guaranteed to have the STATIC_RECEIVER property. EMT stands for: "erased
338+
* marker trait", it exists only at compile time in order to improve type safety.
339+
*/
340+
trait HasStaticReceiverEMT
341+
337342
/** Node types with this marker trait are guaranteed to have the TYPE_DECL_FULL_NAME property. EMT stands for: "erased
338343
* marker trait", it exists only at compile time in order to improve type safety.
339344
*/

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/nodes/Call.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ trait CallEMT
1515
with HasDynamicTypeHintFullNameEMT
1616
with HasMethodFullNameEMT
1717
with HasPossibleTypesEMT
18+
with HasStaticReceiverEMT
1819
with HasTypeFullNameEMT
1920

2021
trait CallBase extends AbstractNode with CallReprBase with ExpressionBase with StaticType[CallEMT] {
@@ -38,6 +39,7 @@ trait CallBase extends AbstractNode with CallReprBase with ExpressionBase with S
3839
val tmpPossibleTypes = this.possibleTypes;
3940
if (tmpPossibleTypes.nonEmpty) res.put("POSSIBLE_TYPES", tmpPossibleTypes)
4041
if (("": String) != this.signature) res.put("SIGNATURE", this.signature)
42+
this.staticReceiver.foreach { p => res.put("STATIC_RECEIVER", p) }
4143
if (("<empty>": String) != this.typeFullName) res.put("TYPE_FULL_NAME", this.typeFullName)
4244
res
4345
}
@@ -106,6 +108,12 @@ object Call {
106108
* enforce a strict format for the signature, that is, it can be chosen by the frontend implementor to fit the source
107109
* language.
108110
*
111+
* ▸ StaticReceiver (String); Cardinality `ZeroOrOne` (optional); The `STATIC_RECEIVER` field is used to keep track of
112+
* the type on which a static method is called for static methods which may be inherited. This information can then be
113+
* used to find the true `METHOD_FULL_NAME` of the method being called during call linking. For example, if a class
114+
* `Foo` defines a static method `foo` and a class `Bar extends Foo`, then the `STATIC_RECEIVER` of a`Bar.foo()` call
115+
* is `Bar` and the `METHOD_FULL_NAME` of the `foo` call is rewritten to `Foo.foo:<signature>`.
116+
*
109117
* ▸ TypeFullName (String); Cardinality `one` (mandatory with default value `<empty>`); This field contains the
110118
* fully-qualified static type name of the program construct represented by a node. It is the name of an instantiated
111119
* type, e.g., `java.util.List<Integer>`, rather than `java.util.List[T]`. If the type cannot be determined, this field
@@ -134,7 +142,8 @@ class Call(graph_4762: flatgraph.Graph, seq_4762: Int)
134142
case 11 => "order"
135143
case 12 => "possibleTypes"
136144
case 13 => "signature"
137-
case 14 => "typeFullName"
145+
case 14 => "staticReceiver"
146+
case 15 => "typeFullName"
138147
case _ => ""
139148
}
140149

@@ -154,12 +163,13 @@ class Call(graph_4762: flatgraph.Graph, seq_4762: Int)
154163
case 11 => this.order
155164
case 12 => this.possibleTypes
156165
case 13 => this.signature
157-
case 14 => this.typeFullName
166+
case 14 => this.staticReceiver
167+
case 15 => this.typeFullName
158168
case _ => null
159169
}
160170

161171
override def productPrefix = "Call"
162-
override def productArity = 15
172+
override def productArity = 16
163173

164174
override def canEqual(that: Any): Boolean = that != null && that.isInstanceOf[Call]
165175
}

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/nodes/Finding.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ class Finding(graph_4762: flatgraph.Graph, seq_4762: Int)
4444
with FindingBase
4545
with StaticType[FindingEMT] {
4646
def evidence: IndexedSeq[StoredNode] =
47-
flatgraph.Accessors.getNodePropertyMulti[StoredNode](graph, nodeKind = nodeKind, propertyKind = 50, seq = seq)
47+
flatgraph.Accessors.getNodePropertyMulti[StoredNode](graph, nodeKind = nodeKind, propertyKind = 51, seq = seq)
4848
def keyValuePairs: IndexedSeq[KeyValuePair] =
49-
flatgraph.Accessors.getNodePropertyMulti[KeyValuePair](graph, nodeKind = nodeKind, propertyKind = 51, seq = seq)
49+
flatgraph.Accessors.getNodePropertyMulti[KeyValuePair](graph, nodeKind = nodeKind, propertyKind = 52, seq = seq)
5050

5151
override def productElementName(n: Int): String =
5252
n match {

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/nodes/NewBlock.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1594,7 +1594,7 @@ class NewBlock extends NewNode(nodeKind = 6) with BlockBase with ExpressionNew {
15941594
interface.countProperty(this, 39, offsetEnd.size)
15951595
interface.countProperty(this, 40, 1)
15961596
interface.countProperty(this, 43, possibleTypes.size)
1597-
interface.countProperty(this, 47, 1)
1597+
interface.countProperty(this, 48, 1)
15981598
}
15991599

16001600
override def copy: this.type = {

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/nodes/NewCall.scala

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,6 +1615,35 @@ object NewCall {
16151615
}
16161616
}
16171617
}
1618+
object NewNodeInserter_Call_staticReceiver extends flatgraph.NewNodePropertyInsertionHelper {
1619+
override def insertNewNodeProperties(
1620+
newNodes: mutable.ArrayBuffer[flatgraph.DNode],
1621+
dst: AnyRef,
1622+
offsets: Array[Int]
1623+
): Unit = {
1624+
if (newNodes.isEmpty) return
1625+
val dstCast = dst.asInstanceOf[Array[String]]
1626+
val seq = newNodes.head.storedRef.get.seq()
1627+
var offset = offsets(seq)
1628+
var idx = 0
1629+
while (idx < newNodes.length) {
1630+
val nn = newNodes(idx)
1631+
nn match {
1632+
case generated: NewCall =>
1633+
generated.staticReceiver match {
1634+
case Some(item) =>
1635+
dstCast(offset) = item
1636+
offset += 1
1637+
case _ =>
1638+
}
1639+
case _ =>
1640+
}
1641+
assert(seq + idx == nn.storedRef.get.seq(), "internal consistency check")
1642+
idx += 1
1643+
offsets(idx + seq) = offset
1644+
}
1645+
}
1646+
}
16181647
object NewNodeInserter_Call_typeFullName extends flatgraph.NewNodePropertyInsertionHelper {
16191648
override def insertNewNodeProperties(
16201649
newNodes: mutable.ArrayBuffer[flatgraph.DNode],
@@ -1668,6 +1697,7 @@ class NewCall extends NewNode(nodeKind = 7) with CallBase with CallReprNew with
16681697
var order: Int = -1: Int
16691698
var possibleTypes: IndexedSeq[String] = ArraySeq.empty
16701699
var signature: String = "": String
1700+
var staticReceiver: Option[String] = None
16711701
var typeFullName: String = "<empty>": String
16721702
def argumentIndex(value: Int): this.type = { this.argumentIndex = value; this }
16731703
def argumentName(value: Option[String]): this.type = { this.argumentName = value; this }
@@ -1690,6 +1720,8 @@ class NewCall extends NewNode(nodeKind = 7) with CallBase with CallReprNew with
16901720
def order(value: Int): this.type = { this.order = value; this }
16911721
def possibleTypes(value: IterableOnce[String]): this.type = { this.possibleTypes = value.iterator.to(ArraySeq); this }
16921722
def signature(value: String): this.type = { this.signature = value; this }
1723+
def staticReceiver(value: Option[String]): this.type = { this.staticReceiver = value; this }
1724+
def staticReceiver(value: String): this.type = { this.staticReceiver = Option(value); this }
16931725
def typeFullName(value: String): this.type = { this.typeFullName = value; this }
16941726
override def countAndVisitProperties(interface: flatgraph.BatchedUpdateInterface): Unit = {
16951727
interface.countProperty(this, 1, 1)
@@ -1706,7 +1738,8 @@ class NewCall extends NewNode(nodeKind = 7) with CallBase with CallReprNew with
17061738
interface.countProperty(this, 40, 1)
17071739
interface.countProperty(this, 43, possibleTypes.size)
17081740
interface.countProperty(this, 45, 1)
1709-
interface.countProperty(this, 47, 1)
1741+
interface.countProperty(this, 46, staticReceiver.size)
1742+
interface.countProperty(this, 48, 1)
17101743
}
17111744

17121745
override def copy: this.type = {
@@ -1725,6 +1758,7 @@ class NewCall extends NewNode(nodeKind = 7) with CallBase with CallReprNew with
17251758
newInstance.order = this.order
17261759
newInstance.possibleTypes = this.possibleTypes
17271760
newInstance.signature = this.signature
1761+
newInstance.staticReceiver = this.staticReceiver
17281762
newInstance.typeFullName = this.typeFullName
17291763
newInstance.asInstanceOf[this.type]
17301764
}
@@ -1745,7 +1779,8 @@ class NewCall extends NewNode(nodeKind = 7) with CallBase with CallReprNew with
17451779
case 11 => "order"
17461780
case 12 => "possibleTypes"
17471781
case 13 => "signature"
1748-
case 14 => "typeFullName"
1782+
case 14 => "staticReceiver"
1783+
case 15 => "typeFullName"
17491784
case _ => ""
17501785
}
17511786

@@ -1765,11 +1800,12 @@ class NewCall extends NewNode(nodeKind = 7) with CallBase with CallReprNew with
17651800
case 11 => this.order
17661801
case 12 => this.possibleTypes
17671802
case 13 => this.signature
1768-
case 14 => this.typeFullName
1803+
case 14 => this.staticReceiver
1804+
case 15 => this.typeFullName
17691805
case _ => null
17701806
}
17711807

17721808
override def productPrefix = "NewCall"
1773-
override def productArity = 15
1809+
override def productArity = 16
17741810
override def canEqual(that: Any): Boolean = that != null && that.isInstanceOf[NewCall]
17751811
}

domainClasses/src/main/generated/io/shiftleft/codepropertygraph/generated/nodes/NewDependency.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ class NewDependency extends NewNode(nodeKind = 12) with DependencyBase {
113113
override def countAndVisitProperties(interface: flatgraph.BatchedUpdateInterface): Unit = {
114114
interface.countProperty(this, 13, dependencyGroupId.size)
115115
interface.countProperty(this, 37, 1)
116-
interface.countProperty(this, 49, 1)
116+
interface.countProperty(this, 50, 1)
117117
}
118118

119119
override def copy: this.type = {

0 commit comments

Comments
 (0)