From 181e14522c9b8fa46916d3c5995c3b205312b459 Mon Sep 17 00:00:00 2001 From: Christian Banse Date: Tue, 23 Jul 2024 15:39:51 +0200 Subject: [PATCH] and more --- .../fraunhofer/aisec/cpg/graph/NodeBuilder.kt | 22 +- .../cpg/frontends/llvm/StatementHandler.kt | 277 +++++++++--------- 2 files changed, 164 insertions(+), 135 deletions(-) diff --git a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt index 70ed30caf6..170afc3854 100644 --- a/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt +++ b/cpg-core/src/main/kotlin/de/fraunhofer/aisec/cpg/graph/NodeBuilder.kt @@ -33,15 +33,12 @@ import de.fraunhofer.aisec.cpg.graph.NodeBuilder.log import de.fraunhofer.aisec.cpg.graph.declarations.Declaration import de.fraunhofer.aisec.cpg.graph.declarations.TranslationUnitDeclaration import de.fraunhofer.aisec.cpg.graph.scopes.Scope -import de.fraunhofer.aisec.cpg.graph.statements.expressions.* -import de.fraunhofer.aisec.cpg.graph.types.* import de.fraunhofer.aisec.cpg.helpers.getCodeOfSubregion import de.fraunhofer.aisec.cpg.passes.inference.IsImplicitProvider import de.fraunhofer.aisec.cpg.passes.inference.IsInferredProvider import de.fraunhofer.aisec.cpg.sarif.PhysicalLocation import de.fraunhofer.aisec.cpg.sarif.Region import java.net.URI -import java.util.* import kotlin.collections.ArrayDeque import org.slf4j.LoggerFactory @@ -420,6 +417,25 @@ fun T.withChildren( return this } +/** + * This function can be used to set the [Node.astParent] of this node to the current node on the + * [AstStackProvider]'s stack. This is particularly useful if the node was created outside of the + * [withChildren] lambda (for example, because it is used in multiple when-branches). + * + * Example: + * ```kotlin + * val binaryOperator = newBinaryOperator("|", rawNode = instr).withChildren { + * it.lhs = ptrDeref.withParent() + * it.rhs = value.withParent() + * } + * ``` + */ +context(AstStackProvider) +fun T.withParent(): T { + this.astParent = (this@AstStackProvider).astStack.lastOrNull() + return this +} + context(ContextProvider) fun T.declare(): T { val scopeManager = diff --git a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt index 9b12912d7f..ae577e9fb0 100644 --- a/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt +++ b/cpg-language-llvm/src/main/kotlin/de/fraunhofer/aisec/cpg/frontends/llvm/StatementHandler.kt @@ -825,148 +825,161 @@ class StatementHandler(lang: LLVMIRLanguageFrontend) : val value = frontend.getOperandValueAtIndex(instr, 1) val ty = value.type - val exchOp = newAssignExpression("=", rawNode = instr).withChildren { - it.name = Name("atomicrmw") - - val ptrDeref = newUnaryOperator("*", postfix = false, prefix = true, rawNode = instr) - ptrDeref.input = frontend.getOperandValueAtIndex(instr, 0) - - val ptrDerefExch = newUnaryOperator("*", postfix = false, prefix = true, rawNode = instr) - ptrDerefExch.input = frontend.getOperandValueAtIndex(instr, 0) - it.lhs = listOf(ptrDerefExch) - - when (operation) { - LLVMAtomicRMWBinOpXchg -> { - it.rhs = listOf(value) - } - - LLVMAtomicRMWBinOpFAdd, - LLVMAtomicRMWBinOpAdd - -> { - val binaryOperator = newBinaryOperator("+", rawNode = instr) - binaryOperator.lhs = ptrDeref - binaryOperator.rhs = value - it.rhs = listOf(binaryOperator) - } - - LLVMAtomicRMWBinOpFSub, - LLVMAtomicRMWBinOpSub - -> { - val binaryOperator = newBinaryOperator("-", rawNode = instr) - binaryOperator.lhs = ptrDeref - binaryOperator.rhs = value - it.rhs = listOf(binaryOperator) - } - - LLVMAtomicRMWBinOpAnd -> { - val binaryOperator = newBinaryOperator("&", rawNode = instr) - binaryOperator.lhs = ptrDeref - binaryOperator.rhs = value - it.rhs = listOf(binaryOperator) - } - - LLVMAtomicRMWBinOpNand -> { - val binaryOperator = newBinaryOperator("|", rawNode = instr) - binaryOperator.lhs = ptrDeref - binaryOperator.rhs = value - val unaryOperator = newUnaryOperator("~", false, true, rawNode = instr) - unaryOperator.input = binaryOperator - it.rhs = listOf(unaryOperator) - } + val exchOp = + newAssignExpression("=", rawNode = instr).withChildren { + it.name = Name("atomicrmw") - LLVMAtomicRMWBinOpOr -> { - val binaryOperator = newBinaryOperator("|", rawNode = instr) - binaryOperator.lhs = ptrDeref - binaryOperator.rhs = value - it.rhs = listOf(binaryOperator) - } + val ptrDeref = + newUnaryOperator("*", postfix = false, prefix = true, rawNode = instr) + ptrDeref.input = frontend.getOperandValueAtIndex(instr, 0) - LLVMAtomicRMWBinOpXor -> { - val binaryOperator = newBinaryOperator("^", rawNode = instr) - binaryOperator.lhs = ptrDeref - binaryOperator.rhs = value - it.rhs = listOf(binaryOperator) - } + val ptrDerefExch = + newUnaryOperator("*", postfix = false, prefix = true, rawNode = instr) + ptrDerefExch.input = frontend.getOperandValueAtIndex(instr, 0) + it.lhs = listOf(ptrDerefExch) - LLVMAtomicRMWBinOpMax, - LLVMAtomicRMWBinOpMin - -> { - val operatorCode = - if (operation == LLVMAtomicRMWBinOpMin) { - "<" - } else { - ">" - } - val condition = newBinaryOperator(operatorCode, rawNode = instr) - condition.lhs = ptrDeref - condition.rhs = value - - val ptrDerefConditional = newUnaryOperator("*", false, true, rawNode = instr) - ptrDerefConditional.input = frontend.getOperandValueAtIndex(instr, 0) - val conditional = - newConditionalExpression( - ty, - ) - .withChildren { - it.condition = condition - it.thenExpression = ptrDerefConditional - it.elseExpression = value + when (operation) { + LLVMAtomicRMWBinOpXchg -> { + it.rhs = listOf(value.withParent()) + } + LLVMAtomicRMWBinOpFAdd, + LLVMAtomicRMWBinOpAdd -> { + val binaryOperator = + newBinaryOperator("+", rawNode = instr).withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() } - it.rhs = listOf(conditional) - } - - LLVMAtomicRMWBinOpUMax, - LLVMAtomicRMWBinOpUMin - -> { - val operatorCode = - if (operation == LLVMAtomicRMWBinOpUMin) { - "<" - } else { - ">" - } - val condition = newBinaryOperator(operatorCode, rawNode = instr) - val castExprLhs = newCastExpression(rawNode = instr) - castExprLhs.castType = objectType("u${ty.name}") - castExprLhs.expression = ptrDeref - condition.lhs = castExprLhs - - val castExprRhs = newCastExpression(rawNode = instr) - castExprRhs.castType = objectType("u${ty.name}") - castExprRhs.expression = value - condition.rhs = castExprRhs - - val ptrDerefConditional = newUnaryOperator("*", false, true, rawNode = instr) - ptrDerefConditional.input = frontend.getOperandValueAtIndex(instr, 0) - val conditional = - newConditionalExpression( - ty, - ) - .withChildren { - it.condition = condition - it.thenExpression = ptrDerefConditional - it.elseExpression = value + it.rhs = listOf(binaryOperator) + } + LLVMAtomicRMWBinOpFSub, + LLVMAtomicRMWBinOpSub -> { + val binaryOperator = + newBinaryOperator("-", rawNode = instr).withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() } - it.rhs = listOf(conditional) - } - - else -> { - throw TranslationException("LLVMAtomicRMWBinOp $operation not supported") + it.rhs = listOf(binaryOperator) + } + LLVMAtomicRMWBinOpAnd -> { + val binaryOperator = + newBinaryOperator("&", rawNode = instr).withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() + } + it.rhs = listOf(binaryOperator) + } + LLVMAtomicRMWBinOpNand -> { + val unaryOperator = + newUnaryOperator("~", false, true, rawNode = instr).withChildren { + it.input = + newBinaryOperator("|", rawNode = instr).withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() + } + } + it.rhs = listOf(unaryOperator) + } + LLVMAtomicRMWBinOpOr -> { + val binaryOperator = + newBinaryOperator("|", rawNode = instr).withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() + } + it.rhs = listOf(binaryOperator) + } + LLVMAtomicRMWBinOpXor -> { + val binaryOperator = + newBinaryOperator("^", rawNode = instr).withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() + } + it.rhs = listOf(binaryOperator) + } + LLVMAtomicRMWBinOpMax, + LLVMAtomicRMWBinOpMin -> { + val operatorCode = + if (operation == LLVMAtomicRMWBinOpMin) { + "<" + } else { + ">" + } + val conditional = + newConditionalExpression( + ty, + ) + .withChildren { + it.condition = + newBinaryOperator(operatorCode, rawNode = instr) + .withChildren { + it.lhs = ptrDeref.withParent() + it.rhs = value.withParent() + } + it.thenExpression = + newUnaryOperator("*", false, true, rawNode = instr) + .withChildren { + it.input = frontend.getOperandValueAtIndex(instr, 0) + } + it.elseExpression = + frontend.getOperandValueAtIndex(instr, 1) // value + } + it.rhs = listOf(conditional) + } + LLVMAtomicRMWBinOpUMax, + LLVMAtomicRMWBinOpUMin -> { + val operatorCode = + if (operation == LLVMAtomicRMWBinOpUMin) { + "<" + } else { + ">" + } + val conditional = + newConditionalExpression( + ty, + ) + .withChildren { + it.condition = + newBinaryOperator(operatorCode, rawNode = instr) + .withChildren { + it.lhs = + newCastExpression(rawNode = instr) + .withChildren { + it.castType = objectType("u${ty.name}") + it.expression = ptrDeref.withParent() + } + it.rhs = + newCastExpression(rawNode = instr) + .withChildren { + it.castType = objectType("u${ty.name}") + it.expression = value.withParent() + } + } + it.thenExpression = + newUnaryOperator("*", false, true, rawNode = instr) + .withChildren { + it.input = frontend.getOperandValueAtIndex(instr, 0) + } + it.elseExpression = + frontend.getOperandValueAtIndex(instr, 1) // value + } + it.rhs = listOf(conditional) + } + else -> { + throw TranslationException("LLVMAtomicRMWBinOp $operation not supported") + } } } - } - // TODO: too complicated because actually exchOp must be inside the block then :( return if (lhs != "") { // set lhs = *ptr, then perform the replacement - val compoundStatement = newBlock(rawNode = instr) - - val ptrDerefAssignment = - newUnaryOperator("*", postfix = false, prefix = true, rawNode = instr) - ptrDerefAssignment.input = frontend.getOperandValueAtIndex(instr, 0) - - compoundStatement.statements = - listOf(declarationOrNot(ptrDerefAssignment, instr), exchOp) - compoundStatement + newBlock(rawNode = instr).withChildren { + it.statements = + listOf( + newUnaryOperator("*", postfix = false, prefix = true, rawNode = instr) + .withChildren { it.input = frontend.getOperandValueAtIndex(instr, 0) } + .declareIfNecessary(instr), + exchOp.withParent() + ) + } } else { // only perform the replacement exchOp