Skip to content

Commit

Permalink
Add test cases for CXX ambiguities (#682)
Browse files Browse the repository at this point in the history
* Add test case for function pointer vs type cast ambiguity
* Add test case MemberCallExpression vs CallExpression ambiguity
* Update README.md

Co-authored-by: Christian Banse <[email protected]>
  • Loading branch information
peckto and oxisto authored Jan 27, 2022
1 parent 0014dbf commit 7604861
Show file tree
Hide file tree
Showing 4 changed files with 111 additions and 0 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ The following authors have contributed to this project (in alphabetical order):
* [maximiliankaul](https://github.com/maximiliankaul)
* [obraunsdorf](https://github.com/obraunsdorf)
* [oxisto](https://github.com/oxisto)
* [peckto](https://github.com/peckto)
* [titze](https://github.com/titze)
* [vfsrfs](https://github.com/vfsrfs)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@ package de.fraunhofer.aisec.cpg.frontends.cpp
import de.fraunhofer.aisec.cpg.TestUtils
import de.fraunhofer.aisec.cpg.graph.bodyOrNull
import de.fraunhofer.aisec.cpg.graph.byNameOrNull
import de.fraunhofer.aisec.cpg.graph.declarations.FunctionDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.MethodDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.ProblemDeclaration
import de.fraunhofer.aisec.cpg.graph.declarations.RecordDeclaration
import de.fraunhofer.aisec.cpg.graph.statements.DeclarationStatement
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CallExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.CastExpression
import de.fraunhofer.aisec.cpg.graph.statements.expressions.MemberCallExpression
import java.io.File
import kotlin.test.assertContains
import kotlin.test.assertEquals
Expand Down Expand Up @@ -76,4 +80,61 @@ class CXXAmbiguitiesTest {
assertNotNull(problem)
assertContains(problem.problem, "CDT")
}

/**
* In CXX there is an ambiguity with the statement: "(A)(B);" 1) If A is a function pointer,
* this is a [CallExpression] 2) If A is a type, this is a [CastExpression]
*/
@Test
fun testFunctionCallOrTypeCast() {
val file = File("src/test/resources/function_ptr_or_type_cast.c")
val tu = TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true)
assertNotNull(tu)

val mainFunc = tu.byNameOrNull<FunctionDeclaration>("main")
assertNotNull(mainFunc)

val fooFunc = tu.byNameOrNull<FunctionDeclaration>("foo")
assertNotNull(fooFunc)

// First two Statements are CallExpressions
val s1 = mainFunc.getBodyStatementAs(1, CallExpression::class.java)
assertNotNull(s1)
assertEquals(s1.invokes.iterator().next(), fooFunc)

val s2 = mainFunc.getBodyStatementAs(2, CallExpression::class.java)
assertNotNull(s2)
assertEquals(s2.invokes.iterator().next(), fooFunc)

// Last two Statements are CastExpressions
val s3 = mainFunc.getBodyStatementAs(3, CastExpression::class.java)
assertNotNull(s3)

val s4 = mainFunc.getBodyStatementAs(4, CastExpression::class.java)
assertNotNull(s4)
}

/**
* In CXX there is an ambiguity with the statement: "(A.B)(C);" 1) If B is a method, this is a
* [MemberCallExpression] 2) if B is a function pointer, this is a [CallExpression].
*
* Function pointer as a struct member are currently not supported in the cpg. This test case
* will just ensure that there will be no crash when parsing such a statement. When adding this
* functionality in the cpg, this test case must be adapted accordingly.
*/
@Test
fun testMethodOrFunction() {
val file = File("src/test/resources/method_or_function_call.cpp")
val tu = TestUtils.analyzeAndGetFirstTU(listOf(file), file.parentFile.toPath(), true)
assertNotNull(tu)

val mainFunc = tu.byNameOrNull<FunctionDeclaration>("main")
assertNotNull(mainFunc)

val classA = tu.byNameOrNull<RecordDeclaration>("A")
assertNotNull(classA)

val structB = tu.byNameOrNull<RecordDeclaration>("B")
assertNotNull(structB)
}
}
22 changes: 22 additions & 0 deletions cpg-core/src/test/resources/function_ptr_or_type_cast.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
void foo(int i) {
}

struct S {
int a;
} typedef s_t;

typedef s_t* s_t_p;

int main() {
void (*ptr)(int) = &foo;

// this is a function call
(*ptr)(1);
(ptr)(2);

// this is a type case
(int)(3);
(s_t_p)(4);

return 0;
}
27 changes: 27 additions & 0 deletions cpg-core/src/test/resources/method_or_function_call.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
struct A {
void foo(int i) {
}
};

struct B {
void (*bar)(int);
};

void bar(int i) {
}

int main() {
A a;
B b;
b.bar = &bar;

// foo is a method
(a.foo)(1);
a.foo(2);

// bar is a function
(b.bar)(3);
(*b.bar)(3);

return 0;
}

0 comments on commit 7604861

Please sign in to comment.