Skip to content

Commit

Permalink
Overhaul of type propagation
Browse files Browse the repository at this point in the history
Removed almost all type listeners for now. This will break anything and we need to rebuild.
  • Loading branch information
oxisto committed Jul 31, 2023
1 parent 5a38c97 commit e2a6c51
Show file tree
Hide file tree
Showing 54 changed files with 691 additions and 1,246 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@
*/
package de.fraunhofer.aisec.cpg.console

import de.fraunhofer.aisec.cpg.graph.HasType
import de.fraunhofer.aisec.cpg.graph.Node
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.VariableDeclaration
import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.IfStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.types.HasType
import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation
import de.fraunhofer.aisec.cpg.sarif.Region
import java.io.File
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.DeclaredReferenceExpression
import de.fraunhofer.aisec.cpg.graph.types.FunctionPointerType
import de.fraunhofer.aisec.cpg.graph.types.HasType
import de.fraunhofer.aisec.cpg.graph.types.IncompleteType
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.helpers.Util
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,33 +151,23 @@ abstract class Language<T : LanguageFrontend<*, *>> : Node() {

return when (operation.operatorCode) {
"+" ->
if (operation.lhs.propagationType is StringType) {
if (operation.lhs.type is StringType) {
// string + anything => string
operation.lhs.propagationType
} else if (operation.rhs.propagationType is StringType) {
operation.lhs.type
} else if (operation.rhs.type is StringType) {
// anything + string => string
operation.rhs.propagationType
operation.rhs.type
} else {
arithmeticOpTypePropagation(
operation.lhs.propagationType,
operation.rhs.propagationType
)
arithmeticOpTypePropagation(operation.lhs.type, operation.rhs.type)
}
"-",
"*",
"/" ->
arithmeticOpTypePropagation(
operation.lhs.propagationType,
operation.rhs.propagationType
)
"/" -> arithmeticOpTypePropagation(operation.lhs.type, operation.rhs.type)
"<<",
">>" ->
if (
operation.lhs.propagationType.isPrimitive &&
operation.rhs.propagationType.isPrimitive
) {
if (operation.lhs.type.isPrimitive && operation.rhs.type.isPrimitive) {
// primitive type 1 OP primitive type 2 => primitive type 1
operation.lhs.propagationType
operation.lhs.type
} else {
unknownType()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ package de.fraunhofer.aisec.cpg.graph
import com.fasterxml.jackson.annotation.JsonIgnore
import de.fraunhofer.aisec.cpg.graph.edge.PropertyEdge
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression
import de.fraunhofer.aisec.cpg.graph.types.HasType

/** An assignment holder is a node that intentionally contains assignment edges. */
interface AssignmentHolder {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ fun <T> Literal<T>.duplicate(implicit: Boolean): Literal<T> {
duplicate.code = this.code
duplicate.location = this.location
duplicate.locals = this.locals
duplicate.possibleSubTypes = this.possibleSubTypes
// duplicate.possibleSubTypes = this.possibleSubTypes
duplicate.argumentIndex = this.argumentIndex
duplicate.annotations = this.annotations
duplicate.comment = this.comment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
package de.fraunhofer.aisec.cpg.graph

import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression
import de.fraunhofer.aisec.cpg.graph.types.HasType

/**
* Specifies that a certain node has an initializer. It is a special case of [ArgumentHolder], in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ import de.fraunhofer.aisec.cpg.graph.declarations.*
import de.fraunhofer.aisec.cpg.graph.scopes.RecordScope
import de.fraunhofer.aisec.cpg.graph.statements.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.*
import de.fraunhofer.aisec.cpg.graph.types.FunctionType
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.graph.types.UnknownType
import de.fraunhofer.aisec.cpg.passes.executePassSequential

fun LanguageFrontend<*, *>.translationResult(
Expand Down Expand Up @@ -157,6 +159,9 @@ fun LanguageFrontend<*, *>.function(
node.returnTypes = listOf(returnType)
}

// Make sure that our function has the correct type
node.type = FunctionType.computeType(node)

scopeManager.enterScope(node)
init?.let { it(node) }
scopeManager.leaveScope(node)
Expand All @@ -180,6 +185,7 @@ fun LanguageFrontend<*, *>.method(
): MethodDeclaration {
val node = newMethodDeclaration(name)
node.returnTypes = listOf(returnType)
node.type = FunctionType.computeType(node)

scopeManager.enterScope(node)
init(node)
Expand Down Expand Up @@ -331,7 +337,7 @@ fun LanguageFrontend<*, *>.call(
init: (CallExpression.() -> Unit)? = null
): CallExpression {
// Try to parse the name
val parsedName = parseName(name)
val parsedName = parseName(name, ".")
val node =
if (parsedName.parent != null) {
newMemberCallExpression(
Expand Down Expand Up @@ -440,9 +446,11 @@ fun LanguageFrontend<*, *>.memberOrRef(name: Name, type: Type = unknownType()):
if (name.parent != null) {
newMemberExpression(name.localName, memberOrRef(name.parent))
} else {
newDeclaredReferenceExpression(name.localName, objectType(name.localName))
newDeclaredReferenceExpression(name.localName)
}
node.type = type
if (type !is UnknownType) {
node.type = type
}

return node
}
Expand Down Expand Up @@ -1042,26 +1050,24 @@ fun Expression.conditional(
*/
context(LanguageFrontend<*, *>, StatementHolder)

infix fun Expression.assign(init: BinaryOperator.() -> Expression): BinaryOperator {
val node = (this@LanguageFrontend).newBinaryOperator("=")
node.lhs = this
node.rhs = init(node)
infix fun Expression.assign(init: AssignExpression.() -> Expression): AssignExpression {
val node = (this@LanguageFrontend).newAssignExpression("=")
node.lhs = listOf(this)
node.rhs = listOf(init(node))

(this@StatementHolder) += node

return node
}

/**
* Creates a new [BinaryOperator] with a `=` [BinaryOperator.operatorCode] in the Fluent Node DSL
* and invokes [StatementHolder.addStatement] of the nearest enclosing [StatementHolder].
* Creates a new [AssignExpression] with a `=` [AssignExpression.operatorCode] in the Fluent Node
* DSL and invokes [StatementHolder.addStatement] of the nearest enclosing [StatementHolder].
*/
context(LanguageFrontend<*, *>, Holder<out Node>)

infix fun Expression.assign(rhs: Expression): BinaryOperator {
val node = (this@LanguageFrontend).newBinaryOperator("=")
node.lhs = this
node.rhs = rhs
infix fun Expression.assign(rhs: Expression): AssignExpression {
val node = (this@LanguageFrontend).newAssignExpression("=", listOf(this), listOf(rhs))

if (this@Holder is StatementHolder) {
this@Holder += node
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ package de.fraunhofer.aisec.cpg.graph.declarations

import de.fraunhofer.aisec.cpg.graph.*
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.InitializerListExpression
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.graph.types.UnknownType
import java.util.*
import org.apache.commons.lang3.builder.ToStringBuilder
import org.neo4j.ogm.annotation.Relationship
Expand All @@ -38,26 +35,7 @@ import org.neo4j.ogm.annotation.Relationship
* Declaration of a field within a [RecordDeclaration]. It contains the modifiers associated with
* the field as well as an initializer [Expression] which provides an initial value for the field.
*/
class FieldDeclaration : ValueDeclaration(), HasType.TypeListener, HasInitializer {
@AST
override var initializer: Expression? = null
set(value) {
if (field != null) {
isDefinition = true
field?.unregisterTypeListener(this)
if (field is HasType.TypeListener) {
unregisterTypeListener(field as HasType.TypeListener)
}
}
field = value
if (value != null) {
value.registerTypeListener(this)
if (value is HasType.TypeListener) {
registerTypeListener(value as HasType.TypeListener)
}
}
}

class FieldDeclaration : VariableDeclaration(), HasInitializer {
/** Specifies, whether this field declaration is also a definition, i.e. has an initializer. */
private var isDefinition = false

Expand All @@ -72,53 +50,8 @@ class FieldDeclaration : ValueDeclaration(), HasType.TypeListener, HasInitialize
}
}

/** @see VariableDeclaration.implicitInitializerAllowed */
var isImplicitInitializerAllowed = false

var isArray = false
var modifiers: List<String> = mutableListOf()

override fun typeChanged(src: HasType, root: MutableList<HasType>, oldType: Type) {
if (!isTypeSystemActive) {
return
}
if (type !is UnknownType && src.propagationType == oldType) {
return
}
val previous = type
val newType =
if (src === initializer && initializer is InitializerListExpression) {
// Init list is seen as having an array type, but can be used ambiguously. It can be
// either used to initialize an array, or to initialize some objects. If it is used
// as an
// array initializer, we need to remove the array/pointer layer from the type,
// otherwise it
// can be ignored once we have a type
if (isArray) {
src.type
} else if (type !is UnknownType) {
return
} else {
src.type.dereference()
}
} else {
src.propagationType
}
setType(newType, root)
if (previous != type) {
type.typeOrigin = Type.Origin.DATAFLOW
}
}

override fun possibleSubTypesChanged(src: HasType, root: MutableList<HasType>) {
if (!isTypeSystemActive) {
return
}
val subTypes: MutableList<Type> = ArrayList(possibleSubTypes)
subTypes.addAll(src.possibleSubTypes)
setPossibleSubTypes(subTypes, root)
}

override fun toString(): String {
return ToStringBuilder(this, TO_STRING_STYLE)
.appendSuper(super.toString())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import de.fraunhofer.aisec.cpg.graph.statements.CompoundStatement
import de.fraunhofer.aisec.cpg.graph.statements.Statement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression
import de.fraunhofer.aisec.cpg.graph.types.Type
import de.fraunhofer.aisec.cpg.graph.types.isSupertypeOf
import java.util.*
import java.util.stream.Collectors
import org.apache.commons.lang3.builder.ToStringBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ package de.fraunhofer.aisec.cpg.graph.declarations

import de.fraunhofer.aisec.cpg.graph.AST
import de.fraunhofer.aisec.cpg.graph.HasDefault
import de.fraunhofer.aisec.cpg.graph.HasType.SecondaryTypeEdge
import de.fraunhofer.aisec.cpg.graph.HasLegacyType.SecondaryTypeEdge
import de.fraunhofer.aisec.cpg.graph.types.Type
import java.util.*
import org.neo4j.ogm.annotation.Relationship
Expand Down
Loading

0 comments on commit e2a6c51

Please sign in to comment.