@eagleoutice/flowr 2.9.14 → 2.10.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/README.md +37 -25
  2. package/benchmark/stats/stats.d.ts +2 -2
  3. package/cli/repl/parser/slice-query-parser.d.ts +2 -2
  4. package/config.d.ts +4 -0
  5. package/config.js +5 -3
  6. package/dataflow/environments/identifier.d.ts +4 -0
  7. package/dataflow/environments/identifier.js +17 -0
  8. package/dataflow/graph/call-graph.d.ts +4 -7
  9. package/dataflow/graph/call-graph.js +0 -22
  10. package/dataflow/graph/df-helper.d.ts +9 -8
  11. package/dataflow/graph/df-helper.js +9 -2
  12. package/dataflow/graph/graph-helper.d.ts +9 -4
  13. package/dataflow/graph/graph-helper.js +26 -3
  14. package/dataflow/graph/graph.d.ts +13 -2
  15. package/dataflow/graph/graph.js +26 -4
  16. package/dataflow/graph/vertex.d.ts +2 -0
  17. package/dataflow/internal/process/functions/call/built-in/built-in-apply.js +1 -0
  18. package/dataflow/internal/process/functions/call/built-in/built-in-assignment.js +1 -1
  19. package/dataflow/internal/process/functions/call/built-in/built-in-for-loop.js +1 -1
  20. package/dataflow/internal/process/functions/call/built-in/built-in-function-definition.js +2 -2
  21. package/dataflow/internal/process/functions/call/common.js +2 -1
  22. package/dataflow/internal/process/functions/process-parameter.js +1 -1
  23. package/documentation/doc-readme.js +2 -1
  24. package/documentation/wiki-linter.js +5 -0
  25. package/linter/linter-rules.d.ts +25 -0
  26. package/linter/linter-rules.js +2 -0
  27. package/linter/rules/problematic-eval.d.ts +44 -0
  28. package/linter/rules/problematic-eval.js +83 -0
  29. package/package.json +7 -7
  30. package/queries/catalog/df-shape-query/df-shape-query-executor.js +1 -1
  31. package/queries/catalog/df-shape-query/df-shape-query-format.d.ts +3 -3
  32. package/queries/catalog/does-call-query/does-call-query-executor.js +1 -1
  33. package/queries/catalog/does-call-query/does-call-query-format.d.ts +2 -2
  34. package/queries/catalog/happens-before-query/happens-before-query-executor.js +2 -2
  35. package/queries/catalog/happens-before-query/happens-before-query-format.d.ts +3 -3
  36. package/queries/catalog/input-sources-query/input-sources-query-executor.d.ts +6 -0
  37. package/queries/catalog/input-sources-query/input-sources-query-executor.js +66 -0
  38. package/queries/catalog/input-sources-query/input-sources-query-format.d.ts +36 -0
  39. package/queries/catalog/input-sources-query/input-sources-query-format.js +63 -0
  40. package/queries/catalog/input-sources-query/simple-input-classifier.d.ts +90 -0
  41. package/queries/catalog/input-sources-query/simple-input-classifier.js +308 -0
  42. package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.d.ts +2 -2
  43. package/queries/catalog/inspect-exceptions-query/inspect-exception-query-executor.js +1 -1
  44. package/queries/catalog/inspect-exceptions-query/inspect-exception-query-format.d.ts +2 -2
  45. package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-executor.js +1 -1
  46. package/queries/catalog/inspect-higher-order-query/inspect-higher-order-query-format.d.ts +2 -2
  47. package/queries/catalog/inspect-recursion-query/inspect-recursion-query-format.d.ts +2 -2
  48. package/queries/catalog/location-map-query/location-map-query-executor.js +1 -1
  49. package/queries/catalog/location-map-query/location-map-query-format.d.ts +2 -2
  50. package/queries/catalog/origin-query/origin-query-executor.d.ts +2 -2
  51. package/queries/catalog/origin-query/origin-query-executor.js +1 -1
  52. package/queries/catalog/origin-query/origin-query-format.d.ts +3 -3
  53. package/queries/catalog/provenance-query/provenance-query-executor.d.ts +1 -4
  54. package/queries/catalog/provenance-query/provenance-query-executor.js +3 -6
  55. package/queries/catalog/provenance-query/provenance-query-format.d.ts +2 -2
  56. package/queries/catalog/resolve-value-query/resolve-value-query-executor.js +1 -1
  57. package/queries/query.d.ts +9 -1
  58. package/queries/query.js +2 -0
  59. package/r-bridge/lang-4.x/ast/model/model.d.ts +3 -0
  60. package/r-bridge/lang-4.x/ast/model/model.js +3 -0
  61. package/r-bridge/lang-4.x/ast/model/nodes/r-access.d.ts +16 -1
  62. package/r-bridge/lang-4.x/ast/model/nodes/r-access.js +2 -0
  63. package/r-bridge/lang-4.x/ast/model/nodes/r-argument.d.ts +16 -1
  64. package/r-bridge/lang-4.x/ast/model/nodes/r-argument.js +2 -0
  65. package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.d.ts +16 -1
  66. package/r-bridge/lang-4.x/ast/model/nodes/r-binary-op.js +2 -0
  67. package/r-bridge/lang-4.x/ast/model/nodes/r-break.d.ts +15 -0
  68. package/r-bridge/lang-4.x/ast/model/nodes/r-break.js +2 -0
  69. package/r-bridge/lang-4.x/ast/model/nodes/r-comment.d.ts +15 -0
  70. package/r-bridge/lang-4.x/ast/model/nodes/r-comment.js +2 -0
  71. package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.d.ts +16 -1
  72. package/r-bridge/lang-4.x/ast/model/nodes/r-expression-list.js +2 -0
  73. package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.d.ts +16 -1
  74. package/r-bridge/lang-4.x/ast/model/nodes/r-for-loop.js +2 -0
  75. package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.d.ts +16 -1
  76. package/r-bridge/lang-4.x/ast/model/nodes/r-function-call.js +2 -0
  77. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.d.ts +21 -0
  78. package/r-bridge/lang-4.x/ast/model/nodes/r-function-definition.js +16 -0
  79. package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.d.ts +16 -1
  80. package/r-bridge/lang-4.x/ast/model/nodes/r-if-then-else.js +2 -0
  81. package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.d.ts +16 -1
  82. package/r-bridge/lang-4.x/ast/model/nodes/r-line-directive.js +2 -0
  83. package/r-bridge/lang-4.x/ast/model/nodes/r-logical.d.ts +16 -1
  84. package/r-bridge/lang-4.x/ast/model/nodes/r-logical.js +2 -0
  85. package/r-bridge/lang-4.x/ast/model/nodes/r-next.d.ts +16 -1
  86. package/r-bridge/lang-4.x/ast/model/nodes/r-next.js +2 -0
  87. package/r-bridge/lang-4.x/ast/model/nodes/r-number.d.ts +16 -1
  88. package/r-bridge/lang-4.x/ast/model/nodes/r-number.js +2 -0
  89. package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.d.ts +16 -1
  90. package/r-bridge/lang-4.x/ast/model/nodes/r-parameter.js +2 -0
  91. package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.d.ts +16 -1
  92. package/r-bridge/lang-4.x/ast/model/nodes/r-pipe.js +2 -0
  93. package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.d.ts +16 -1
  94. package/r-bridge/lang-4.x/ast/model/nodes/r-repeat-loop.js +2 -0
  95. package/r-bridge/lang-4.x/ast/model/nodes/r-string.d.ts +16 -1
  96. package/r-bridge/lang-4.x/ast/model/nodes/r-string.js +2 -0
  97. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.d.ts +16 -1
  98. package/r-bridge/lang-4.x/ast/model/nodes/r-symbol.js +2 -0
  99. package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.d.ts +16 -1
  100. package/r-bridge/lang-4.x/ast/model/nodes/r-unary-op.js +2 -0
  101. package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.d.ts +16 -1
  102. package/r-bridge/lang-4.x/ast/model/nodes/r-while-loop.js +2 -0
  103. package/search/search-executor/search-generators.js +1 -1
  104. package/slicing/criterion/parse.d.ts +11 -10
  105. package/slicing/criterion/parse.js +9 -8
  106. package/slicing/static/static-slicer.js +24 -1
  107. package/util/collections/arrays.d.ts +4 -0
  108. package/util/collections/arrays.js +7 -0
  109. package/util/mermaid/dfg.js +2 -1
  110. package/util/version.js +1 -1
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.InputSourcesDefinition = void 0;
7
+ const ansi_1 = require("../../../util/text/ansi");
8
+ const time_1 = require("../../../util/text/time");
9
+ const joi_1 = __importDefault(require("joi"));
10
+ const slice_query_parser_1 = require("../../../cli/repl/parser/slice-query-parser");
11
+ const input_sources_query_executor_1 = require("./input-sources-query-executor");
12
+ const range_1 = require("../../../util/range");
13
+ function inputSourcesQueryLineParser(output, line, _config) {
14
+ const criterion = (0, slice_query_parser_1.sliceCriteriaParser)(line[0]);
15
+ if (!criterion || criterion.length !== 1) {
16
+ output.stderr(output.formatter.format('Invalid provenance query format, a single slicing criterion must be given in the form "(criterion1)"', { color: 1 /* Colors.Red */, effect: ansi_1.ColorEffect.Foreground, style: 1 /* FontStyles.Bold */ }));
17
+ return { query: [] };
18
+ }
19
+ return { query: [{
20
+ type: 'input-sources',
21
+ criterion: criterion[0],
22
+ }], rCode: line[1] };
23
+ }
24
+ exports.InputSourcesDefinition = {
25
+ executor: input_sources_query_executor_1.executeInputSourcesQuery,
26
+ asciiSummarizer: async (formatter, analyzer, queryResults, result) => {
27
+ const out = queryResults;
28
+ result.push(`Query: ${(0, ansi_1.bold)('input-sources', formatter)} (${(0, time_1.printAsMs)(out['.meta'].timing, 0)})`);
29
+ const nast = (await analyzer.normalize()).idMap;
30
+ for (const [key, sources] of Object.entries(out.results)) {
31
+ result.push(` ╰ Input Sources for ${key}`);
32
+ for (const { id, trace, type } of sources) {
33
+ const kNode = nast.get(id);
34
+ const kLoc = kNode ? range_1.SourceLocation.format(range_1.SourceLocation.fromNode(kNode)) : 'unknown location';
35
+ result.push(` ╰ ${kLoc} (id: ${id}), type: ${JSON.stringify(type)}, trace: ${trace}`);
36
+ }
37
+ }
38
+ return true;
39
+ },
40
+ fromLine: inputSourcesQueryLineParser,
41
+ schema: joi_1.default.object({
42
+ type: joi_1.default.string().valid('input-sources').required().description('The type of the query.'),
43
+ criterion: joi_1.default.string().required().description('The slicing criterion to use.'),
44
+ config: joi_1.default.object({
45
+ networkFunctions: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that fetch data from the network.'),
46
+ randomnessConsumers: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that consume randomness.'),
47
+ randomnessProducers: joi_1.default.array().items(joi_1.default.object({ type: joi_1.default.string().valid('function', 'assignment'), name: joi_1.default.string().required() })).optional().description('Functions or assignments that produce randomness seeds.'),
48
+ configurableFunctions: joi_1.default.array().items(joi_1.default.string()).optional().description('Functions that read configuration (options/env).'),
49
+ pureFunctions: joi_1.default.array().items(joi_1.default.string()).optional().description('Deterministic functions that keep constant inputs constant.'),
50
+ }).optional()
51
+ }).description('Input Sources query definition'),
52
+ flattenInvolvedNodes: (queryResults) => {
53
+ const flattened = [];
54
+ const out = queryResults;
55
+ for (const obj of Object.values(out.results)) {
56
+ for (const e of obj) {
57
+ flattened.push(e.id);
58
+ }
59
+ }
60
+ return flattened;
61
+ }
62
+ };
63
+ //# sourceMappingURL=input-sources-query-format.js.map
@@ -0,0 +1,90 @@
1
+ import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
2
+ import type { DataflowGraph } from '../../../dataflow/graph/graph';
3
+ import type { MergeableRecord } from '../../../util/objects';
4
+ import { Identifier } from '../../../dataflow/environments/identifier';
5
+ /**
6
+ * Lattice flattening until we have a taint engine :)
7
+ *
8
+ *```
9
+ * [ Unknown ]
10
+ * / / | \ \
11
+ *[Param] [File] [Net] [Rand] [Scope]
12
+ * \ \ | / /
13
+ * [ DerivedConstant ]
14
+ * |
15
+ * [ Constant ]
16
+ *```
17
+ *
18
+ */
19
+ export declare enum InputType {
20
+ Parameter = "param",
21
+ File = "file",
22
+ Network = "net",
23
+ Random = "rand",
24
+ Constant = "const",
25
+ /** Read from environment/call scope */
26
+ Scope = "scope",
27
+ /** Pure calculations from constants that lead to a constant */
28
+ DerivedConstant = "dconst",
29
+ Unknown = "unknown"
30
+ }
31
+ export declare enum InputTraceType {
32
+ /** Derived only from aliasing */
33
+ Alias = "alias",
34
+ /** Derived from pure function chains */
35
+ Pure = "pure",
36
+ /** Derived from known but not necessarily all pure function chains */
37
+ Known = "known",
38
+ /** Not fully known origin */
39
+ Unknown = "unknown"
40
+ }
41
+ /**
42
+ * Object attached to an input source
43
+ * @see {@link InputSources}
44
+ */
45
+ export interface InputSource extends MergeableRecord {
46
+ id: NodeId;
47
+ type: InputType[];
48
+ trace: InputTraceType;
49
+ /** if the trace is affected by control dependencies, they are classified too, this is a duplicate free array */
50
+ cds?: InputType[];
51
+ }
52
+ /**
53
+ * Map of input sources, keyed by the node id of the input source. Each input source is classified with an {@link InputSource} object.
54
+ */
55
+ export type InputSources = InputSource[];
56
+ /**
57
+ * This is either an {@link NodeId|id} of a known functions all of that category (e.g., you can issue a dependencies query before and then pass all
58
+ * identified ids to this query here).
59
+ */
60
+ export type InputClassifierFunctionIdentifier = Identifier | NodeId;
61
+ /**
62
+ * For the specifications of `pureFns` etc. please have a look at {@link InputClassifierFunctionIdentifier}.
63
+ */
64
+ export interface InputClassifierConfig extends MergeableRecord {
65
+ /**
66
+ * Functions which are considered to be pure (i.e., deterministic, trusted, safe, idempotent on the lub of the input types)
67
+ */
68
+ pureFns: readonly InputClassifierFunctionIdentifier[];
69
+ /**
70
+ * Functions that read from the network
71
+ */
72
+ networkFns: readonly InputClassifierFunctionIdentifier[];
73
+ /**
74
+ * Functions that produce a random value
75
+ * Note: may need to check with respect to seeded randomness
76
+ */
77
+ randomFns: readonly InputClassifierFunctionIdentifier[];
78
+ /**
79
+ * Functions that read from the file system
80
+ */
81
+ readFileFns: readonly InputClassifierFunctionIdentifier[];
82
+ }
83
+ /**
84
+ * Takes the given id which is expected to either be:
85
+ * - a function call - in this case all arguments are considered to be inputs (additionally to all read edges from the function call in the dataflow graph)
86
+ * - anything else - in that case the node itself is considered as an "input" - please note that in these scenarios the *return* value will only contain one mapping - that for the id you pased in.
87
+ *
88
+ * This method traces the dependencies in the dataflow graph using the specification of functions passed in
89
+ */
90
+ export declare function classifyInput(id: NodeId, dfg: DataflowGraph, config: InputClassifierConfig): InputSources;
@@ -0,0 +1,308 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.InputTraceType = exports.InputType = void 0;
4
+ exports.classifyInput = classifyInput;
5
+ const graph_1 = require("../../../dataflow/graph/graph");
6
+ const objects_1 = require("../../../util/objects");
7
+ const vertex_1 = require("../../../dataflow/graph/vertex");
8
+ const df_helper_1 = require("../../../dataflow/graph/df-helper");
9
+ const identifier_1 = require("../../../dataflow/environments/identifier");
10
+ const assert_1 = require("../../../util/assert");
11
+ const arrays_1 = require("../../../util/collections/arrays");
12
+ const built_in_proc_name_1 = require("../../../dataflow/environments/built-in-proc-name");
13
+ class InputClassifier {
14
+ dfg;
15
+ config;
16
+ cache = new Map();
17
+ constructor(dfg, config) {
18
+ this.dfg = dfg;
19
+ this.config = config;
20
+ }
21
+ classifyEntry(vertex) {
22
+ const cached = this.cache.get(vertex.id);
23
+ if (cached) {
24
+ return cached;
25
+ }
26
+ // insert temporary unknown to break cycles
27
+ this.cache.set(vertex.id, { id: vertex.id, type: [InputType.Unknown], trace: InputTraceType.Unknown });
28
+ switch (vertex.tag) {
29
+ case vertex_1.VertexType.Value:
30
+ return this.classifyCdsAndReturn(vertex, { id: vertex.id, type: [InputType.Constant], trace: InputTraceType.Unknown });
31
+ case vertex_1.VertexType.FunctionCall:
32
+ return this.classifyFunctionCall(vertex);
33
+ case vertex_1.VertexType.VariableDefinition:
34
+ return this.classifyVariableDefinition(vertex);
35
+ case vertex_1.VertexType.Use:
36
+ return this.classifyVariable(vertex);
37
+ default:
38
+ return this.classifyCdsAndReturn(vertex, { id: vertex.id, type: [InputType.Unknown], trace: InputTraceType.Unknown });
39
+ }
40
+ }
41
+ classifyFunctionCall(call) {
42
+ if (call.origin.includes(built_in_proc_name_1.BuiltInProcName.IfThenElse) || call.origin.includes(built_in_proc_name_1.BuiltInProcName.WhileLoop)) {
43
+ const condition = graph_1.FunctionArgument.getReference(call.args[0]);
44
+ if (condition) {
45
+ const vtx = this.dfg.getVertex(condition);
46
+ if (vtx) {
47
+ return this.classifyCdsAndReturn(call, this.classifyEntry(vtx));
48
+ }
49
+ }
50
+ }
51
+ else if (call.origin.includes(built_in_proc_name_1.BuiltInProcName.ForLoop)) {
52
+ const condition = graph_1.FunctionArgument.getReference(call.args[1]);
53
+ if (condition) {
54
+ const vtx = this.dfg.getVertex(condition);
55
+ if (vtx) {
56
+ return this.classifyCdsAndReturn(call, this.classifyEntry(vtx));
57
+ }
58
+ }
59
+ }
60
+ if (!matchesList(call, this.config.pureFns)) {
61
+ if (matchesList(call, this.config.readFileFns)) {
62
+ return this.classifyCdsAndReturn(call, { id: call.id, type: [InputType.File], trace: InputTraceType.Unknown });
63
+ }
64
+ else if (matchesList(call, this.config.networkFns)) {
65
+ return this.classifyCdsAndReturn(call, { id: call.id, type: [InputType.Network], trace: InputTraceType.Unknown });
66
+ }
67
+ else if (matchesList(call, this.config.randomFns)) {
68
+ return this.classifyCdsAndReturn(call, { id: call.id, type: [InputType.Random], trace: InputTraceType.Unknown });
69
+ }
70
+ else {
71
+ // if it is not pure, we cannot classify based on the inputs, in that case we do not know!
72
+ return this.classifyCdsAndReturn(call, { id: call.id, type: [InputType.Unknown], trace: InputTraceType.Unknown });
73
+ }
74
+ }
75
+ // Otherwise, classify by arguments; pure functions get Known/Pure handling
76
+ const argTypes = [];
77
+ const cdTypes = [];
78
+ for (const arg of call.args) {
79
+ if (graph_1.FunctionArgument.isEmpty(arg)) {
80
+ continue;
81
+ }
82
+ const ref = graph_1.FunctionArgument.getReference(arg);
83
+ if (ref === undefined) {
84
+ argTypes.push(InputType.Unknown);
85
+ continue;
86
+ }
87
+ const argVtx = this.dfg.getVertex(ref);
88
+ if (!argVtx) {
89
+ argTypes.push(InputType.Unknown);
90
+ continue;
91
+ }
92
+ const classified = this.classifyEntry(argVtx);
93
+ // collect all observed types from this argument
94
+ argTypes.push(...classified.type);
95
+ if (classified.cds) {
96
+ cdTypes.push(...classified.cds);
97
+ }
98
+ }
99
+ const cds = cdTypes.length > 0 ? (0, arrays_1.uniqueArray)(cdTypes) : undefined;
100
+ // all arguments only contain constant-like types -> derived constant
101
+ const allConstLike = argTypes.length > 0 && argTypes.every(t => t === InputType.Constant || t === InputType.DerivedConstant);
102
+ if (allConstLike) {
103
+ return this.classifyCdsAndReturn(call, (0, objects_1.compactRecord)({ id: call.id, type: [InputType.DerivedConstant], trace: InputTraceType.Pure, cds }));
104
+ }
105
+ const types = argTypes.length === 0 ? [InputType.DerivedConstant] : (0, arrays_1.uniqueArray)(argTypes);
106
+ return this.classifyCdsAndReturn(call, (0, objects_1.compactRecord)({ id: call.id, type: types, trace: InputTraceType.Known, cds }));
107
+ }
108
+ classifyVariable(vtx) {
109
+ const origins = df_helper_1.Dataflow.origin(this.dfg, vtx.id);
110
+ if (origins === undefined) {
111
+ return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: [InputType.Unknown], trace: InputTraceType.Unknown });
112
+ }
113
+ const types = [];
114
+ const cds = [];
115
+ let allPure = true;
116
+ for (const o of origins) {
117
+ if (o.type === 4 /* OriginType.ConstantOrigin */) {
118
+ types.push(InputType.Constant);
119
+ continue;
120
+ }
121
+ if (o.type === 0 /* OriginType.ReadVariableOrigin */ || o.type === 1 /* OriginType.WriteVariableOrigin */) {
122
+ const v = this.dfg.getVertex(o.id);
123
+ if (v) {
124
+ // if this is a variable definition that is a parameter, classify as Parameter
125
+ if (v.tag === vertex_1.VertexType.VariableDefinition && this.dfg.idMap?.get(v.id)?.info.role === "param-n" /* RoleInParent.ParameterName */) {
126
+ types.push(InputType.Parameter);
127
+ continue;
128
+ }
129
+ const c = this.classifyEntry(v);
130
+ types.push(...c.type);
131
+ if (c.cds) {
132
+ cds.push(...c.cds);
133
+ }
134
+ if (c.trace !== InputTraceType.Pure) {
135
+ allPure = false;
136
+ }
137
+ }
138
+ else {
139
+ types.push(InputType.Unknown);
140
+ }
141
+ continue;
142
+ }
143
+ if (o.type === 2 /* OriginType.FunctionCallOrigin */ || o.type === 3 /* OriginType.BuiltInFunctionOrigin */) {
144
+ const v = this.dfg.getVertex(o.id);
145
+ if (v) {
146
+ const c = this.classifyEntry(v);
147
+ types.push(...c.type);
148
+ if (c.cds) {
149
+ cds.push(...c.cds);
150
+ }
151
+ if (c.trace !== InputTraceType.Pure) {
152
+ allPure = false;
153
+ }
154
+ }
155
+ else {
156
+ types.push(InputType.Unknown);
157
+ }
158
+ continue;
159
+ }
160
+ // unknown origin type
161
+ types.push(InputType.Unknown);
162
+ }
163
+ const t = types.length === 0 ? [InputType.Unknown] : (0, arrays_1.uniqueArray)(types);
164
+ const trace = allPure ? InputTraceType.Pure : InputTraceType.Alias;
165
+ return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: t, trace, cds: cds.length === 0 ? undefined : (0, arrays_1.uniqueArray)(cds) });
166
+ }
167
+ classifyVariableDefinition(vtx) {
168
+ // parameter definitions are classified as Parameter
169
+ if (this.dfg.idMap?.get(vtx.id)?.info.role === "param-n" /* RoleInParent.ParameterName */) {
170
+ return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: [InputType.Parameter], trace: InputTraceType.Unknown });
171
+ }
172
+ const sources = vtx.source;
173
+ if (sources === undefined || sources.length === 0) {
174
+ // fallback to unknown if we cannot find the value
175
+ return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: [InputType.Unknown], trace: InputTraceType.Unknown });
176
+ }
177
+ const types = [];
178
+ const cds = [];
179
+ let allPure = true;
180
+ for (const tid of sources) {
181
+ const tv = this.dfg.getVertex(tid);
182
+ if (tv) {
183
+ const c = this.classifyEntry(tv);
184
+ types.push(...c.type);
185
+ if (c.cds) {
186
+ cds.push(...c.cds);
187
+ }
188
+ if (c.trace !== InputTraceType.Pure) {
189
+ allPure = false;
190
+ }
191
+ }
192
+ else {
193
+ types.push(InputType.Unknown);
194
+ }
195
+ }
196
+ const t = types.length === 0 ? [InputType.Unknown] : (0, arrays_1.uniqueArray)(types);
197
+ const trace = allPure ? InputTraceType.Pure : InputTraceType.Alias;
198
+ return this.classifyCdsAndReturn(vtx, { id: vtx.id, type: t, trace, cds: cds.length === 0 ? undefined : (0, arrays_1.uniqueArray)(cds) });
199
+ }
200
+ classifyCdsAndReturn(vtx, src) {
201
+ if (vtx.cds) {
202
+ const cds = (0, arrays_1.uniqueArray)(vtx.cds.flatMap(c => {
203
+ const cv = this.dfg.getVertex(c.id);
204
+ if (!cv) {
205
+ return undefined;
206
+ }
207
+ const e = this.classifyEntry(cv);
208
+ return e.cds ? [...e.type, ...e.cds] : [...e.type];
209
+ }).filter(assert_1.isNotUndefined).concat(src.cds ?? []));
210
+ if (cds.length > 0) {
211
+ src.cds = cds;
212
+ }
213
+ }
214
+ if (src.cds?.length === 0) {
215
+ delete src.cds;
216
+ }
217
+ this.cache.set(vtx.id, src);
218
+ return src;
219
+ }
220
+ }
221
+ /**
222
+ * Lattice flattening until we have a taint engine :)
223
+ *
224
+ *```
225
+ * [ Unknown ]
226
+ * / / | \ \
227
+ *[Param] [File] [Net] [Rand] [Scope]
228
+ * \ \ | / /
229
+ * [ DerivedConstant ]
230
+ * |
231
+ * [ Constant ]
232
+ *```
233
+ *
234
+ */
235
+ var InputType;
236
+ (function (InputType) {
237
+ InputType["Parameter"] = "param";
238
+ InputType["File"] = "file";
239
+ InputType["Network"] = "net";
240
+ InputType["Random"] = "rand";
241
+ InputType["Constant"] = "const";
242
+ /** Read from environment/call scope */
243
+ InputType["Scope"] = "scope";
244
+ /** Pure calculations from constants that lead to a constant */
245
+ InputType["DerivedConstant"] = "dconst";
246
+ InputType["Unknown"] = "unknown";
247
+ })(InputType || (exports.InputType = InputType = {}));
248
+ var InputTraceType;
249
+ (function (InputTraceType) {
250
+ /** Derived only from aliasing */
251
+ InputTraceType["Alias"] = "alias";
252
+ /** Derived from pure function chains */
253
+ InputTraceType["Pure"] = "pure";
254
+ /** Derived from known but not necessarily all pure function chains */
255
+ InputTraceType["Known"] = "known";
256
+ /** Not fully known origin */
257
+ InputTraceType["Unknown"] = "unknown";
258
+ })(InputTraceType || (exports.InputTraceType = InputTraceType = {}));
259
+ function matchesList(fn, list) {
260
+ if (!list || list.length === 0) {
261
+ return false;
262
+ }
263
+ for (const id of list) {
264
+ if (fn.id === id || identifier_1.Identifier.matches(id, fn.name)) {
265
+ return true;
266
+ }
267
+ }
268
+ return false;
269
+ }
270
+ /**
271
+ * Takes the given id which is expected to either be:
272
+ * - a function call - in this case all arguments are considered to be inputs (additionally to all read edges from the function call in the dataflow graph)
273
+ * - anything else - in that case the node itself is considered as an "input" - please note that in these scenarios the *return* value will only contain one mapping - that for the id you pased in.
274
+ *
275
+ * This method traces the dependencies in the dataflow graph using the specification of functions passed in
276
+ */
277
+ function classifyInput(id, dfg, config) {
278
+ const vtx = dfg.getVertex(id);
279
+ if (!vtx) {
280
+ return [];
281
+ }
282
+ const c = new InputClassifier(dfg, config);
283
+ if (vtx.tag === vertex_1.VertexType.FunctionCall) {
284
+ const ret = [];
285
+ const args = vtx.args;
286
+ for (const arg of args) {
287
+ if (graph_1.FunctionArgument.isEmpty(arg)) {
288
+ continue;
289
+ }
290
+ const ref = graph_1.FunctionArgument.getReference(arg);
291
+ if (ref === undefined) {
292
+ continue;
293
+ }
294
+ const argVtx = dfg.getVertex(ref);
295
+ if (argVtx === undefined) {
296
+ continue;
297
+ }
298
+ ret.push(c.classifyEntry(argVtx));
299
+ }
300
+ return ret;
301
+ }
302
+ else {
303
+ return [
304
+ c.classifyEntry(vtx)
305
+ ];
306
+ }
307
+ }
308
+ //# sourceMappingURL=simple-input-classifier.js.map
@@ -1,13 +1,13 @@
1
1
  import type { InspectExceptionQuery, InspectExceptionQueryResult } from './inspect-exception-query-format';
2
2
  import type { BasicQueryData } from '../../base-query-format';
3
- import { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
3
+ import { SlicingCriterion } from '../../../slicing/criterion/parse';
4
4
  import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
5
5
  import type { ReadonlyFlowrAnalysisProvider } from '../../../project/flowr-analyzer';
6
6
  /**
7
7
  * Get the functions to consider in the call graph based on the given queries.
8
8
  */
9
9
  export declare function getFunctionsToConsiderInCallGraph(queries: readonly {
10
- filter?: readonly SingleSlicingCriterion[];
10
+ filter?: readonly SlicingCriterion[];
11
11
  }[], analyzer: ReadonlyFlowrAnalysisProvider, onlyDefinitions?: boolean): Promise<{
12
12
  cg: import("../../../dataflow/graph/call-graph").CallGraph;
13
13
  fns: MapIterator<[NodeId, Required<import("../../../dataflow/graph/vertex").DataflowGraphVertexFunctionCall | import("../../../dataflow/graph/vertex").DataflowGraphVertexFunctionDefinition>]>;
@@ -25,7 +25,7 @@ async function getFunctionsToConsiderInCallGraph(queries, analyzer, onlyDefiniti
25
25
  const filterFor = new Set();
26
26
  if (filters) {
27
27
  for (const f of filters) {
28
- const i = parse_1.SingleSlicingCriterion.tryParse(f, ast.idMap);
28
+ const i = parse_1.SlicingCriterion.tryParse(f, ast.idMap);
29
29
  if (i !== undefined) {
30
30
  filterFor.add(i);
31
31
  }
@@ -6,7 +6,7 @@ import { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id'
6
6
  import type { ReplOutput } from '../../../cli/repl/commands/repl-main';
7
7
  import type { FlowrConfig } from '../../../config';
8
8
  import type { ExceptionPoint } from '../../../dataflow/fn/exceptions-of-function';
9
- import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
9
+ import type { SlicingCriterion } from '../../../slicing/criterion/parse';
10
10
  /**
11
11
  * Either returns all function definitions alongside exception information,
12
12
  * or just those matching the filters.
@@ -14,7 +14,7 @@ import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
14
14
  export interface InspectExceptionQuery extends BaseQueryFormat {
15
15
  readonly type: 'inspect-exception';
16
16
  /** If given, only function definitions that match one of the given slicing criteria are considered. */
17
- readonly filter?: SingleSlicingCriterion[];
17
+ readonly filter?: SlicingCriterion[];
18
18
  }
19
19
  export interface InspectExceptionQueryResult extends BaseQueryResult {
20
20
  /**
@@ -26,7 +26,7 @@ async function executeHigherOrderQuery({ analyzer }, queries) {
26
26
  const filterFor = new Set();
27
27
  if (filters) {
28
28
  for (const f of filters) {
29
- const i = parse_1.SingleSlicingCriterion.tryParse(f, ast.idMap);
29
+ const i = parse_1.SlicingCriterion.tryParse(f, ast.idMap);
30
30
  if (i !== undefined) {
31
31
  filterFor.add(i);
32
32
  }
@@ -3,7 +3,7 @@ import Joi from 'joi';
3
3
  import type { ParsedQueryLine } from '../../query';
4
4
  import { executeHigherOrderQuery } from './inspect-higher-order-query-executor';
5
5
  import { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
6
- import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
6
+ import type { SlicingCriterion } from '../../../slicing/criterion/parse';
7
7
  import type { ReplOutput } from '../../../cli/repl/commands/repl-main';
8
8
  import type { FlowrConfig } from '../../../config';
9
9
  /**
@@ -12,7 +12,7 @@ import type { FlowrConfig } from '../../../config';
12
12
  */
13
13
  export interface InspectHigherOrderQuery extends BaseQueryFormat {
14
14
  readonly type: 'inspect-higher-order';
15
- readonly filter?: SingleSlicingCriterion[];
15
+ readonly filter?: SlicingCriterion[];
16
16
  }
17
17
  export interface InspectHigherOrderQueryResult extends BaseQueryResult {
18
18
  readonly higherOrder: Record<NodeId, boolean>;
@@ -3,7 +3,7 @@ import Joi from 'joi';
3
3
  import type { ParsedQueryLine } from '../../query';
4
4
  import { executeRecursionQuery } from './inspect-recursion-query-executor';
5
5
  import { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
6
- import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
6
+ import type { SlicingCriterion } from '../../../slicing/criterion/parse';
7
7
  import type { ReplOutput } from '../../../cli/repl/commands/repl-main';
8
8
  import type { FlowrConfig } from '../../../config';
9
9
  /**
@@ -12,7 +12,7 @@ import type { FlowrConfig } from '../../../config';
12
12
  */
13
13
  export interface InspectRecursionQuery extends BaseQueryFormat {
14
14
  readonly type: 'inspect-recursion';
15
- readonly filter?: SingleSlicingCriterion[];
15
+ readonly filter?: SlicingCriterion[];
16
16
  }
17
17
  export interface InspectRecursionQueryResult extends BaseQueryResult {
18
18
  readonly recursive: Record<NodeId, boolean>;
@@ -31,7 +31,7 @@ async function executeLocationMapQuery({ analyzer }, queries) {
31
31
  const start = Date.now();
32
32
  const criteriaOfInterest = new Set(queries
33
33
  .flatMap(q => q.ids ?? [])
34
- .map(c => parse_1.SingleSlicingCriterion.tryParse(c, ast.idMap))
34
+ .map(c => parse_1.SlicingCriterion.tryParse(c, ast.idMap))
35
35
  .filter(assert_1.isNotUndefined));
36
36
  const locationMap = {
37
37
  files: {},
@@ -4,14 +4,14 @@ import { type OutputFormatter } from '../../../util/text/ansi';
4
4
  import Joi from 'joi';
5
5
  import type { NodeId } from '../../../r-bridge/lang-4.x/ast/model/processing/node-id';
6
6
  import type { SourceRange } from '../../../util/range';
7
- import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
7
+ import type { SlicingCriterion } from '../../../slicing/criterion/parse';
8
8
  import type { ReplOutput } from '../../../cli/repl/commands/repl-main';
9
9
  import type { FlowrConfig } from '../../../config';
10
10
  import type { ParsedQueryLine } from '../../query';
11
11
  export interface LocationMapQuery extends BaseQueryFormat {
12
12
  readonly type: 'location-map';
13
13
  /** Optional list of ids to filter the results by. If not provided, all ids will be included. */
14
- readonly ids?: readonly SingleSlicingCriterion[];
14
+ readonly ids?: readonly SlicingCriterion[];
15
15
  }
16
16
  export type FileId = number & {
17
17
  readonly __fileId?: unique symbol;
@@ -1,10 +1,10 @@
1
1
  import type { BasicQueryData } from '../../base-query-format';
2
- import { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
2
+ import { SlicingCriterion } from '../../../slicing/criterion/parse';
3
3
  import type { OriginQuery, OriginQueryResult } from './origin-query-format';
4
4
  /**
5
5
  * Produce a fingerprint string for an origin query
6
6
  */
7
- export declare function fingerPrintOfQuery(query: OriginQuery): SingleSlicingCriterion;
7
+ export declare function fingerPrintOfQuery(query: OriginQuery): SlicingCriterion;
8
8
  /**
9
9
  * Execute origin queries, catching duplicates with the same fingerprint
10
10
  */
@@ -22,7 +22,7 @@ async function executeResolveValueQuery({ analyzer }, queries) {
22
22
  if (results[key]) {
23
23
  log_1.log.warn(`Duplicate Key for origin-query: ${key}, skipping...`);
24
24
  }
25
- const astId = parse_1.SingleSlicingCriterion.tryParse(key, (await analyzer.normalize()).idMap);
25
+ const astId = parse_1.SlicingCriterion.tryParse(key, (await analyzer.normalize()).idMap);
26
26
  if (astId === undefined) {
27
27
  log_1.log.warn(`Could not resolve id for ${key}, skipping...`);
28
28
  continue;
@@ -1,5 +1,5 @@
1
1
  import type { BaseQueryFormat, BaseQueryResult } from '../../base-query-format';
2
- import type { SingleSlicingCriterion } from '../../../slicing/criterion/parse';
2
+ import type { SlicingCriterion } from '../../../slicing/criterion/parse';
3
3
  import type { ParsedQueryLine } from '../../query';
4
4
  import Joi from 'joi';
5
5
  import { executeResolveValueQuery } from './origin-query-executor';
@@ -10,10 +10,10 @@ import type { FlowrConfig } from '../../../config';
10
10
  export interface OriginQuery extends BaseQueryFormat {
11
11
  readonly type: 'origin';
12
12
  /** The slicing criteria to use */
13
- readonly criterion: SingleSlicingCriterion;
13
+ readonly criterion: SlicingCriterion;
14
14
  }
15
15
  export interface OriginQueryResult extends BaseQueryResult {
16
- results: Record<SingleSlicingCriterion, Origin[] | undefined>;
16
+ results: Record<SlicingCriterion, Origin[] | undefined>;
17
17
  }
18
18
  declare function originQueryLineParser(output: ReplOutput, line: readonly string[], _config: FlowrConfig): ParsedQueryLine<'origin'>;
19
19
  export declare const OriginQueryDefinition: {
@@ -1,9 +1,6 @@
1
1
  import type { BasicQueryData } from '../../base-query-format';
2
2
  import type { ProvenanceQuery, ProvenanceQueryResult } from './provenance-query-format';
3
3
  /**
4
- * Execute static slice queries, catching duplicates with the same fingerprint
5
- * @param analyzer - The basic query data containing the analyzer
6
- * @param queries - The static slice queries to execute
7
- * @returns The results of the static slice queries
4
+ * Execute a provenance query collection, {@link Dataflow.provenance}
8
5
  */
9
6
  export declare function executeProvenanceQuery({ analyzer }: BasicQueryData, queries: readonly ProvenanceQuery[]): Promise<ProvenanceQueryResult>;