Skip to content
Merged
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 @@ -19,6 +19,7 @@ import org.opentaint.dataflow.ap.ifds.access.InitialFactAp
import org.opentaint.dataflow.ap.ifds.analysis.AnalysisManager
import org.opentaint.dataflow.ap.ifds.analysis.MethodAnalysisContext
import org.opentaint.dataflow.ap.ifds.analysis.MethodCallFactMapper
import org.opentaint.dataflow.ap.ifds.analysis.MethodCallResolver.MethodCallResolutionResult
import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPrecondition
import org.opentaint.dataflow.ap.ifds.trace.MethodCallPrecondition.CallPreconditionFact
import org.opentaint.dataflow.ap.ifds.trace.MethodSequentPrecondition.SequentPrecondition
Expand All @@ -39,6 +40,7 @@ import org.opentaint.dataflow.configuration.CommonTaintAssignAction
import org.opentaint.dataflow.configuration.CommonTaintConfigurationItem
import org.opentaint.dataflow.configuration.CommonTaintConfigurationSource
import org.opentaint.dataflow.graph.MethodInstGraph
import org.opentaint.dataflow.util.Cancellation
import org.opentaint.dataflow.util.CompactIntSet
import org.opentaint.dataflow.util.ConcurrentReadSafeObject2IntMap
import org.opentaint.dataflow.util.ConcurrentReadSafeObject2IntMap.NO_VALUE
Expand All @@ -56,9 +58,6 @@ import org.opentaint.ir.api.common.cfg.CommonValue
import java.util.BitSet
import java.util.LinkedList
import java.util.Objects
import org.opentaint.dataflow.ap.ifds.analysis.MethodCallResolver.MethodCallResolutionResult
import org.opentaint.dataflow.util.Cancellation
import kotlin.collections.plusAssign

class MethodTraceResolver(
private val runner: AnalysisRunner,
Expand Down Expand Up @@ -1025,12 +1024,32 @@ class MethodTraceResolver(

val mergedRules = mergeCallRules(rules)

val mergedCallSummaries = mergeCallSummaries(summary, unresolvedSkips, resolveMethodCallees())
?: return listOf(PartialCallEdgeCombination(unchanged, primary = null, mergedRules))
if (summary.isEmpty()) {
if (unresolvedSkips.isEmpty()) {
return listOf(PartialCallEdgeCombination(unchanged, primary = null, mergedRules))
}

return mergedCallSummaries.map {
PartialCallEdgeCombination(unchanged, it, mergedRules)
val skippedEdges = unresolvedSkips.mapTo(hashSetOf()) { it.currentEdge }
val primary = MergedPrimaryUnresolvedCallSkip(UnresolvedCallSkip(skippedEdges, skippedEdges))
return listOf(PartialCallEdgeCombination(unchanged, primary, mergedRules))
}

if (unresolvedSkips.isNotEmpty()) {
// note: we have a summary (i.e. call resolved) and an unresolved call
return emptyList()
}

val callees = resolveMethodCallees()

val result = mutableListOf<PartialCallEdgeCombination>()
callees.forEach { callee ->
methodEntryPoints(callee).forEach {
val primary = MergedPrimaryCall2StartAction(it, summary)
result += PartialCallEdgeCombination(unchanged, primary, mergedRules)
}
}

return result
}

private fun mergeCallRules(callRules: HashSet<PartiallyResolvedCallAction.CallRule>): Set<MergedRuleAction> {
Expand Down Expand Up @@ -1070,25 +1089,6 @@ class MethodTraceResolver(
return result
}

private fun mergeCallSummaries(
callSummaries: Set<PartiallyResolvedCallAction.Call2Start>,
unresolvedCallSkips: Set<PartiallyResolvedCallAction.UnresolvedCallSkip>,
callees: List<MethodWithContext>,
): Set<PartiallyResolvedMergedPrimaryCallAction>? = buildSet {
if (callSummaries.isNotEmpty()) {
callees.forEach { callee ->
methodEntryPoints(callee).forEach {
this += MergedPrimaryCall2StartAction(it, callSummaries)
}
}
}

if (unresolvedCallSkips.isNotEmpty()) {
val skippedEdges = unresolvedCallSkips.mapTo(hashSetOf()) { it.currentEdge }
this += MergedPrimaryUnresolvedCallSkip(UnresolvedCallSkip(skippedEdges, skippedEdges))
}
}.ifEmpty { null }

private sealed interface PartiallyResolvedCallAction {
data class CallRule(
val currentEdge: TraceEdge,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package example;

import base.RuleSample;
import base.RuleSet;

@RuleSet("example/RuleWithConcretePlaceholder.yaml")
public abstract class RuleWithConcretePlaceholder implements RuleSample {
public static String source() {
return "tainted";
}

static class Engine {
public void foo(String a, String b, Context data, String d) {

}
}

static class Context {
void put(String a, String data) {
}
}

static class PositiveFoo extends RuleWithConcretePlaceholder {
@Override
public void entrypoint() {
Context context = new Context();
Engine engine = new Engine();

String data = source();
context.put("data", data);
engine.foo("a", "b", context, "d");
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
rules:
- id: example-Rule
languages:
- java
severity: ERROR
message: match example/Rule
mode: taint
pattern-sources:
- patterns:
- pattern: $DATA = source();
focus-metavariable: $DATA
pattern-sinks:
- patterns:
- pattern: $CTX.put($_, $UNTRUSTED)
- pattern-either:
- pattern-inside: |
...
(example.RuleWithConcretePlaceholder.Engine $E).foo($_, $_, $CTX, ...);
- focus-metavariable: $UNTRUSTED
3 changes: 2 additions & 1 deletion core/opentaint-java-querylang/src/main/antlr/JavaLexer.g4
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN);

IDENTIFIER: LetterNoDollar LetterOrDigit*;

METAVAR: [$] MetavarLetter+;
METAVAR: [$] MetavarFirstLetter MetavarLetter*;

ANONYMOUS_METAVAR: [$] '_';

Expand Down Expand Up @@ -252,4 +252,5 @@ fragment LetterNoDollar:
| [\uD800-\uDBFF] [\uDC00-\uDFFF] // covers UTF-16 surrogate pairs encodings for U+10000 to U+10FFFF
;

fragment MetavarFirstLetter: [A-Z] | [0-9];
fragment MetavarLetter: [A-Z_] | [0-9];
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ sealed interface SemgrepJavaPattern {
val children: List<SemgrepJavaPattern>
}

data object AnonymousMetavar : SemgrepJavaPattern {
override val children: List<SemgrepJavaPattern> = emptyList()
}

data class Metavar(val name: String) : SemgrepJavaPattern {
override val children: List<SemgrepJavaPattern> = emptyList()
}
Expand Down Expand Up @@ -186,6 +190,7 @@ sealed interface Name

data class ConcreteName(val name: String) : Name
data class MetavarName(val metavarName: String) : Name
data object AnonymousName: Name

sealed interface TypeName {
data class SimpleTypeName(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,7 @@ class SemgrepJavaPatternMatcher(
}
pattern
}
is AnonymousName -> TODO()
}
if (acc.isEmpty()) cur else "$acc\\.$cur"
}
Expand Down Expand Up @@ -801,5 +802,7 @@ class SemgrepJavaPatternMatcher(
)
)
}

AnonymousName -> TODO()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class SemgrepJavaPatternParser {

private fun IdentifierContext.parseName(): Name = withRule {
tryRule(IdentifierContext::METAVAR) { return MetavarName(it.text) }
tryRule(IdentifierContext::ANONYMOUS_METAVAR) { this@parseName.todo() }
tryRule(IdentifierContext::ANONYMOUS_METAVAR) { return AnonymousName }
return ConcreteName(text)
}

Expand Down Expand Up @@ -644,6 +644,7 @@ private class SemgrepJavaPatternParserVisitor : JavaParserBaseVisitor<SemgrepJav
return when (name) {
is ConcreteName -> Identifier(name.name)
is MetavarName -> Metavar(name.metavarName)
is AnonymousName -> AnonymousMetavar
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentaint.semgrep.pattern.conversion

import org.opentaint.semgrep.pattern.AnonymousName
import org.opentaint.semgrep.pattern.ConcreteName
import org.opentaint.semgrep.pattern.MetavarName
import org.opentaint.semgrep.pattern.MethodInvocation
Expand Down Expand Up @@ -38,7 +39,8 @@ private fun flatStringConcat(pattern: SemgrepJavaPattern): List<SemgrepJavaPatte
}
}

is MetavarName -> {}
is MetavarName,
is AnonymousName -> {}
}

return listOf(pattern)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentaint.semgrep.pattern.conversion

import org.opentaint.semgrep.pattern.AnonymousName
import org.opentaint.semgrep.pattern.ConcreteName
import org.opentaint.semgrep.pattern.Ellipsis
import org.opentaint.semgrep.pattern.Metavar
Expand All @@ -19,7 +20,8 @@ fun rewriteCatchStatement(rule: NormalizedSemgrepRule<SemgrepJavaPattern>): List
handlerBlock: SemgrepJavaPattern
): List<SemgrepJavaPattern> {
val exceptionMetaVarName = when (exceptionVariable) {
is ConcreteName -> return super.createCatchStatement(exceptionTypes, exceptionVariable, handlerBlock)
is ConcreteName,
is AnonymousName -> return super.createCatchStatement(exceptionTypes, exceptionVariable, handlerBlock)
is MetavarName -> exceptionVariable.metavarName
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.opentaint.semgrep.pattern.conversion

import org.opentaint.semgrep.pattern.AddExpr
import org.opentaint.semgrep.pattern.Annotation
import org.opentaint.semgrep.pattern.AnonymousMetavar
import org.opentaint.semgrep.pattern.ArrayAccess
import org.opentaint.semgrep.pattern.BoolConstant
import org.opentaint.semgrep.pattern.CatchStatement
Expand Down Expand Up @@ -75,6 +76,7 @@ interface PatternRewriter {
is CatchStatement -> rewriteCatchStatement()
is DeepExpr -> rewriteDeepExpr()
is EllipsisMetavar -> rewriteEllipsisMetavar()
is AnonymousMetavar -> rewriteAnonymousMetavar()
}

fun AddExpr.rewriteAddExpr(): List<SemgrepJavaPattern> {
Expand Down Expand Up @@ -254,6 +256,7 @@ interface PatternRewriter {
fun Identifier.rewriteIdentifier(): List<SemgrepJavaPattern> = listOf(this)
fun Metavar.rewriteMetavar(): List<SemgrepJavaPattern> = listOf(this)
fun EllipsisMetavar.rewriteEllipsisMetavar(): List<SemgrepJavaPattern> = listOf(this)
fun AnonymousMetavar.rewriteAnonymousMetavar(): List<SemgrepJavaPattern> = listOf(this)
fun rewriteEllipsis(): List<SemgrepJavaPattern> = listOf(Ellipsis)
fun rewriteStringEllipsis(): List<SemgrepJavaPattern> = listOf(StringEllipsis)
fun rewriteThisExpr(): List<SemgrepJavaPattern> = listOf(ThisExpr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package org.opentaint.semgrep.pattern.conversion

import org.opentaint.semgrep.pattern.AddExpr
import org.opentaint.semgrep.pattern.Annotation
import org.opentaint.semgrep.pattern.AnonymousMetavar
import org.opentaint.semgrep.pattern.AnonymousName
import org.opentaint.semgrep.pattern.ArrayAccess
import org.opentaint.semgrep.pattern.BoolConstant
import org.opentaint.semgrep.pattern.CatchStatement
Expand Down Expand Up @@ -116,6 +118,7 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
is CatchStatement,
is DeepExpr,
is EllipsisMetavar,
is AnonymousMetavar,
is IntLiteral -> {
val messagePrefix = if (isRootPattern) "Root pattern is: " else ""
transformationFailed("$messagePrefix${pattern::class.java.simpleName}")
Expand All @@ -131,6 +134,7 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
is StringLiteral -> when (val value = pattern.content) {
is ConcreteName -> SpecificStringValue(value.name)
is MetavarName -> StringValueMetaVar(MetavarAtom.create(value.metavarName))
is AnonymousName -> ParamCondition.AnyStringLiteral
}

is StringEllipsis -> {
Expand All @@ -141,6 +145,10 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
IsMetavar(MetavarAtom.create(pattern.name))
}

is AnonymousMetavar -> {
ParamCondition.True
}

is TypedMetavar -> {
if (isGeneratedMethodInvocationObjMetaVar(pattern.name)) {
return ParamCondition.True
Expand All @@ -163,7 +171,7 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
ParamCondition.SpecificStaticFieldValue(fn.name, type)
}

is MetavarName -> {
is MetavarName, is AnonymousName -> {
transformationFailed("Static field name is metavar")
}
}
Expand Down Expand Up @@ -317,6 +325,7 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
val methodName = when (val name = pattern.methodName) {
is ConcreteName -> SignatureName.Concrete(name.name)
is MetavarName -> SignatureName.MetaVar(name.metavarName)
is AnonymousName -> transformationFailed("Method name is anonymous")
}

val actionList = mutableListOf<SemgrepPatternAction>()
Expand Down Expand Up @@ -557,6 +566,7 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
val methodName = when (val name = pattern.name) {
is ConcreteName -> SignatureName.Concrete(name.name)
is MetavarName -> SignatureName.MetaVar(name.metavarName)
is AnonymousName -> transformationFailed("Method name is anonymous")
}

val returnTypePattern: TypeConstraint? = pattern.returnType?.let { transformTypeName(it) }
Expand All @@ -567,21 +577,32 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
for ((i, param) in params.withIndex()) {
when (param) {
is FormalArgument -> {
val paramName = (param.name as? MetavarName)?.metavarName
?: transformationFailed("MethodDeclaration_param_name_not_metavar")

val position = if (idxIsConcrete) {
ParamPosition.Concrete(i)
} else {
ParamPosition.Any(paramClassifier = paramName)
val positionName = when (val name = param.name) {
is ConcreteName -> name.name
is MetavarName -> name.metavarName
is AnonymousName -> "*"
}
ParamPosition.Any(paramClassifier = positionName)
}

val paramModifiers = param.modifiers.map { transformModifier(it) }
paramModifiers.mapTo(paramConditions) { modifier ->
ParamPattern(position, ParamCondition.ParamModifier(modifier))
}

paramConditions += ParamPattern(position, IsMetavar(MetavarAtom.create(paramName)))
when(val name = param.name){
is MetavarName -> {
paramConditions += ParamPattern(
position,
IsMetavar(MetavarAtom.create(name.metavarName))
)
}
is AnonymousName -> {}
is ConcreteName -> transformationFailed("MethodDeclaration_param_name_not_metavar")
}

val paramType = transformTypeName(param.type)
paramConditions += ParamPattern(position, ParamCondition.TypeIs(paramType))
Expand Down Expand Up @@ -658,6 +679,7 @@ class PatternToActionListConverter: ActionListBuilder<SemgrepJavaPattern> {
}

is ConcreteName -> SignatureModifierValue.StringValue(paramName, value.name)
is AnonymousName -> SignatureModifierValue.AnyValue
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.opentaint.semgrep.pattern.conversion

import org.opentaint.semgrep.pattern.AnonymousName
import org.opentaint.semgrep.pattern.ConcreteName
import org.opentaint.semgrep.pattern.FieldAccess
import org.opentaint.semgrep.pattern.Identifier
Expand Down Expand Up @@ -34,7 +35,8 @@ fun tryExtractConcreteNames(names: List<Name>): List<String>? {
names.forEach { name ->
when (name) {
is ConcreteName -> result.add(name.name)
is MetavarName -> return null
is MetavarName,
is AnonymousName -> return null
}
}
return result
Expand Down
Loading
Loading