-
Notifications
You must be signed in to change notification settings - Fork 14
Expand file tree
/
Copy pathfunction-mapper.ts
More file actions
99 lines (86 loc) · 3.66 KB
/
Copy pathfunction-mapper.ts
File metadata and controls
99 lines (86 loc) · 3.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
import type { RNode } from '../r-bridge/lang-4.x/ast/model/model';
import type { ParentInformation } from '../r-bridge/lang-4.x/ast/model/processing/decorate';
import { RType } from '../r-bridge/lang-4.x/ast/model/type';
import { Identifier } from '../dataflow/environments/identifier';
import type { AbstractValue, AnyAbstractDomain } from '../abstract-interpretation/domains/abstract-domain';
import { VariableResolve } from '../config';
import type { FunctionParameterLocation } from '../abstract-interpretation/data-frame/mappers/arguments';
import {
getArgumentValue,
getFunctionArgument,
getFunctionArguments
} from '../abstract-interpretation/data-frame/mappers/arguments';
import type { DataflowGraph } from '../dataflow/graph/graph';
import type { ReadOnlyFlowrAnalyzerContext } from '../project/context/flowr-analyzer-context';
import type { PotentiallyEmptyRArgument } from '../r-bridge/lang-4.x/ast/model/nodes/r-function-call';
import { guard } from '../util/assert';
export type ResolvedTaint<Domain extends AnyAbstractDomain> =
{
condition: TaintConditionFunction<Domain>,
valArgs: unknown[], // TODO Support for other types apart from booleans
taintArgs: PotentiallyEmptyRArgument<ParentInformation>[]
}
| { taint: AbstractValue<Domain> }
| undefined;
/**
* Determine the resulting taint of a function call
* @param node - The function call
* @param mapper - Function mapper containing relations between function names and their tainting behaviour
* @param dfg - Data flow graph
* @param ctx - The analysis context
*/
export function mapFnCallToTaint<Domain extends AnyAbstractDomain>(
node: RNode<ParentInformation>,
mapper: TaintMapper<Domain>,
dfg: DataflowGraph,
ctx: ReadOnlyFlowrAnalyzerContext
): ResolvedTaint<Domain> {
if(node.type !== RType.FunctionCall || !node.named) {
return;
}
const functionName = Identifier.getName(node.functionName.content);
const mapping = mapper.find(m => {
if(Identifier.is(m.identifier)) {
return Identifier.matches(m.identifier, functionName);
} else {
return m.identifier.find(s => Identifier.matches(s, functionName));
}
});
if(mapping?.taint) {
return { taint: mapping.taint };
} else if(mapping?.condition) {
const resolveInfo = { graph: dfg, idMap: dfg.idMap, full: true, resolve: VariableResolve.Alias, ctx: ctx };
const allArgs = getFunctionArguments(node, dfg);
const valArgs = mapping.condition.argValues
? mapping.condition.argValues.map(location => getArgumentValue(allArgs, location, resolveInfo))
: [];
const taintArgs = mapping.condition.argTaints ? mapping.condition.argTaints.map(location => {
const arg = getFunctionArgument(allArgs, location, resolveInfo);
guard(arg, `Could not determine function argument for requested taint at position ${location.pos} with name ${location.name}`);
return arg;
}) : [];
return {
valArgs,
taintArgs,
condition: mapping.condition.condition,
};
}
}
export type TaintMapper<Domain extends AnyAbstractDomain> = TaintMapping<Domain>[];
export type TaintMapping<Domain extends AnyAbstractDomain> = {
identifier: Identifier | Identifier[];
} & (
| { taint: AbstractValue<Domain>; condition?: TaintCondition<Domain> }
| { taint?: AbstractValue<Domain>; condition: TaintCondition<Domain> }
);
export type TaintCondition<Domain extends AnyAbstractDomain = AnyAbstractDomain> = {
argValues?: FunctionParameterLocation<unknown>[],
argTaints?: TaintParameterLocation[],
condition: TaintConditionFunction<Domain>
};
export type TaintConditionFunction<Domain extends AnyAbstractDomain> =
( args: unknown[], taints: AbstractValue<Domain>[]) => AbstractValue<Domain>;
export interface TaintParameterLocation {
pos: number,
name?: string
}