From 281675f2f03c025cf39d5d5c992d9706710879e4 Mon Sep 17 00:00:00 2001 From: Christian Banse Date: Tue, 2 Jan 2024 21:51:09 +0100 Subject: [PATCH] Added operators --- .../aisec/cpg/frontends/ExpressionHandler.kt | 95 ++++++++++++++---- .../cpg/frontends/JVMLanguageFrontend.kt | 14 ++- .../aisec/cpg/frontends/StatementHandler.kt | 23 +++++ .../cpg/frontends/JVMLanguageFrontendTest.kt | 3 + .../class/literals/mypackage/Literals.class | Bin 501 -> 657 bytes .../class/literals/mypackage/Literals.java | 6 ++ 6 files changed, 122 insertions(+), 19 deletions(-) diff --git a/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/ExpressionHandler.kt b/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/ExpressionHandler.kt index 754fb0377f..58698c27b0 100644 --- a/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/ExpressionHandler.kt +++ b/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/ExpressionHandler.kt @@ -30,22 +30,9 @@ import de.fraunhofer.aisec.cpg.graph.statements.expressions.* import de.fraunhofer.aisec.cpg.graph.types.FunctionType import sootup.core.jimple.basic.Local import sootup.core.jimple.basic.Value -import sootup.core.jimple.common.constant.DoubleConstant -import sootup.core.jimple.common.constant.FloatConstant -import sootup.core.jimple.common.constant.IntConstant -import sootup.core.jimple.common.constant.LongConstant -import sootup.core.jimple.common.constant.StringConstant -import sootup.core.jimple.common.expr.JAddExpr -import sootup.core.jimple.common.expr.JNewArrayExpr -import sootup.core.jimple.common.expr.JNewExpr -import sootup.core.jimple.common.expr.JSpecialInvokeExpr -import sootup.core.jimple.common.expr.JStaticInvokeExpr -import sootup.core.jimple.common.expr.JVirtualInvokeExpr -import sootup.core.jimple.common.ref.JArrayRef -import sootup.core.jimple.common.ref.JInstanceFieldRef -import sootup.core.jimple.common.ref.JParameterRef -import sootup.core.jimple.common.ref.JStaticFieldRef -import sootup.core.jimple.common.ref.JThisRef +import sootup.core.jimple.common.constant.* +import sootup.core.jimple.common.expr.* +import sootup.core.jimple.common.ref.* import sootup.core.signatures.MethodSignature import sootup.core.signatures.SootClassMemberSignature import sootup.java.core.jimple.basic.JavaLocal @@ -69,14 +56,56 @@ class ExpressionHandler(frontend: JVMLanguageFrontend) : } map.put(JSpecialInvokeExpr::class.java) { handleSpecialInvoke(it as JSpecialInvokeExpr) } map.put(JStaticInvokeExpr::class.java) { handleStaticInvoke(it as JStaticInvokeExpr) } - map.put(JAddExpr::class.java) { handleAddExpr(it as JAddExpr) } map.put(JNewExpr::class.java) { handleNewExpr(it as JNewExpr) } map.put(JNewArrayExpr::class.java) { handleNewArrayExpr(it as JNewArrayExpr) } + + // Binary operators + // - Equality checks + map.put(JEqExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JNeExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JGeExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JGtExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JLeExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JLtExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + + // - Numeric comparisons + map.put(JCmpExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JCmplExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JCmpgExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + + // - Simple arithmetics + map.put(JAddExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JDivExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JMulExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JRemExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JSubExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + + // - Binary arithmetics + map.put(JAndExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JOrExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JShlExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JShrExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JUshrExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + map.put(JXorExpr::class.java) { handleAbstractBinopExpr(it as AbstractBinopExpr) } + + // Unary operator + map.put(JNegExpr::class.java) { + handleAbstractUnopExpr( + it as AbstractUnopExpr, + postfix = false, + prefix = true, + opCode = "-" + ) + } + + // Constants + map.put(BooleanConstant::class.java) { handleBooleanConstant(it as BooleanConstant) } map.put(FloatConstant::class.java) { handleFloatConstant(it as FloatConstant) } map.put(DoubleConstant::class.java) { handleDoubleConstant(it as DoubleConstant) } map.put(IntConstant::class.java) { handleIntConstant(it as IntConstant) } map.put(LongConstant::class.java) { handleLongConstant(it as LongConstant) } map.put(StringConstant::class.java) { handleStringConstant(it as StringConstant) } + map.put(NullConstant::class.java) { handleNullConstant(it as NullConstant) } } private fun handleLocal(local: Local): Expression { @@ -200,6 +229,35 @@ class ExpressionHandler(frontend: JVMLanguageFrontend) : return new } + private fun handleAbstractBinopExpr(expr: AbstractBinopExpr): BinaryOperator { + val op = newBinaryOperator(expr.symbol.trim(), rawNode = expr) + op.lhs = handle(expr.op1) ?: newProblemExpression("missing lhs") + op.rhs = handle(expr.op2) ?: newProblemExpression("missing rhs") + op.type = frontend.typeOf(expr.type) + + return op + } + + private fun handleAbstractUnopExpr( + expr: AbstractUnopExpr, + postfix: Boolean, + prefix: Boolean, + opCode: String + ): UnaryOperator { + val op = newUnaryOperator(opCode, postfix = postfix, prefix = prefix, rawNode = expr) + op.input = handle(expr.op) ?: newProblemExpression("missing input") + op.type = frontend.typeOf(expr.type) + + return op + } + + private fun handleBooleanConstant(constant: BooleanConstant) = + newLiteral( + constant.equalEqual(BooleanConstant.getTrue()), + primitiveType("boolean"), + rawNode = constant + ) + private fun handleFloatConstant(constant: FloatConstant) = newLiteral(constant.value, primitiveType("float"), rawNode = constant) @@ -215,6 +273,9 @@ class ExpressionHandler(frontend: JVMLanguageFrontend) : private fun handleStringConstant(constant: StringConstant) = newLiteral(constant.value, primitiveType("java.lang.String"), rawNode = constant) + private fun handleNullConstant(constant: NullConstant) = + newLiteral(null, unknownType(), rawNode = constant) + private fun MethodSignature.toStaticRef(): Reference { // First, construct the name using . val ref = (this as SootClassMemberSignature<*>).toStaticRef() diff --git a/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontend.kt b/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontend.kt index e0ab6a6446..f05d27e91f 100644 --- a/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontend.kt +++ b/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontend.kt @@ -38,8 +38,8 @@ import sootup.core.model.SootMethod import sootup.core.model.SourceType import sootup.core.types.ArrayType import sootup.core.types.UnknownType -import sootup.java.bytecode.inputlocation.BytecodeClassLoadingOptions import sootup.java.bytecode.inputlocation.JavaClassPathAnalysisInputLocation +import sootup.java.bytecode.interceptors.* import sootup.java.core.JavaSootClass import sootup.java.core.views.JavaView import sootup.java.sourcecode.inputlocation.JavaSourcePathAnalysisInputLocation @@ -82,7 +82,17 @@ class JVMLanguageFrontend( JavaClassPathAnalysisInputLocation( ctx.config.topLevel!!.path, SourceType.Library, - BytecodeClassLoadingOptions.Default.bodyInterceptors + listOf( + NopEliminator(), + CastAndReturnInliner(), + UnreachableCodeEliminator(), + Aggregator(), + CopyPropagator(), + // ConditionalBranchFolder(), + EmptySwitchEliminator(), + TypeAssigner(), + LocalNameStandardizer() + ) ) JavaView(inputLocation) } else if (file.extension == "java") { diff --git a/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/StatementHandler.kt b/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/StatementHandler.kt index ab05a184f3..e20911c417 100644 --- a/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/StatementHandler.kt +++ b/cpg-language-jvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/StatementHandler.kt @@ -26,6 +26,8 @@ package de.fraunhofer.aisec.cpg.frontends import de.fraunhofer.aisec.cpg.graph.* +import de.fraunhofer.aisec.cpg.graph.statements.GotoStatement +import de.fraunhofer.aisec.cpg.graph.statements.IfStatement import de.fraunhofer.aisec.cpg.graph.statements.ReturnStatement import de.fraunhofer.aisec.cpg.graph.statements.Statement import de.fraunhofer.aisec.cpg.graph.statements.expressions.* @@ -38,6 +40,8 @@ class StatementHandler(frontend: JVMLanguageFrontend) : map.put(Body::class.java) { handleBody(it as Body) } map.put(JAssignStmt::class.java) { handleAbstractDefinitionStmt(it as JAssignStmt) } map.put(JIdentityStmt::class.java) { handleAbstractDefinitionStmt(it as JIdentityStmt) } + map.put(JIfStmt::class.java) { handleIfStmt(it as JIfStmt) } + map.put(JGotoStmt::class.java) { handleGotoStmt(it as JGotoStmt) } map.put(JInvokeStmt::class.java) { handleInvokeStmt(it as JInvokeStmt) } map.put(JReturnStmt::class.java) { handleReturnStmt(it as JReturnStmt) } map.put(JReturnVoidStmt::class.java) { handleReturnVoidStmt(it as JReturnVoidStmt) } @@ -75,6 +79,25 @@ class StatementHandler(frontend: JVMLanguageFrontend) : return assign } + private fun handleIfStmt(ifStmt: JIfStmt): IfStatement { + val stmt = newIfStatement(rawNode = ifStmt) + stmt.condition = + frontend.expressionHandler.handle(ifStmt.condition) + ?: newProblemExpression("missing condition") + + // TODO: parse statements + + return stmt + } + + private fun handleGotoStmt(gotoStmt: JGotoStmt): GotoStatement { + val stmt = newGotoStatement(rawNode = gotoStmt) + + // TODO: parse statements + + return stmt + } + private fun handleInvokeStmt(invokeStmt: JInvokeStmt) = frontend.expressionHandler.handle(invokeStmt.invokeExpr) diff --git a/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontendTest.kt b/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontendTest.kt index ad7fc6736b..a38462bff9 100644 --- a/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontendTest.kt +++ b/cpg-language-jvm/src/test/kotlin/de/fraunhofer/aisec/cpg/frontends/JVMLanguageFrontendTest.kt @@ -100,6 +100,7 @@ class JVMLanguageFrontendTest { it.registerLanguage() } assertNotNull(tu) + assertEquals(0, tu.problems.size) val pkg = tu.namespaces["mypackage"] assertNotNull(pkg) @@ -164,6 +165,7 @@ class JVMLanguageFrontendTest { it.registerLanguage() } assertNotNull(tu) + assertEquals(0, tu.problems.size) val haveFun = tu.methods["haveFunWithLiterals"] assertNotNull(haveFun) @@ -186,6 +188,7 @@ class JVMLanguageFrontendTest { it.registerLanguage() } assertNotNull(tu) + assertEquals(0, tu.problems.size) tu.methods.forEach { println(it.code) } diff --git a/cpg-language-jvm/src/test/resources/class/literals/mypackage/Literals.class b/cpg-language-jvm/src/test/resources/class/literals/mypackage/Literals.class index fb77fea1a91a59405e22da1b058f48f2d9678053..9f4e810bf19599738ea25ec558ce993806fb43de 100644 GIT binary patch delta 330 zcmYL^IZne+5QhJ;V;h_ph;Z1fKpYZ?9YiQl3KwA!qCiR&YNSViumpo5i%U>hE|9nY zw1@(Wf`*Pe&~pJg1dLt4lV*7{zrLCIltV>-`+j}_uz{se-&-9y6<4Cs7k;nN7Qrz= z9SHy6;+!DYoGo>|!cu-ZCNQaCDu-#zgh!j%Sw*)Ky=UA;&NB) z_YXBVgt32oCm5Xgy~w80P8m{4l|WFSvQNeoITA<3eF8mjLa4G&+JMZq@F%@T1_oEw zqHD5NVi+dIZ*DP6o_+___4K^_5u@N`O;|CCUM|5&DXs}4dL_G6#VG2?V;LrzD4@j` eF0#sk^uvuI4P{BzP$SCl{4Ypc;7!~VRR0A|do=I> delta 211 zcmXAhyA8rX5Jcx}?89dRHfR2S5%GzQcG*b`br%+mAO#$_WIwxz=4rrP zp#YmT{9ia7=?vJHm2C{UuX|}JREZPGXX3{2SJF0)%`S(QIM-12-5L9{>OV diff --git a/cpg-language-jvm/src/test/resources/class/literals/mypackage/Literals.java b/cpg-language-jvm/src/test/resources/class/literals/mypackage/Literals.java index c944cf6552..7172c05a4e 100644 --- a/cpg-language-jvm/src/test/resources/class/literals/mypackage/Literals.java +++ b/cpg-language-jvm/src/test/resources/class/literals/mypackage/Literals.java @@ -10,6 +10,12 @@ void haveFunWithLiterals() { int i = 2000; long l = 2000L; boolean b = false; + Literals obj; + if(Math.random() == 10) { + obj = null; + } else { + obj = this; + } Integer i2 = 1000; Long l2 = 1000L;