Skip to content
This repository has been archived by the owner on Oct 15, 2020. It is now read-only.

Commit

Permalink
Add support for C++ style casts. (#177)
Browse files Browse the repository at this point in the history
  • Loading branch information
GlassAndOneHalf authored Jan 30, 2020
1 parent 12a6440 commit ccf6240
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 6 deletions.
3 changes: 3 additions & 0 deletions src/main/antlr4/io/shiftleft/fuzzyc2cpg/Common.g4
Original file line number Diff line number Diff line change
Expand Up @@ -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
;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<int>(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<int>(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<int>(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<int>(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);
}
}
71 changes: 65 additions & 6 deletions src/test/scala/io/shiftleft/fuzzyc2cpg/astnew/AstToCpgTests.scala
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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 {

Expand Down Expand Up @@ -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<int>(n);
| return;
|}
|""".stripMargin
) {
val call = getCall("<operator>.cast")
call.checkForSingle(NodeKeys.CODE, "const_cast<int>(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<int>(n);
| return;
|}
|""".stripMargin
) {
val call = getCall("<operator>.cast")
call.checkForSingle(NodeKeys.CODE, "static_cast<int>(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<int>(n);
| return;
|}
|""".stripMargin
) {
val call = getCall("<operator>.cast")
call.checkForSingle(NodeKeys.CODE, "dynamic_cast<int>(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<int>(n);
| return;
|}
|""".stripMargin
) {
val call = getCall("<operator>.cast")
call.checkForSingle(NodeKeys.CODE, "reinterpret_cast<int>(n)")

val callArgs = call.expandArgument
callArgs.check(2, x => x.value2(NodeKeys.CODE), "int", "n")
}
}

"AST" should {
Expand Down

0 comments on commit ccf6240

Please sign in to comment.