-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement a throw or raise statement (#1733)
* new node for RaiseStatement + NodeBuilder code * don't add python stuff in this branch * started work on EOG and DFG * doc * raise: fluent and first test * fluent: patch @oxisto * Start work on DFG test for raise * rename raise -> throw * more renaming raise -> throw * copy & paste handleThrowOperator * Update cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/edges/flows/DataflowTest.kt Co-authored-by: KuechA <31155350+KuechA@users.noreply.github.com> * Rename `findSymbols` into `lookupSymbolByName` (#1772) * Rename `findSymbols` into `lookupSymbolByName` This PR renames `findSymbols` into `lookupSymbolByName` as a more appropriate name, because it lookups a symbol by its name. Fixes #1767 * Update cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/ScopeManager.kt Co-authored-by: KuechA <31155350+KuechA@users.noreply.github.com> * Added documentation --------- Co-authored-by: KuechA <31155350+KuechA@users.noreply.github.com> * Update dependency rollup to v4.24.0 (#1774) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * Added language trait `HasImplicitReceiver` (#1778) Added language trait `HasImplicit Receiver` This is needed in preparation for #1777 to better handle access to fields/members of a class when an implicit receiver is used. * Cleanup of `SymbolResolver` (#1777) * Fixed crash in `getCodeOfSubregion` (#1776) * Add new function `lookupUniqueTypeSymbolByName` (#1781) * Add new function `lookupUniqueTypeSymbolByName` This adds two new functions `ScopeManager.lookupUniqueTypeSymbolByName` and `Reference.doesReferToType`. This harmonizes a lot of boilerplate code in type resolver, cxx extra pass and resolve ambuigity pass, which were all trying to achieve the same thing. Fixes #1766 * Fixed issue with Go test, more robust handling of wrapped references * Addressed code review * Make sure to move `typeObservers` from old to new node when replacing nodes (#1783) * Make sure to move `typeObservers` from old to new node when replacing nodes * Added doc for typeobservers * `implicit()` only triggers code/location update now if its not empty (#1784) Otherwise, we override the code/location again. * Added `:=` as simple operator in Python (#1785) Named expressions in Python use `:=` as operator. Therefore we need to include it in the language definition. Otherwise, the `access` value of a reference will not be set correctly. * code review * code review * code review * rename cause to parentException * doc * ThrowStatement: add toString * fix tests * Merge EOG, add tests * Documentation * More doc of EOG handling --------- Co-authored-by: KuechA <31155350+KuechA@users.noreply.github.com> Co-authored-by: Christian Banse <christian.banse@aisec.fraunhofer.de> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Alexander Kuechler <alexander.kuechler@aisec.fraunhofer.de>
- Loading branch information
1 parent
e956427
commit a12951b
Showing
10 changed files
with
351 additions
and
16 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
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
93 changes: 93 additions & 0 deletions
93
cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/statements/ThrowStatement.kt
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,93 @@ | ||
/* | ||
* Copyright (c) 2024, Fraunhofer AISEC. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* $$$$$$\ $$$$$$$\ $$$$$$\ | ||
* $$ __$$\ $$ __$$\ $$ __$$\ | ||
* $$ / \__|$$ | $$ |$$ / \__| | ||
* $$ | $$$$$$$ |$$ |$$$$\ | ||
* $$ | $$ ____/ $$ |\_$$ | | ||
* $$ | $$\ $$ | $$ | $$ | | ||
* \$$$$$ |$$ | \$$$$$ | | ||
* \______/ \__| \______/ | ||
* | ||
*/ | ||
package de.fraunhofer.aisec.cpg.graph.statements | ||
|
||
import de.fraunhofer.aisec.cpg.graph.ArgumentHolder | ||
import de.fraunhofer.aisec.cpg.graph.edges.ast.astOptionalEdgeOf | ||
import de.fraunhofer.aisec.cpg.graph.edges.unwrapping | ||
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Expression | ||
import java.util.Objects | ||
import org.apache.commons.lang3.builder.ToStringBuilder | ||
import org.neo4j.ogm.annotation.Relationship | ||
|
||
/** Represents a `throw` or `raise` statement. */ | ||
class ThrowStatement : Statement(), ArgumentHolder { | ||
|
||
/** The exception object to be raised. */ | ||
@Relationship(value = "EXCEPTION") var exceptionEdge = astOptionalEdgeOf<Expression>() | ||
var exception by unwrapping(ThrowStatement::exceptionEdge) | ||
|
||
/** | ||
* Some languages (Python) can add a parent exception (or `cause`) to indicate that an exception | ||
* was raised while handling another exception. | ||
*/ | ||
@Relationship(value = "PARENT_EXCEPTION") | ||
var parentExceptionEdge = astOptionalEdgeOf<Expression>() | ||
var parentException by unwrapping(ThrowStatement::parentExceptionEdge) | ||
|
||
override fun addArgument(expression: Expression) { | ||
when { | ||
exception == null -> exception = expression | ||
parentException == null -> parentException = expression | ||
} | ||
} | ||
|
||
override fun replaceArgument(old: Expression, new: Expression): Boolean { | ||
return when { | ||
exception == old -> { | ||
exception = new | ||
true | ||
} | ||
parentException == old -> { | ||
parentException = new | ||
true | ||
} | ||
else -> false | ||
} | ||
} | ||
|
||
override fun hasArgument(expression: Expression): Boolean { | ||
return exception == expression || parentException == expression | ||
} | ||
|
||
override fun equals(other: Any?): Boolean { | ||
if (this === other) return true | ||
if (other !is ThrowStatement) return false | ||
return super.equals(other) && | ||
exception == other.exception && | ||
parentException == other.parentException | ||
} | ||
|
||
override fun hashCode() = Objects.hash(super.hashCode(), exception, parentException) | ||
|
||
override fun toString(): String { | ||
return ToStringBuilder(this, TO_STRING_STYLE) | ||
.appendSuper(super.toString()) | ||
.append("exception", exception) | ||
.append("parentException", parentException) | ||
.toString() | ||
} | ||
} |
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
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
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
101 changes: 101 additions & 0 deletions
101
cpg-core/src/test/kotlin/de/fraunhofer/aisec/cpg/graph/ThrowStatementTest.kt
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,101 @@ | ||
/* | ||
* Copyright (c) 2022, Fraunhofer AISEC. All rights reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
* | ||
* $$$$$$\ $$$$$$$\ $$$$$$\ | ||
* $$ __$$\ $$ __$$\ $$ __$$\ | ||
* $$ / \__|$$ | $$ |$$ / \__| | ||
* $$ | $$$$$$$ |$$ |$$$$\ | ||
* $$ | $$ ____/ $$ |\_$$ | | ||
* $$ | $$\ $$ | $$ | $$ | | ||
* \$$$$$ |$$ | \$$$$$ | | ||
* \______/ \__| \______/ | ||
* | ||
*/ | ||
package de.fraunhofer.aisec.cpg.graph | ||
|
||
import de.fraunhofer.aisec.cpg.GraphExamples.Companion.testFrontend | ||
import de.fraunhofer.aisec.cpg.TranslationConfiguration | ||
import de.fraunhofer.aisec.cpg.frontends.TestLanguage | ||
import de.fraunhofer.aisec.cpg.graph.builder.* | ||
import de.fraunhofer.aisec.cpg.graph.statements.ThrowStatement | ||
import de.fraunhofer.aisec.cpg.graph.statements.expressions.Block | ||
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression | ||
import de.fraunhofer.aisec.cpg.test.assertLocalName | ||
import kotlin.test.* | ||
|
||
class ThrowStatementTest { | ||
@Test | ||
fun testThrow() { | ||
val result = | ||
testFrontend( | ||
TranslationConfiguration.builder() | ||
.defaultPasses() | ||
.registerLanguage(TestLanguage(".")) | ||
.build() | ||
) | ||
.build { | ||
translationResult { | ||
translationUnit("some.file") { | ||
function("foo", t("void")) { | ||
body { | ||
`throw` {} | ||
`throw` { call("SomeError") } | ||
`throw` { | ||
call("SomeError") | ||
call("SomeError2") | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
// Let's assert that we did this correctly | ||
val main = result.functions["foo"] | ||
assertNotNull(main) | ||
val body = main.body | ||
assertIs<Block>(body) | ||
|
||
val emptyThrow = body.statements.getOrNull(0) | ||
assertIs<ThrowStatement>(emptyThrow) | ||
println(emptyThrow.toString()) // This is only here to simulate a higher test coverage | ||
assertNull(emptyThrow.exception) | ||
assertTrue(emptyThrow.prevDFG.isEmpty()) | ||
|
||
val throwWithExc = body.statements.getOrNull(1) | ||
assertIs<ThrowStatement>(throwWithExc) | ||
println(throwWithExc.toString()) // This is only here to simulate a higher test coverage | ||
val throwCall = throwWithExc.exception | ||
assertIs<CallExpression>(throwCall) | ||
assertLocalName("SomeError", throwCall) | ||
assertEquals(setOf<Node>(throwCall), throwWithExc.prevDFG.toSet()) | ||
|
||
val throwWithExcAndParent = body.statements.getOrNull(2) | ||
assertIs<ThrowStatement>(throwWithExcAndParent) | ||
println( | ||
throwWithExcAndParent.toString() | ||
) // This is only here to simulate a higher test coverage | ||
val throwCallException = throwWithExcAndParent.exception | ||
assertIs<CallExpression>(throwCallException) | ||
assertLocalName("SomeError", throwCallException) | ||
val throwCallParent = throwWithExcAndParent.parentException | ||
assertIs<CallExpression>(throwCallParent) | ||
assertLocalName("SomeError2", throwCallParent) | ||
assertEquals( | ||
setOf<Node>(throwCallException, throwCallParent), | ||
throwWithExcAndParent.prevDFG.toSet() | ||
) | ||
} | ||
} |
Oops, something went wrong.