-
Notifications
You must be signed in to change notification settings - Fork 297
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[pysrc2cpg] Module Reference Query Layer (#3824)
This query package, `modulevariable`, adds the necessary complexity to reason and handle the changes introduced by #3750 See the README.md for additional context. One can now navigate the module members, the block references, the locals and identifiers referencing these variables, and go navigate back concisely.
- Loading branch information
1 parent
ff5e780
commit dea6ab2
Showing
11 changed files
with
290 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
semanticcpg/src/main/scala/io/shiftleft/semanticcpg/language/modulevariable/Implicits.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable | ||
|
||
import io.shiftleft.codepropertygraph.Cpg | ||
import io.shiftleft.codepropertygraph.generated.nodes.Member | ||
import io.shiftleft.semanticcpg.language.modulevariable.NodeTypeStarters | ||
import io.shiftleft.semanticcpg.language.modulevariable.nodemethods.{ | ||
ModuleVariableAsMemberMethods, | ||
ModuleVariableReferenceMethods | ||
} | ||
|
||
import scala.language.implicitConversions | ||
|
||
trait Implicits { | ||
|
||
implicit def toNodeTypeStartersModuleVariableExtension(cpg: Cpg): NodeTypeStarters = new NodeTypeStarters(cpg) | ||
|
||
implicit def toModuleVariableAsMemberExt(node: Member): ModuleVariableAsMemberMethods = | ||
new ModuleVariableAsMemberMethods(node) | ||
|
||
implicit def toModuleVariableAsMemberTrav(steps: Iterator[Member]): ModuleVariableAsMemberTraversal = | ||
new ModuleVariableAsMemberTraversal(steps) | ||
|
||
implicit def toModuleVariablesExt(node: OpNodes.ModuleVariableReference): ModuleVariableReferenceMethods = | ||
new ModuleVariableReferenceMethods(node) | ||
|
||
implicit def toModuleVariablesTrav(steps: IterableOnce[OpNodes.ModuleVariable]): ModuleVariableTraversal = | ||
new ModuleVariableTraversal(steps.iterator) | ||
|
||
implicit def toModuleReferenceTrav(steps: IterableOnce[OpNodes.ModuleVariableReference]): ModuleReferenceTraversal = | ||
new ModuleReferenceTraversal(steps.iterator) | ||
|
||
} |
28 changes: 28 additions & 0 deletions
28
...ain/scala/io/shiftleft/semanticcpg/language/modulevariable/ModuleReferenceTraversal.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable | ||
|
||
import io.shiftleft.codepropertygraph.generated.nodes.Local | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.operatorextension.OpNodes.Assignment | ||
import overflowdb.traversal.help.Doc | ||
|
||
class ModuleReferenceTraversal(traversal: Iterator[OpNodes.ModuleVariableReference]) extends AnyVal { | ||
|
||
@Doc(info = "The module variable that this references to") | ||
def moduleVariable: Iterator[OpNodes.ModuleVariable] = | ||
traversal.flatMap(_.moduleVariable) | ||
|
||
@Doc(info = "All assignments where the module reference in this traversal are the target") | ||
def definitions: Iterator[Assignment] = { | ||
val varRefs = traversal.toList | ||
val moduleVarNames = varRefs.iterator.moduleVariable.name.distinct.toSeq | ||
varRefs.iterator.inAssignment | ||
.where(_.target.isIdentifier.nameExact(moduleVarNames*)) | ||
.dedup | ||
} | ||
|
||
@Doc(info = "All local variables concerning the module variable") | ||
def referencingLocals: Iterator[Local] = { | ||
traversal.inAssignment.target.isIdentifier.refsTo.collectAll[Local] | ||
} | ||
|
||
} |
22 changes: 22 additions & 0 deletions
22
...la/io/shiftleft/semanticcpg/language/modulevariable/ModuleVariableAsMemberTraversal.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable | ||
|
||
import io.shiftleft.codepropertygraph.generated.nodes.{Call, Member} | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.modulevariable.OpNodes.ModuleVariable | ||
import overflowdb.traversal.help.Doc | ||
|
||
class ModuleVariableAsMemberTraversal(traversal: Iterator[Member]) extends AnyVal { | ||
|
||
@Doc(info = "Members representing module variables") | ||
def moduleVariables: Iterator[ModuleVariable] = { | ||
val sourceMembers = traversal.toList | ||
sourceMembers | ||
.where( | ||
_.ref.parentBlock.inAssignment.target.isIdentifier | ||
.where(_.and(_.nameExact(sourceMembers.name.toSeq*), _.method.nameExact("<module>"))) | ||
) | ||
.map(new ModuleVariable(_)) | ||
.iterator | ||
} | ||
|
||
} |
32 changes: 32 additions & 0 deletions
32
...main/scala/io/shiftleft/semanticcpg/language/modulevariable/ModuleVariableTraversal.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable | ||
|
||
import io.shiftleft.codepropertygraph.generated.nodes.{Call, Identifier} | ||
import io.shiftleft.semanticcpg.language.* | ||
import io.shiftleft.semanticcpg.language.operatorextension.OpNodes.Assignment | ||
import overflowdb.traversal.help.Doc | ||
|
||
class ModuleVariableTraversal(traversal: Iterator[OpNodes.ModuleVariable]) extends AnyVal { | ||
|
||
@Doc(info = "All module references where the module variables in this traversal are the target") | ||
def moduleVariableRefs: Iterator[OpNodes.ModuleVariableReference] = | ||
traversal.ref.parentBlock.map(new OpNodes.ModuleVariableReference(_)) | ||
|
||
@Doc(info = "All assignments where the module variables in this traversal are the target") | ||
def definitions: Iterator[Assignment] = { | ||
val sourceMembers = traversal.toList | ||
sourceMembers.iterator.moduleVariableRefs.inAssignment | ||
.where(_.target.isIdentifier.nameExact(sourceMembers.name.toSeq*)) | ||
.dedup | ||
} | ||
|
||
@Doc(info = "All identifiers related to the module variables in this traversal") | ||
def referencingIdentifiers: Iterator[Identifier] = { | ||
definitions.target.isIdentifier.refsTo._refIn.collectAll[Identifier] | ||
} | ||
|
||
@Doc(info = "Calls this module variable invokes") | ||
def invokingCalls: Iterator[Call] = { | ||
referencingIdentifiers.argumentIndexLte(1).inCall.dedup.iterator | ||
} | ||
|
||
} |
14 changes: 14 additions & 0 deletions
14
...pg/src/main/scala/io/shiftleft/semanticcpg/language/modulevariable/NodeTypeStarters.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable | ||
|
||
import io.shiftleft.codepropertygraph.Cpg | ||
import overflowdb.traversal.help.{Doc, TraversalSource} | ||
import io.shiftleft.semanticcpg.language.* | ||
|
||
@TraversalSource | ||
class NodeTypeStarters(cpg: Cpg) { | ||
|
||
@Doc(info = "All module-level variables, e.g., variables declared at the root of a file in Python or JavaScript.") | ||
def moduleVariables: Iterator[OpNodes.ModuleVariable] = | ||
cpg.member.moduleVariables | ||
|
||
} |
21 changes: 21 additions & 0 deletions
21
semanticcpg/src/main/scala/io/shiftleft/semanticcpg/language/modulevariable/OpNodes.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable | ||
|
||
import io.shiftleft.codepropertygraph.generated.nodes.{Block, Member} | ||
|
||
object OpNodes { | ||
|
||
/** Represents a module-level global variable. This kind of node behaves like both a local variable and a field access | ||
* and is common in languages such as Python/JavaScript. | ||
*/ | ||
class ModuleVariable(node: Member) extends Member(node.graph(), node.id) | ||
|
||
/** Represents a module variable access block, which represents a lowered view of operations taken on both the local | ||
* variable and member-level access. | ||
* | ||
* @see | ||
* <a href="https://github.com/joernio/joern/pull/3750/">[pysrc2cpg] Model Field-like Behaviour of Module | ||
* Variables</a> | ||
*/ | ||
class ModuleVariableReference(node: Block) extends Block(node.graph(), node.id) | ||
|
||
} |
9 changes: 9 additions & 0 deletions
9
...iccpg/src/main/scala/io/shiftleft/semanticcpg/language/modulevariable/README.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
# Module Variables | ||
|
||
This package adds the necessary complexity to reason and handle the changes introduced by: | ||
[\[pysrc2cpg\] Model Field-like Behaviour of Module Variables](https://github.com/joernio/joern/pull/3750/) | ||
|
||
There is likely a much better schema-level way of addressing this hybrid behaviour of module-level variables, but this | ||
is the least intrusive and does not require some larger amount of planning. Thus, we leave the following note: | ||
|
||
TODO: Replace with a far-reaching, but simpler solution across frontends. |
19 changes: 19 additions & 0 deletions
19
...tleft/semanticcpg/language/modulevariable/nodemethods/ModuleVariableAsMemberMethods.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable.nodemethods | ||
|
||
import io.shiftleft.codepropertygraph.generated.nodes.Member | ||
import io.shiftleft.semanticcpg.language.* | ||
import overflowdb.traversal.help.Doc | ||
|
||
class ModuleVariableAsMemberMethods(node: Member) extends AnyVal { | ||
|
||
@Doc(info = "If this member refers to a module variable") | ||
def isModuleVariable: Boolean = { | ||
Iterator(node) | ||
.where( | ||
_.ref.parentBlock.inAssignment.target.isIdentifier | ||
.where(_.and(_.nameExact(node.name), _.method.nameExact("<module>"))) | ||
) | ||
.nonEmpty | ||
} | ||
|
||
} |
13 changes: 13 additions & 0 deletions
13
...left/semanticcpg/language/modulevariable/nodemethods/ModuleVariableReferenceMethods.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package io.shiftleft.semanticcpg.language.modulevariable.nodemethods | ||
|
||
import io.shiftleft.semanticcpg.language.modulevariable.OpNodes | ||
import io.shiftleft.semanticcpg.language.* | ||
import overflowdb.traversal.help.Doc | ||
|
||
class ModuleVariableReferenceMethods(node: OpNodes.ModuleVariableReference) extends AnyVal { | ||
|
||
@Doc(info = "The module variable being referenced") | ||
def moduleVariable: Iterator[OpNodes.ModuleVariable] = | ||
node.astChildren.headOption.isCall.fieldAccess.referencedMember.map(new OpNodes.ModuleVariable(_)) | ||
|
||
} |
20 changes: 12 additions & 8 deletions
20
semanticcpg/src/main/scala/io/shiftleft/semanticcpg/language/package.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters