Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,10 @@ import org.opentaint.dataflow.configuration.jvm.serialized.PositionBaseWithModif

sealed interface GoSerializedAction

sealed interface GoSerializedAssignAction : GoSerializedAction {
val kind: String

fun rawPosition(): PositionBaseWithModifiers
fun changePos(newPos: PositionBaseWithModifiers): GoSerializedAssignAction

data class Direct(
override val kind: String,
val pos: PositionBaseWithModifiers,
) : GoSerializedAssignAction {
override fun rawPosition(): PositionBaseWithModifiers = pos
override fun changePos(newPos: PositionBaseWithModifiers) = copy(pos = newPos)
}

data class AnyAccessor(
override val kind: String,
val pos: PositionBaseWithModifiers,
) : GoSerializedAssignAction {
override fun rawPosition(): PositionBaseWithModifiers = pos
override fun changePos(newPos: PositionBaseWithModifiers) = copy(pos = newPos)
}

companion object {
operator fun invoke(kind: String, pos: PositionBaseWithModifiers) = Direct(kind, pos)
}
}
data class GoSerializedAssignAction(
val kind: String,
val pos: PositionBaseWithModifiers,
) : GoSerializedAction

data class GoSerializedCleanAction(
val taintKind: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ sealed interface GoSerializedCondition {

data class ContainsMark(val tainted: String, val pos: PositionBaseWithModifiers) : GoSerializedCondition

data class ContainsMarkOnAnyAccessor(val tainted: String, val pos: PositionBaseWithModifiers) : GoSerializedCondition

data class ConstantCmp(val pos: PositionBase, val value: ConstantValue, val cmp: ConstantCmpType) : GoSerializedCondition

data class ConstantMatches(val pos: PositionBase, val pattern: String) : GoSerializedCondition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ sealed interface PositionAccessor {
override fun toString(): String = javaClass.simpleName
}

data object AnyFieldAccessor : PositionAccessor {
override fun toString(): String = javaClass.simpleName
}

data class FieldAccessor(
val className: String,
val fieldName: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,35 @@ package org.opentaint.dataflow.configuration.jvm

import org.opentaint.dataflow.configuration.CommonTaintAction
import org.opentaint.dataflow.configuration.CommonTaintAssignAction
import org.opentaint.dataflow.configuration.TaintCleanReach

sealed interface Action: CommonTaintAction

sealed interface ActionPosition {
data class Exact(val position: Position) : ActionPosition
data class AnyAccessorAfter(val position: Position): ActionPosition
}

data class CopyAllMarks(
val from: Position,
val to: Position,
val from: ActionPosition,
val to: ActionPosition,
) : Action

data class CopyMark(
val mark: TaintMark,
val from: Position,
val to: Position,
val from: ActionPosition,
val to: ActionPosition,
) : Action

data class AssignMark(
val mark: TaintMark,
val position: Position,
val position: ActionPosition,
) : Action, CommonTaintAssignAction

data class RemoveAllMarks(
val position: Position,
val position: ActionPosition,
) : Action

data class RemoveMark(
val mark: TaintMark,
val position: Position,
val reach: TaintCleanReach = TaintCleanReach.Exact,
val position: ActionPosition,
) : Action
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package org.opentaint.dataflow.configuration.jvm.serialized

import kotlinx.serialization.Serializable
import org.opentaint.dataflow.configuration.TaintCleanReach

sealed interface SerializedAction

Expand All @@ -16,7 +15,6 @@ data class SerializedTaintAssignAction(
data class SerializedTaintCleanAction(
val taintKind: String? = null,
val pos: PositionBaseWithModifiers,
val reach: TaintCleanReach = TaintCleanReach.Exact,
): SerializedAction

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,29 @@ sealed interface PositionBaseWithModifiers {
PositionBaseWithModifiers
}

data class PositionBeforeAnyField(
val position: PositionBaseWithModifiers,
val hasAnyField: Boolean,
)

fun PositionBaseWithModifiers.beforeFirstAnyField(): PositionBeforeAnyField {
return when (this) {
is PositionBaseWithModifiers.BaseOnly -> PositionBeforeAnyField(this, hasAnyField = false)
is PositionBaseWithModifiers.WithModifiers -> {
val firstAnyField = modifiers.indexOfFirst { it == PositionModifier.AnyField }
if (firstAnyField < 0) return PositionBeforeAnyField(this, hasAnyField = false)
val retained = modifiers.take(firstAnyField)

val position = if (retained.isEmpty()) {
PositionBaseWithModifiers.BaseOnly(base)
} else {
PositionBaseWithModifiers.WithModifiers(base, retained)
}
PositionBeforeAnyField(position, hasAnyField = true)
}
}
}

class PositionBaseWithModifiersSerializer :
YamlContentPolymorphicSerializer<PositionBaseWithModifiers>(PositionBaseWithModifiers::class) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,28 +42,51 @@ class TaintFactAwareConditionEvaluator(
}
}

private val anyFieldMarkEvalCache = hashMapOf<Pair<PositionAccess, TaintMarkAccessor>, MarkEvaluationResult>()

private fun evalContainsMarkOnAnyField(positionAccess: PositionAccess, mark: TaintMarkAccessor): Boolean {
val conditionBase = positionAccess.base()
val relevantFacts = basedFacts[conditionBase] ?: return false

val result = anyFieldMarkEvalCache.computeIfAbsent(positionAccess to mark) {
val evaluatedFact = containsMarkOnAnyField(positionAccess, mark, relevantFacts)

if (evaluatedFact != null) {
evaluatedFact
} else {
markAfterAnyAccessorResolver?.resolve(mark)
NoFact
}
}

return when (result) {
is NoFact -> false
is EvaluatedFact -> {
hasEvaluatedContainsMark = true
evaluatedFacts += result

true
}
}
}

private fun containsMarkOnAnyField(
positionAccess: PositionAccess,
mark: TaintMarkAccessor,
relevantFacts: List<FactReader>
): EvaluatedFact? {
val requiredPosition = positionAccess.withSuffix(listOf(mark))

for (reader in relevantFacts) {
val positionWithTaintMark = reader.containsAnyPosition(requiredPosition) ?: continue

val finalPositionWithTaintMark = positionWithTaintMark.withSuffix(listOf(FinalAccessor))
if (!reader.containsPosition(finalPositionWithTaintMark)) continue

val tmPosition = positionWithTaintMark.removeSuffix(listOf(mark))

hasEvaluatedContainsMark = true
evaluatedFacts += EvaluatedFact(reader, tmPosition, mark)

return true
return EvaluatedFact(reader, tmPosition, mark)
}

markAfterAnyAccessorResolver?.resolve(mark)

return false
return null
}

private val markEvalCache = hashMapOf<Pair<PositionAccess, TaintMarkAccessor>, MarkEvaluationResult>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ abstract class TaintUtil<C, Src, Sink, Trace>(val apManager: ApManager) {

abstract fun conditionFact(factReader: FinalFactReader): List<FinalFactReader>

open fun patchSinkConditionFactReader(factReaders: List<FinalFactReader>): List<FactReader> = factReaders

abstract fun handleReachedSink(rule: Sink, factReader: FinalFactReader?, evaluatedFacts: List<InitialFactAp>)

open fun patchSinkConditionFactReader(factReaders: List<FinalFactReader>): List<FactReader> = factReaders

fun applySinkRules(
sinkRules: List<RuleWithCondition<Sink>>,
factReader: FinalFactReader?,
Expand Down Expand Up @@ -63,6 +63,7 @@ abstract class TaintUtil<C, Src, Sink, Trace>(val apManager: ApManager) {
createFinalFact: (FinalFactAp, Trace) -> Unit,
createEdge: (InitialFactAp, FinalFactAp, Trace) -> Unit,
createNDEdge: (Set<InitialFactAp>, FinalFactAp, Trace) -> Unit,
markAfterAnyFieldResolver: FactWithMarkAfterAnyAccessorResolver? = null,
) {
if (sourceRules.isEmpty()) return

Expand All @@ -76,7 +77,7 @@ abstract class TaintUtil<C, Src, Sink, Trace>(val apManager: ApManager) {
apManager,
initialFacts,
conditionFactReaders,
markAfterAnyFieldResolver = null, // we don't expect such marks in source rules
markAfterAnyFieldResolver = markAfterAnyFieldResolver,
assumptionsManager = sourceAssumptionsManager(),
applyRule = { rule, evaluatedFacts ->
// unconditional sources handled with zero fact
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,5 +65,15 @@ fun GoCallExpr.signature(): GoFunctionSignature? {
val receiverType = effectiveReceiver?.type
val paramTypes = explicitArgs.map { it.type }
val resultType = callInfo.resultType
return GoFunctionSignature(name, receiverType, paramTypes, resultType, resolvedCallee?.pkg?.name)
val variadicArgumentIndexes = resolvedCallee
?.signature
?.takeIf { it.isVariadic && it.params.isNotEmpty() }
?.let { signature ->
val firstVariadicIndex = signature.params.lastIndex
(firstVariadicIndex until explicitArgs.size).toSet()
}
.orEmpty()
return GoFunctionSignature(
name, receiverType, paramTypes, resultType, resolvedCallee?.pkg?.name, variadicArgumentIndexes
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.opentaint.dataflow.ap.ifds.ElementAccessor
import org.opentaint.dataflow.ap.ifds.FieldAccessor
import org.opentaint.dataflow.go.GoFlowFunctionUtils.Access.RefAccess
import org.opentaint.dataflow.go.GoFlowFunctionUtils.Access.Simple
import org.opentaint.dataflow.go.rules.ActionPosition
import org.opentaint.dataflow.go.rules.Position
import org.opentaint.dataflow.go.rules.PositionAccessor
import org.opentaint.dataflow.go.rules.PositionWithAccess
Expand Down Expand Up @@ -289,24 +290,29 @@ object GoFlowFunctionUtils {
return type is GoIRBasicType && type.kind == GoIRBasicTypeKind.STRING
}

fun ActionPosition.resolvePosAccess(): PositionAccess = when (this) {
is ActionPosition.Exact -> position.resolvePosAccess()
is ActionPosition.AnyAccessorAfter -> PositionAccess.Complex(position.resolvePosAccess(), AnyAccessor)
}

fun Position.resolvePosAccess(): PositionAccess = when (this) {
is Position.Simple -> resolvePosAccess()
is PositionWithAccess -> PositionAccess.Complex(base.resolvePosAccess(), access.resolvePosAccess())
}

fun Position.Simple.resolvePosAccess(): PositionAccess.Simple {
val base = when (this) {
is Position.Argument -> AccessPathBase.Argument(index)
is Position.Result -> AccessPathBase.Return
is Position.This -> AccessPathBase.This
}
return PositionAccess.Simple(base)
fun Position.Simple.resolvePosAccess(): PositionAccess = when (this) {
is Position.Argument -> PositionAccess.Simple(AccessPathBase.Argument(index))
is Position.Result -> PositionAccess.Simple(AccessPathBase.Return)
is Position.This -> PositionAccess.Simple(AccessPathBase.This)
is Position.ClassStatic -> PositionAccess.Complex(
PositionAccess.Simple(AccessPathBase.ClassStatic),
ClassStaticAccessor(className)
)
}

fun PositionAccessor.resolvePosAccess(): Accessor = when (this) {
is PositionAccessor.ElementAccessor -> ElementAccessor
is PositionAccessor.FieldAccessor -> createFieldAccessor(className, fieldName)
is PositionAccessor.AnyAccessor -> AnyAccessor
}

fun detectGlobalReadName(inst: GoIRAssignInst): GoGlobalFieldSignature? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class GoFunctionSignature(
val paramTypes: List<GoIRType>,
val resultType: GoIRType,
val pkgName: String? = null,
val variadicArgumentIndexes: Set<Int> = emptySet(),
) {
val arity: Int get() = paramTypes.size
val hasReceiver: Boolean get() = receiverType != null
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentaint.dataflow.go.analysis

import org.opentaint.dataflow.ap.ifds.AccessPathBase
import org.opentaint.dataflow.ap.ifds.TaintMarkAccessor
import org.opentaint.dataflow.ap.ifds.access.ApManager
import org.opentaint.dataflow.ap.ifds.access.FinalFactAp
Expand All @@ -8,7 +9,7 @@ import org.opentaint.dataflow.configuration.go.serialized.GoUserDefinedRuleInfo
import org.opentaint.dataflow.go.GoCallExpr
import org.opentaint.dataflow.go.GoFlowFunctionUtils.resolvePosAccess
import org.opentaint.dataflow.go.GoFunctionSignature
import org.opentaint.dataflow.go.rules.Position
import org.opentaint.dataflow.go.rules.ActionPosition
import org.opentaint.dataflow.go.rules.RemoveMark
import org.opentaint.dataflow.go.rules.TaintRule
import org.opentaint.dataflow.go.signature
Expand All @@ -31,9 +32,14 @@ class GoCallRuleBasedSummaryRewriter(
private val callSignature: GoFunctionSignature?
get() = callExpr.signature()

private fun ActionPosition.cleanReach(): TaintCleanReach = when (this) {
is ActionPosition.Exact -> TaintCleanReach.Exact
is ActionPosition.AnyAccessorAfter -> TaintCleanReach.ExactAndAnyField
}

private data class UserRuleDefinedAction(
val rule: TaintRule,
val positions: Set<Position>,
val positions: Set<ActionPosition>,
val controlledMarks: Set<String>
)

Expand All @@ -47,7 +53,7 @@ class GoCallRuleBasedSummaryRewriter(

if (sourceRuleWithCond.condition.isFalse) continue

val positions = sourceRule.actionsAfter.mapTo(hashSetOf()) { it.rawPosition() }
val positions = sourceRule.actionsAfter.mapTo(hashSetOf()) { it.pos }
result += UserRuleDefinedAction(sourceRule, positions, ruleInfo.relevantTaintMarks)
}

Expand All @@ -72,7 +78,7 @@ class GoCallRuleBasedSummaryRewriter(
val cleanedFact = userRuleDefinedActions.applyCleanerActions(
evalAction = { f, rule, action ->
val pos = action.pos.resolvePosAccess()
cleanEvaluator.removeFinalFact(f, pos, TaintMarkAccessor(action.mark), rule, action, TaintCleanReach.Exact)
cleanEvaluator.removeFinalFact(f, pos, TaintMarkAccessor(action.mark), rule, action, action.pos.cleanReach())
},
itemRule = { it.rule },
itemActions = { action ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import org.opentaint.dataflow.configuration.CommonTaintConfigurationSource
import org.opentaint.dataflow.configuration.isTrue
import org.opentaint.dataflow.go.GoFlowFunctionUtils
import org.opentaint.dataflow.go.GoFlowFunctionUtils.resolvePosAccess
import org.opentaint.dataflow.go.rules.ActionPosition
import org.opentaint.dataflow.go.rules.GoAssignAction
import org.opentaint.dataflow.go.rules.TaintRule
import org.opentaint.dataflow.taint.PositionAccess
Expand Down Expand Up @@ -59,7 +60,7 @@ inline fun <T> applyGlobalOrFieldReadSourceRules(
}
}

fun GoAssignAction.resolvePosAccess(): PositionAccess = when (this) {
is GoAssignAction.Direct -> pos.resolvePosAccess()
is GoAssignAction.AnyAccessor -> PositionAccess.Complex(pos.resolvePosAccess(), AnyAccessor)
fun GoAssignAction.resolvePosAccess(): PositionAccess = when (val actionPos = pos) {
is ActionPosition.Exact -> actionPos.position.resolvePosAccess()
is ActionPosition.AnyAccessorAfter -> PositionAccess.Complex(actionPos.position.resolvePosAccess(), AnyAccessor)
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class GoBasicAtomEvaluator(
is Position.Argument -> callExpr.explicitArgs.getOrNull(pos.index)
is Position.Result -> returnValue
is Position.This -> callExpr.effectiveReceiver
is Position.ClassStatic -> null
}

private inline fun cmpConstant(
Expand Down
Loading
Loading