Skip to content

Commit

Permalink
Merge branch 'main' into kw/wikiToSpec
Browse files Browse the repository at this point in the history
  • Loading branch information
oxisto authored Nov 30, 2024
2 parents 2adf5d3 + 897955d commit be9da46
Show file tree
Hide file tree
Showing 55 changed files with 2,070 additions and 170 deletions.
2 changes: 2 additions & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,5 @@ cpg-neo4j @peckto

build.gradle.kts @oxisto
.github @oxisto

cpg-language-ini @maximiliankaul
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ The current state of languages is:
| C++ | cpg-language-cxx | [main](https://github.com/Fraunhofer-AISEC/cpg) | `maintained` |
| Python | cpg-language-python | [main](https://github.com/Fraunhofer-AISEC/cpg) | `maintained` |
| Go | cpg-language-go | [main](https://github.com/Fraunhofer-AISEC/cpg) | `maintained` |
| INI | cpg-language-ini | [main](https://github.com/Fraunhofer-AISEC/cpg) | `maintained` |
| JVM (Bytecode) | cpg-language-jvm | [main](https://github.com/Fraunhofer-AISEC/cpg) | `incubating` |
| LLVM | cpg-language-llvm | [main](https://github.com/Fraunhofer-AISEC/cpg) | `incubating` |
| TypeScript/JavaScript | cpg-language-typescript | [main](https://github.com/Fraunhofer-AISEC/cpg) | `experimental` |
Expand Down
6 changes: 6 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -143,3 +143,9 @@ val enableJVMFrontend: Boolean by extra {
enableJVMFrontend.toBoolean()
}
project.logger.lifecycle("JVM frontend is ${if (enableJVMFrontend) "enabled" else "disabled"}")

val enableINIFrontend: Boolean by extra {
val enableINIFrontend: String? by project
enableINIFrontend.toBoolean()
}
project.logger.lifecycle("INI frontend is ${if (enableINIFrontend) "enabled" else "disabled"}")
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ val enableLLVMFrontend: Boolean by rootProject.extra
val enableTypeScriptFrontend: Boolean by rootProject.extra
val enableRubyFrontend: Boolean by rootProject.extra
val enableJVMFrontend: Boolean by rootProject.extra
val enableINIFrontend: Boolean by rootProject.extra

dependencies {
if (enableJavaFrontend) {
Expand Down Expand Up @@ -46,4 +47,8 @@ dependencies {
api(project(":cpg-language-ruby"))
kover(project(":cpg-language-ruby"))
}
if (enableINIFrontend) {
api(project(":cpg-language-ini"))
kover(project(":cpg-language-ini"))
}
}
2 changes: 2 additions & 0 deletions configure_frontends.sh
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,5 @@ answerRuby=$(ask "Do you want to enable the Ruby frontend? (currently $(getPrope
setProperty "enableRubyFrontend" $answerRuby
answerJVM=$(ask "Do you want to enable the JVM frontend? (currently $(getProperty "enableJVMFrontend"))")
setProperty "enableJVMFrontend" $answerJVM
answerINI=$(ask "Do you want to enable the INI frontend? (currently $(getProperty "enableINIFrontend"))")
setProperty "enableINIFrontend" $answerINI
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ fun executionPath(from: Node, to: Node): QueryTree<Boolean> {
* requirement specified in [predicate].
*/
fun executionPath(from: Node, predicate: (Node) -> Boolean): QueryTree<Boolean> {
val evalRes = from.followNextEOGEdgesUntilHit(predicate)
val evalRes = from.followNextEOGEdgesUntilHit(predicate = predicate)
val allPaths = evalRes.fulfilled.map { QueryTree(it) }.toMutableList()
allPaths.addAll(evalRes.failed.map { QueryTree(it) })
return QueryTree(
Expand All @@ -264,7 +264,7 @@ fun executionPath(from: Node, predicate: (Node) -> Boolean): QueryTree<Boolean>
* requirement specified in [predicate].
*/
fun executionPathBackwards(to: Node, predicate: (Node) -> Boolean): QueryTree<Boolean> {
val evalRes = to.followPrevEOGEdgesUntilHit(predicate)
val evalRes = to.followPrevEOGEdgesUntilHit(predicate = predicate)
val allPaths = evalRes.fulfilled.map { QueryTree(it) }.toMutableList()
allPaths.addAll(evalRes.failed.map { QueryTree(it) })
return QueryTree(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ private constructor(
/** Enables the inference of variables, such as global variables. */
val inferVariables: Boolean,

/**
* A very EXPERIMENTAL feature. If this is enabled, we will try to infer return types of
* functions based on the context of the call it originated out of. This is disabled by default.
*/
val inferReturnTypes: Boolean,

/**
* Uses heuristics to add DFG edges for call expressions to unresolved functions (i.e.,
* functions not implemented in the given source code).
Expand All @@ -61,6 +67,7 @@ private constructor(
private var inferRecords: Boolean = true,
private var inferFunctions: Boolean = true,
private var inferVariables: Boolean = true,
private var inferReturnTypes: Boolean = false,
private var inferDfgForUnresolvedCalls: Boolean = true
) {
fun enabled(infer: Boolean) = apply { this.enabled = infer }
Expand All @@ -73,6 +80,8 @@ private constructor(

fun inferVariables(infer: Boolean) = apply { this.inferVariables = infer }

fun inferReturnTypes(infer: Boolean) = apply { this.inferReturnTypes = infer }

fun inferDfgForUnresolvedCalls(infer: Boolean) = apply {
this.inferDfgForUnresolvedCalls = infer
}
Expand All @@ -84,6 +93,7 @@ private constructor(
inferRecords,
inferFunctions,
inferVariables,
inferReturnTypes,
inferDfgForUnresolvedCalls
)
}
Expand Down
28 changes: 1 addition & 27 deletions cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,6 @@ class ScopeManager : ScopeProvider {
val currentRecord: RecordDeclaration?
get() = this.firstScopeIsInstanceOrNull<RecordScope>()?.astNode as? RecordDeclaration

val currentTypedefs: Collection<TypedefDeclaration>
get() = this.getCurrentTypedefs(currentScope)

val currentNamespace: Name?
get() {
val namedScope = this.firstScopeIsInstanceOrNull<NameScope>()
Expand Down Expand Up @@ -237,7 +234,7 @@ class ScopeManager : ScopeProvider {
is Block -> BlockScope(nodeToScope)
is WhileStatement,
is DoStatement,
is AssertStatement -> LoopScope(nodeToScope as Statement)
is AssertStatement -> LoopScope(nodeToScope)
is ForStatement,
is ForEachStatement -> LoopScope(nodeToScope as Statement)
is SwitchStatement -> SwitchScope(nodeToScope)
Expand Down Expand Up @@ -508,29 +505,6 @@ class ScopeManager : ScopeProvider {
scope?.addTypedef(typedef)
}

private fun getCurrentTypedefs(searchScope: Scope?): Collection<TypedefDeclaration> {
val typedefs = mutableMapOf<Name, TypedefDeclaration>()

val path = mutableListOf<ValueDeclarationScope>()
var current = searchScope

// We need to build a path from the current scope to the top most one
while (current != null) {
if (current is ValueDeclarationScope) {
path += current
}
current = current.parent
}

// And then follow the path in reverse. This ensures us that a local definition
// overwrites / shadows one that was there on a higher scope.
for (scope in path.reversed()) {
typedefs.putAll(scope.typedefs)
}

return typedefs.values
}

/**
* Resolves only references to Values in the current scope, static references to other visible
* records are not resolved over the ScopeManager.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,10 @@ private constructor(
matchCommentsToNodes: Boolean,
addIncludesToGraph: Boolean,
passConfigurations: Map<KClass<out Pass<*>>, PassConfiguration>,
/** A list of exclusion patterns used to filter files and directories. */
val exclusionPatternsByString: List<String>,
/** A list of exclusion patterns using regular expressions to filter files and directories. */
val exclusionPatternsByRegex: List<Regex>
) {
/** This list contains all languages which we want to translate. */
val languages: List<Language<*>>
Expand Down Expand Up @@ -257,6 +261,8 @@ private constructor(
private var useDefaultPasses = false
private var passConfigurations: MutableMap<KClass<out Pass<*>>, PassConfiguration> =
mutableMapOf()
private val exclusionPatternsByRegex = mutableListOf<Regex>()
private val exclusionPatternsByString = mutableListOf<String>()

fun symbols(symbols: Map<String, String>): Builder {
this.symbols = symbols
Expand Down Expand Up @@ -453,6 +459,32 @@ private constructor(
return this.configurePass(T::class, config)
}

/**
* Adds exclusion patterns using regular expressions for filtering files and directories.
*
* @param patterns Exclusion patterns. Example:
* ```
* exclusionPatterns(Regex(".*test(s)?"))
* ```
*/
fun exclusionPatterns(vararg patterns: Regex): Builder {
exclusionPatternsByRegex.addAll(patterns)
return this
}

/**
* Adds exclusion patterns for filtering files and directories.
*
* @param patterns Exclusion patterns. Example:
* ```
* exclusionPatterns("tests")
* ```
*/
fun exclusionPatterns(vararg patterns: String): Builder {
exclusionPatternsByString.addAll(patterns)
return this
}

/**
* Loads and registers an additional [Language] based on a fully qualified class name (FQN).
*/
Expand Down Expand Up @@ -647,7 +679,9 @@ private constructor(
compilationDatabase,
matchCommentsToNodes,
addIncludesToGraph,
passConfigurations
passConfigurations,
exclusionPatternsByString,
exclusionPatternsByRegex
)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,16 @@ private constructor(
.walkTopDown()
.onEnter { !it.name.startsWith(".") }
.filter { it.isFile && !it.name.startsWith(".") }
.filter {
ctx.config.exclusionPatternsByString.none { pattern ->
it.absolutePath.contains(pattern)
}
}
.filter {
ctx.config.exclusionPatternsByRegex.none { pattern ->
pattern.containsMatchIn(it.absolutePath)
}
}
.toList()
files
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,14 @@ interface HasAnonymousIdentifier : LanguageTrait {
*/
interface HasGlobalVariables : LanguageTrait

/**
* A language trait, that specifies that this language has global functions directly in the
* [GlobalScope], i.e., not within a namespace, but directly contained in a
* [TranslationUnitDeclaration]. For example, C++ has global functions, Java and Go do not (as every
* function is either in a class or a namespace).
*/
interface HasGlobalFunctions : LanguageTrait

/**
* A common super-class for all language traits that arise because they are an ambiguity of a
* function call, e.g., function-style casts. This means that we cannot differentiate between a
Expand Down
Loading

0 comments on commit be9da46

Please sign in to comment.