From ccf6240139888ac24a330f42612d19f855be67c2 Mon Sep 17 00:00:00 2001 From: Jacob Taylor-Hindle Date: Thu, 30 Jan 2020 14:59:17 +0100 Subject: [PATCH] Add support for C++ style casts. (#177) --- .../antlr4/io/shiftleft/fuzzyc2cpg/Common.g4 | 3 + .../functionparser/FunctionParserTest.java | 32 +++++++++ .../fuzzyc2cpg/astnew/AstToCpgTests.scala | 71 +++++++++++++++++-- 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/src/main/antlr4/io/shiftleft/fuzzyc2cpg/Common.g4 b/src/main/antlr4/io/shiftleft/fuzzyc2cpg/Common.g4 index b88a55e..e0d1648 100644 --- a/src/main/antlr4/io/shiftleft/fuzzyc2cpg/Common.g4 +++ b/src/main/antlr4/io/shiftleft/fuzzyc2cpg/Common.g4 @@ -152,7 +152,10 @@ shift_expression: additive_expression ( ('<<'|'>>') shift_expression)?; additive_expression: multiplicative_expression (('+'| '-') additive_expression)?; multiplicative_expression: cast_expression ( ('*'| '/'| '%') multiplicative_expression)?; +cpp_cast_identifier: 'const_cast' | 'static_cast' | 'dynamic_cast' | 'reinterpret_cast'; + cast_expression: ('(' cast_target ')' cast_expression) + | cpp_cast_identifier '<' cast_target '>' '(' cast_expression ')' | unary_expression ; diff --git a/src/test/java/io/shiftleft/fuzzyc2cpg/antlrparsers/functionparser/FunctionParserTest.java b/src/test/java/io/shiftleft/fuzzyc2cpg/antlrparsers/functionparser/FunctionParserTest.java index cd53c9b..2d95be2 100644 --- a/src/test/java/io/shiftleft/fuzzyc2cpg/antlrparsers/functionparser/FunctionParserTest.java +++ b/src/test/java/io/shiftleft/fuzzyc2cpg/antlrparsers/functionparser/FunctionParserTest.java @@ -99,4 +99,36 @@ public void testArrayDelete() { assertEquals("(statements (statement (expr_statement (expr (assign_expr (conditional_expression (or_expression (and_expression (inclusive_or_expression (exclusive_or_expression (bit_and_expression (equality_expression (relational_expression (shift_expression (additive_expression (multiplicative_expression (cast_expression (unary_expression (delete_expression delete [ ] (identifier n))))))))))))))))) ;)))", output); } + + @Test + public void testCPPConstCast() { + String input = "int x = const_cast(n);"; + String output = generateParserOutput(input); + assertEquals("(statements (statement (simple_decl (var_decl (type_name (base_type int)) (init_declarator_list (init_declarator (declarator (identifier x)) = (initializer (assign_expr (conditional_expression (or_expression (and_expression (inclusive_or_expression (exclusive_or_expression (bit_and_expression (equality_expression (relational_expression (shift_expression (additive_expression (multiplicative_expression (cast_expression (cpp_cast_identifier const_cast) < (cast_target (type_name (base_type int))) > ( (cast_expression (unary_expression (postfix_expression (primary_expression (identifier n))))) )))))))))))))))) ;)))))", + output); + } + + @Test + public void testCPPStaticCast() { + String input = "int x = static_cast(n);"; + String output = generateParserOutput(input); + assertEquals("(statements (statement (simple_decl (var_decl (type_name (base_type int)) (init_declarator_list (init_declarator (declarator (identifier x)) = (initializer (assign_expr (conditional_expression (or_expression (and_expression (inclusive_or_expression (exclusive_or_expression (bit_and_expression (equality_expression (relational_expression (shift_expression (additive_expression (multiplicative_expression (cast_expression (cpp_cast_identifier static_cast) < (cast_target (type_name (base_type int))) > ( (cast_expression (unary_expression (postfix_expression (primary_expression (identifier n))))) )))))))))))))))) ;)))))", + output); + } + + @Test + public void testCPPDynamicCast() { + String input = "int x = dynamic_cast(n);"; + String output = generateParserOutput(input); + assertEquals("(statements (statement (simple_decl (var_decl (type_name (base_type int)) (init_declarator_list (init_declarator (declarator (identifier x)) = (initializer (assign_expr (conditional_expression (or_expression (and_expression (inclusive_or_expression (exclusive_or_expression (bit_and_expression (equality_expression (relational_expression (shift_expression (additive_expression (multiplicative_expression (cast_expression (cpp_cast_identifier dynamic_cast) < (cast_target (type_name (base_type int))) > ( (cast_expression (unary_expression (postfix_expression (primary_expression (identifier n))))) )))))))))))))))) ;)))))", + output); + } + + @Test + public void testCPPReinterpretCast() { + String input = "int x = reinterpret_cast(n);"; + String output = generateParserOutput(input); + assertEquals("(statements (statement (simple_decl (var_decl (type_name (base_type int)) (init_declarator_list (init_declarator (declarator (identifier x)) = (initializer (assign_expr (conditional_expression (or_expression (and_expression (inclusive_or_expression (exclusive_or_expression (bit_and_expression (equality_expression (relational_expression (shift_expression (additive_expression (multiplicative_expression (cast_expression (cpp_cast_identifier reinterpret_cast) < (cast_target (type_name (base_type int))) > ( (cast_expression (unary_expression (postfix_expression (primary_expression (identifier n))))) )))))))))))))))) ;)))))", + output); + } } diff --git a/src/test/scala/io/shiftleft/fuzzyc2cpg/astnew/AstToCpgTests.scala b/src/test/scala/io/shiftleft/fuzzyc2cpg/astnew/AstToCpgTests.scala index 7500846..bd825d9 100644 --- a/src/test/scala/io/shiftleft/fuzzyc2cpg/astnew/AstToCpgTests.scala +++ b/src/test/scala/io/shiftleft/fuzzyc2cpg/astnew/AstToCpgTests.scala @@ -1,9 +1,11 @@ package io.shiftleft.fuzzyc2cpg.astnew -import java.util.prefs.NodeChangeListener - import gremlin.scala._ -import io.shiftleft.codepropertygraph.generated.{EdgeTypes, NodeKeyNames, NodeKeys, NodeTypes, Operators} +import org.antlr.v4.runtime.{CharStreams, ParserRuleContext} +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph +import org.scalatest.{Matchers, WordSpec} + +import io.shiftleft.codepropertygraph.generated.{EdgeTypes, NodeKeys, NodeTypes, Operators} import io.shiftleft.fuzzyc2cpg.ModuleLexer import io.shiftleft.fuzzyc2cpg.adapter.CpgAdapter import io.shiftleft.fuzzyc2cpg.adapter.EdgeKind.EdgeKind @@ -13,9 +15,6 @@ import io.shiftleft.fuzzyc2cpg.adapter.NodeProperty.NodeProperty import io.shiftleft.fuzzyc2cpg.ast.{AstNode, AstNodeBuilder} import io.shiftleft.fuzzyc2cpg.parser.modules.AntlrCModuleParserDriver import io.shiftleft.fuzzyc2cpg.parser.{AntlrParserDriverObserver, TokenSubStream} -import org.antlr.v4.runtime.{CharStreams, ParserRuleContext} -import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph -import org.scalatest.{Matchers, WordSpec} class AstToCpgTests extends WordSpec with Matchers { @@ -1001,6 +1000,66 @@ class AstToCpgTests extends WordSpec with Matchers { val callArgs = call.expandArgument callArgs.check(1, x => x.value2[String](NodeKeys.CODE), "n") } + + "be correct for const_cast" in new Fixture( + """ + |void foo() { + | int y = const_cast(n); + | return; + |} + |""".stripMargin + ) { + val call = getCall(".cast") + call.checkForSingle(NodeKeys.CODE, "const_cast(n)") + + val callArgs = call.expandArgument + callArgs.check(2, x => x.value2(NodeKeys.CODE), "int", "n") + } + + "be correct for static_cast" in new Fixture( + """ + |void foo() { + | int y = static_cast(n); + | return; + |} + |""".stripMargin + ) { + val call = getCall(".cast") + call.checkForSingle(NodeKeys.CODE, "static_cast(n)") + + val callArgs = call.expandArgument + callArgs.check(2, x => x.value2(NodeKeys.CODE), "int", "n") + } + + "be correct for dynamic_cast" in new Fixture( + """ + |void foo() { + | int y = dynamic_cast(n); + | return; + |} + |""".stripMargin + ) { + val call = getCall(".cast") + call.checkForSingle(NodeKeys.CODE, "dynamic_cast(n)") + + val callArgs = call.expandArgument + callArgs.check(2, x => x.value2(NodeKeys.CODE), "int", "n") + } + + "be correct for reinterpret_cast" in new Fixture( + """ + |void foo() { + | int y = reinterpret_cast(n); + | return; + |} + |""".stripMargin + ) { + val call = getCall(".cast") + call.checkForSingle(NodeKeys.CODE, "reinterpret_cast(n)") + + val callArgs = call.expandArgument + callArgs.check(2, x => x.value2(NodeKeys.CODE), "int", "n") + } } "AST" should {