Compare commits

..

65 Commits

Author SHA1 Message Date
Jean Helie
bc0e2947d7 use new mad kinds 2023-06-19 08:51:27 +02:00
Jean Helie
982bebea82 add raw framework generated models for spring framework 2023-06-16 12:08:20 +02:00
Jean Helie
209f3e26d4 Merge pull request #13239 from github/tausbn/automodel-application-mode
Java: Add QL support for automodel application mode
2023-06-14 11:42:26 +02:00
Anders Schack-Mulligen
1a4fca334f Merge pull request #13273 from aschackmull/dataflow/summarynode-refactor
Dataflow: Refactor FlowSummaryImpl to synthesize nodes independently from DataFlow::Node.
2023-06-14 09:38:36 +02:00
Anders Schack-Mulligen
2d616d494e C#/Ruby: Add fields as per review comments. 2023-06-13 11:26:30 +02:00
Michael Nebel
577bbd531d C#: Base tests on stubs, move extractor options to options file and updated expected test output. 2023-06-13 10:17:42 +02:00
Anders Schack-Mulligen
bc7cb1ec47 C#: Fix some qltests. 2023-06-12 16:19:04 +02:00
Anders Schack-Mulligen
949d4491f9 C#: Remove summaries for void-returning Reverse methods. 2023-06-12 13:18:28 +02:00
Anders Schack-Mulligen
eec012d308 Java: Fix test 2023-06-12 13:18:13 +02:00
Anders Schack-Mulligen
88fe0f089e C#: Fix expected output. 2023-06-12 13:17:55 +02:00
Anders Schack-Mulligen
f8ff575ff0 C#: Fix bugs in misc models. 2023-06-12 11:37:57 +02:00
Anders Schack-Mulligen
5062442982 Go/Python/Ruby/Swift: Add stub. 2023-06-09 15:39:28 +02:00
Anders Schack-Mulligen
2ecce575a9 C#: Fix types of summary parameter nodes. 2023-06-09 15:39:28 +02:00
Anders Schack-Mulligen
98f51d7f29 Dataflow: Sync. 2023-06-09 15:39:28 +02:00
Anders Schack-Mulligen
97b2bdaa9f Java: Fix types of summary parameter nodes. 2023-06-09 15:39:28 +02:00
Anders Schack-Mulligen
b2d3f29ef3 Swift: Fix tests. 2023-06-09 15:39:28 +02:00
Anders Schack-Mulligen
5eb278095c Go: Fix tests. 2023-06-09 15:39:28 +02:00
Anders Schack-Mulligen
0c62901a67 Ruby: Fix tests. 2023-06-09 15:39:18 +02:00
Anders Schack-Mulligen
6020e4d0e3 C#/Go/Python/Ruby/Swift: Fix some more references. 2023-06-09 15:30:38 +02:00
Anders Schack-Mulligen
1c3b8e2b96 Swift: Adjust to FlowSummaryImpl changes. 2023-06-09 15:30:38 +02:00
Anders Schack-Mulligen
4e531af71b Ruby: Adjust to FlowSummaryImpl changes. 2023-06-09 15:30:35 +02:00
Anders Schack-Mulligen
1e3b960c1b Python: Adjust to FlowSummaryImpl changes. 2023-06-09 15:27:17 +02:00
Anders Schack-Mulligen
e6e4cef35e Go: Adjust to FlowSummaryImpl changes. 2023-06-09 15:27:17 +02:00
Anders Schack-Mulligen
5e6031724a C#: Adjust to FlowSummaryImpl changes. 2023-06-09 15:27:17 +02:00
Anders Schack-Mulligen
2cc5bde925 Dataflow: Sync. 2023-06-09 15:27:17 +02:00
Anders Schack-Mulligen
254d60c826 Dataflow: Refactor FlowSummaryImpl to synthesize nodes independently from DataFlow::Node. 2023-06-09 15:27:17 +02:00
Anders Schack-Mulligen
59636c43ca Dataflow: Rename two private predicates. 2023-06-09 15:27:17 +02:00
Stephan Brandauer
b38bc52019 Java: fix bug in ExcludedFromModeling Characteristic 2023-06-09 14:57:56 +02:00
Stephan Brandauer
2921df41da Java: fix import 2023-06-07 15:22:59 +02:00
Stephan Brandauer
ec3a7e39ad Java: qldoc style 2023-06-07 14:57:38 +02:00
Stephan Brandauer
715b1351f3 Java: share considerSubtypes predicate between Java modes 2023-06-07 14:55:00 +02:00
Stephan Brandauer
7e77e2ea82 Java: comment why we're using erased types in MaD 2023-06-07 14:42:20 +02:00
Stephan Brandauer
a8799fe981 Java: share getCallable interface between automodel extraction modes 2023-06-07 14:38:52 +02:00
Stephan Brandauer
92ad02a752 Java: update getRelatedLocation qldoc 2023-06-07 14:09:07 +02:00
Stephan Brandauer
be6b1d8aaf Java: remove SkipFrameworkModeling characteristic in favour of later evaluation 2023-06-07 13:58:56 +02:00
Stephan Brandauer
2e16b71215 Java: update qldoc of ClassQualifierCharacteristic 2023-06-07 13:52:57 +02:00
Stephan Brandauer
1bfbfec1bc Java: use problem.severity in automodel extraction queries 2023-06-07 13:44:52 +02:00
Stephan Brandauer
5de56db3af Java: QlDoc for isKnownKind 2023-05-31 14:13:14 +02:00
Stephan Brandauer
03051dde7f Java: spelling 2023-05-31 14:13:14 +02:00
Taus
ea5c36491b Java: Improve documentation of sampling strategy 2023-05-31 11:39:54 +00:00
Stephan Brandauer
5a9d09c49e Java: docs update
Co-authored-by: Aditya Sharad <6874315+adityasharad@users.noreply.github.com>
2023-05-31 13:36:58 +02:00
Stephan Brandauer
12ea5e0e90 Java: fix sanitizer bug 2023-05-31 11:53:02 +02:00
Stephan Brandauer
86559317d7 Java: update comments 2023-05-31 11:52:26 +02:00
Stephan Brandauer
96bae2d5ec Java: avoid downcasting to DollarAtString 2023-05-31 10:41:52 +02:00
Taus
73aa790cdd Java: Improve sampling strategy
Instead of the "random" sampling used before (which could -- in rare circumstances -- end up sampling fewer points than we want) we now sample an equally distributed set of points.
2023-05-30 11:22:26 +00:00
Stephan Brandauer
d4b964c849 add support for sanitizers 2023-05-30 10:25:52 +02:00
Taus
227c5fab40 Java: Get location ordering without toString 2023-05-26 14:52:08 +00:00
Stephan Brandauer
efe539eb32 Java: better sampling of negative examples 2023-05-26 14:15:32 +02:00
Stephan Brandauer
a89378d86d Java: add extra known frameworks and sample negative samples to manage sarif file sizes 2023-05-26 13:20:04 +02:00
Stephan Brandauer
5ca2221097 remove some of the biggest frameworks from application mode consideration 2023-05-25 17:06:02 +02:00
Stephan Brandauer
db77c6b9a3 Java: mark functional expressions as likely not sinks 2023-05-25 16:39:27 +02:00
Stephan Brandauer
76d731a61d improve CannotBeTaintedCharacteristic 2023-05-25 16:28:07 +02:00
Stephan Brandauer
9a041243ff Java: fine-tune characteristics 2023-05-25 14:16:32 +02:00
Stephan Brandauer
f224a40dec Java: use containing call as call context, not argument 2023-05-25 14:16:23 +02:00
Stephan Brandauer
33fdb0fc52 Java: remove superfluous characteristic 2023-05-25 14:16:23 +02:00
Taus
2000f22533 Java: Port over characteristics from codex branch 2023-05-25 14:16:23 +02:00
Taus
11ab7e2e71 Java: Share argument indexing logic
Adds a utility predicate for turning integer indices into the desired string representation.
2023-05-25 14:16:23 +02:00
Taus
04b8bf35d4 Java: Avoid overlapping import
Importing `AutomodelEndpointTypes` inside `AutomodelSharedUtil` non-privately made it overlap with the imports in the candidate extraction queries.
2023-05-25 14:16:23 +02:00
Stephan Brandauer
db61a2d099 Java: share isKnownKind between modes 2023-05-25 14:16:16 +02:00
Stephan Brandauer
d93ad9b398 Java: remove unneeded abstract metadata extractor classes and fix some names 2023-05-25 14:16:11 +02:00
Stephan Brandauer
6e21f14c09 Java: update extraction query metadata 2023-05-25 14:16:03 +02:00
Stephan Brandauer
7c3bc26c41 Java: make input an actual string, not an integer 2023-05-25 14:15:59 +02:00
Stephan Brandauer
185ad101b3 Java: add application-mode and framework-mode tags to extraction queries 2023-05-25 14:15:50 +02:00
Taus
9b30f9a476 Java: Add negative characteristic for static calls 2023-05-25 14:15:49 +02:00
Taus
6fc16574b3 Java: Add QL support for automodel application mode 2023-05-25 14:15:49 +02:00
85 changed files with 6972 additions and 2335 deletions

View File

@@ -37,13 +37,13 @@ private class MyConsistencyConfiguration extends ConsistencyConfiguration {
}
override predicate postWithInFlowExclude(Node n) {
n instanceof SummaryNode
n instanceof FlowSummaryNode
or
n.asExpr().(ObjectCreation).hasInitializer()
}
override predicate argHasPostUpdateExclude(ArgumentNode n) {
n instanceof SummaryNode
n instanceof FlowSummaryNode
or
not exists(LocalFlow::getAPostUpdateNodeForArg(n.getControlFlowNode()))
or

View File

@@ -40,7 +40,7 @@ extensions:
- ["System.Collections.Generic", "LinkedList<>", False, "FindLast", "(T)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Generic", "LinkedList<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.LinkedList<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "AddRange", "(System.Collections.Generic.IEnumerable<T>)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "AsReadOnly", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "AsReadOnly", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Find", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Find", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "FindAll", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
@@ -48,10 +48,8 @@ extensions:
- ["System.Collections.Generic", "List<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.List<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "InsertRange", "(System.Int32,System.Collections.Generic.IEnumerable<T>)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "List<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "Queue<>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "Queue<>", False, "CopyTo", "(T[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System.Collections.Generic", "Queue<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.Queue<>+Enumerator.Current]", "value", "manual"]
@@ -79,7 +77,7 @@ extensions:
- ["System.Collections.Generic", "SortedList<,>+KeyList", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "SortedList<,>+ValueList", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "SortedSet<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.SortedSet<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Generic", "SortedSet<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "SortedSet<>", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Generic", "Stack<>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Generic", "Stack<>", False, "CopyTo", "(T[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System.Collections.Generic", "Stack<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.Stack<>+Enumerator.Current]", "value", "manual"]

View File

@@ -20,7 +20,6 @@ extensions:
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "AddRange<>", "(System.Collections.Immutable.ImmutableArray<TDerived>+Builder)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "AddRange<>", "(TDerived[])", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableArray<>+Builder", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableDictionary<,>", False, "Add", "(TKey,TValue)", "", "Argument[0]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
@@ -49,11 +48,11 @@ extensions:
- ["System.Collections.Immutable", "ImmutableList<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Insert", "(System.Int32,T)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "InsertRange", "(System.Int32,System.Collections.Generic.IEnumerable<T>)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "AddRange", "(System.Collections.Generic.IEnumerable<T>)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "Find", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
@@ -63,10 +62,8 @@ extensions:
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "Argument[0].Parameter[0]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "FindLast", "(System.Predicate<T>)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "InsertRange", "(System.Int32,System.Collections.Generic.IEnumerable<T>)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableList<>+Builder", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableQueue<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableQueue<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedDictionary<,>", False, "Add", "(System.Collections.Generic.KeyValuePair<TKey,TValue>)", "", "Argument[0].Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
@@ -85,8 +82,8 @@ extensions:
- ["System.Collections.Immutable", "ImmutableSortedDictionary<,>+Builder", False, "get_Values", "()", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "Add", "(T)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>", False, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>+Builder", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current]", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>+Builder", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableSortedSet<>+Builder", False, "Reverse", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Immutable", "ImmutableStack<>", False, "GetEnumerator", "()", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.Immutable.ImmutableStack<>+Enumerator.Current]", "value", "manual"]

View File

@@ -9,7 +9,7 @@ extensions:
- ["System.Collections.Specialized", "NameValueCollection", False, "Add", "(System.Collections.Specialized.NameValueCollection)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Specialized", "NameValueCollection", True, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections.Specialized", "NameValueCollection", False, "CopyTo", "(System.Array,System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System.Collections.Specialized", "OrderedDictionary", False, "AsReadOnly", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Specialized", "OrderedDictionary", False, "AsReadOnly", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections.Specialized", "StringCollection", False, "Add", "(System.String)", "", "Argument[0]", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Specialized", "StringCollection", False, "AddRange", "(System.String[])", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections.Specialized", "StringCollection", False, "CopyTo", "(System.String[],System.Int32)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]

View File

@@ -4,17 +4,15 @@ extensions:
extensible: summaryModel
data:
- ["System.Collections", "ArrayList", False, "AddRange", "(System.Collections.ICollection)", "", "Argument[0].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "FixedSize", "(System.Collections.ArrayList)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "FixedSize", "(System.Collections.IList)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "GetEnumerator", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Property[System.Collections.IEnumerator.Current]", "value", "manual"]
- ["System.Collections", "ArrayList", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "GetRange", "(System.Int32,System.Int32)", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "InsertRange", "(System.Int32,System.Collections.ICollection)", "", "Argument[1].Element", "Argument[this].Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Repeat", "(System.Object,System.Int32)", "", "Argument[0]", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "ArrayList", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "BitArray", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "BitArray", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Hashtable", "(System.Collections.IDictionary)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Hashtable", "(System.Collections.IDictionary)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
- ["System.Collections", "Hashtable", False, "Hashtable", "(System.Collections.IDictionary,System.Collections.IEqualityComparer)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
@@ -43,9 +41,9 @@ extensions:
- ["System.Collections", "IList", True, "get_Item", "(System.Int32)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections", "IList", True, "set_Item", "(System.Int32,System.Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Collections", "Queue", True, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections", "Queue", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Queue", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Queue", False, "Peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections", "SortedList", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "SortedList", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "SortedList", False, "GetByIndex", "(System.Int32)", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue", "value", "manual"]
- ["System.Collections", "SortedList", False, "GetValueList", "()", "", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "SortedList", False, "SortedList", "(System.Collections.IDictionary)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
@@ -53,6 +51,6 @@ extensions:
- ["System.Collections", "SortedList", False, "SortedList", "(System.Collections.IDictionary,System.Collections.IComparer)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key]", "value", "manual"]
- ["System.Collections", "SortedList", False, "SortedList", "(System.Collections.IDictionary,System.Collections.IComparer)", "", "Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value]", "value", "manual"]
- ["System.Collections", "Stack", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Collections", "Stack", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Stack", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Collections", "Stack", False, "Peek", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Collections", "Stack", False, "Pop", "()", "", "Argument[this].Element", "ReturnValue", "value", "manual"]

View File

@@ -58,7 +58,7 @@ extensions:
- ["System.Data", "IDataParameterCollection", True, "set_Item", "(System.String,System.Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Data", "ITableMappingCollection", True, "get_Item", "(System.String)", "", "Argument[this].Element", "ReturnValue", "value", "manual"]
- ["System.Data", "ITableMappingCollection", True, "set_Item", "(System.String,System.Object)", "", "Argument[1]", "Argument[this].Element", "value", "manual"]
- ["System.Data", "PropertyCollection", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Data", "PropertyCollection", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Data", "TypedTableBaseExtensions", False, "AsEnumerable<>", "(System.Data.TypedTableBase<TRow>)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Data", "TypedTableBaseExtensions", False, "ElementAtOrDefault<>", "(System.Data.TypedTableBase<TRow>,System.Int32)", "", "Argument[0].Element", "ReturnValue", "value", "manual"]
- ["System.Data", "TypedTableBaseExtensions", False, "OrderBy<,>", "(System.Data.TypedTableBase<TRow>,System.Func<TRow,TKey>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]

View File

@@ -6,6 +6,4 @@ extensions:
- ["System.Runtime.CompilerServices", "ConditionalWeakTable<,>", False, "Clear", "()", "", "Argument[this].WithoutElement", "Argument[this]", "value", "manual"]
- ["System.Runtime.CompilerServices", "ConfiguredTaskAwaitable<>", False, "GetAwaiter", "()", "", "Argument[this].SyntheticField[m_configuredTaskAwaiter]", "ReturnValue", "value", "manual"]
- ["System.Runtime.CompilerServices", "ConfiguredTaskAwaitable<>+ConfiguredTaskAwaiter", False, "GetResult", "()", "", "Argument[this].SyntheticField[m_task_configured_task_awaitable].Property[System.Threading.Tasks.Task<>.Result]", "ReturnValue", "value", "manual"]
- ["System.Runtime.CompilerServices", "ReadOnlyCollectionBuilder<>", False, "Reverse", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Runtime.CompilerServices", "ReadOnlyCollectionBuilder<>", False, "Reverse", "(System.Int32,System.Int32)", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System.Runtime.CompilerServices", "TaskAwaiter<>", False, "GetResult", "()", "", "Argument[this].SyntheticField[m_task_task_awaiter].Property[System.Threading.Tasks.Task<>.Result]", "ReturnValue", "value", "manual"]

View File

@@ -13,7 +13,7 @@ extensions:
- ["System", "Array", False, "AsReadOnly<>", "(T[])", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System", "Array", False, "Clear", "(System.Array)", "", "Argument[0].WithoutElement", "Argument[0]", "value", "manual"]
- ["System", "Array", False, "Clear", "(System.Array,System.Int32,System.Int32)", "", "Argument[0].WithoutElement", "Argument[0]", "value", "manual"]
- ["System", "Array", False, "Clone", "()", "", "Argument[0].Element", "ReturnValue.Element", "value", "manual"]
- ["System", "Array", False, "Clone", "()", "", "Argument[this].Element", "ReturnValue.Element", "value", "manual"]
- ["System", "Array", False, "CopyTo", "(System.Array,System.Int64)", "", "Argument[this].Element", "Argument[0].Element", "value", "manual"]
- ["System", "Array", False, "Find<>", "(T[],System.Predicate<T>)", "", "Argument[0].Element", "Argument[1].Parameter[0]", "value", "manual"]
- ["System", "Array", False, "Find<>", "(T[],System.Predicate<T>)", "", "Argument[0].Element", "ReturnValue", "value", "manual"]

View File

@@ -128,7 +128,9 @@ private module Cached {
// No need to include calls that are compiled from source
not call.getImplementation().getMethod().compiledFromSource()
} or
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
TSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -472,12 +474,12 @@ class CilDataFlowCall extends DataFlowCall, TCilCall {
*/
class SummaryCall extends DelegateDataFlowCall, TSummaryCall {
private FlowSummaryImpl::Public::SummarizedCallable c;
private Node receiver;
private FlowSummaryImpl::Private::SummaryNode receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
Node getReceiver() { result = receiver }
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
override DataFlowCallable getARuntimeTarget() {
none() // handled by the shared library

View File

@@ -500,7 +500,7 @@ module LocalFlow {
* inter-procedurality or field-sensitivity.
*/
predicate excludeFromExposedRelations(Node n) {
n instanceof SummaryNode or
n instanceof FlowSummaryNode or
n instanceof ImplicitCapturedArgumentNode
}
@@ -559,7 +559,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
or
LocalFlow::localFlowCapturedVarStep(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
or
nodeTo.(ObjectCreationNode).getPreUpdateNode() = nodeFrom.(ObjectInitializerNode)
}
@@ -805,7 +806,8 @@ private module Cached {
// Add artificial dependencies to enforce all cached predicates are evaluated
// in the "DataFlowImplCommon stage"
private predicate forceCaching() {
cached
predicate forceCaching() {
TaintTrackingPrivate::forceCachingInSameStage() or
exists(any(NodeImpl n).getTypeImpl()) or
exists(any(NodeImpl n).getControlFlowNodeImpl()) or
@@ -815,10 +817,7 @@ private module Cached {
cached
newtype TNode =
TExprNode(ControlFlow::Nodes::ElementNode cfn) {
forceCaching() and
cfn.getElement() instanceof Expr
} or
TExprNode(ControlFlow::Nodes::ElementNode cfn) { cfn.getElement() instanceof Expr } or
TCilExprNode(CIL::Expr e) { e.getImplementation() instanceof CIL::BestImplementation } or
TCilSsaDefinitionExtNode(CilSsaImpl::DefinitionExt def) or
TSsaDefinitionExtNode(SsaImpl::DefinitionExt def) {
@@ -867,12 +866,7 @@ private module Cached {
)
)
} or
TSummaryNode(DataFlowSummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(DataFlowSummarizedCallable c, ParameterPosition pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TParamsArgumentNode(ControlFlow::Node callCfn) {
callCfn = any(Call c | isParamsArg(c, _, _)).getAControlFlowNode()
}
@@ -977,9 +971,7 @@ predicate nodeIsHidden(Node n) {
or
n instanceof MallocNode
or
n instanceof SummaryNode
or
n instanceof SummaryParameterNode
n instanceof FlowSummaryNode
or
n instanceof ParamsArgumentNode
or
@@ -1132,29 +1124,16 @@ private module ParameterNodes {
}
/** A parameter for a library callable with a flow summary. */
class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
private FlowSummaryImpl::Public::SummarizedCallable sc;
class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode {
private ParameterPosition pos_;
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_)
}
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
sc = c.asSummarizedCallable() and pos = pos_
this.getSummarizedCallable() = c.asSummarizedCallable() and pos = pos_
}
override DataFlowCallable getEnclosingCallableImpl() { result.asSummarizedCallable() = sc }
override Type getTypeImpl() {
exists(int i | pos_.getPosition() = i and result = sc.getParameter(i).getType())
or
pos_.isThisParameter() and result = sc.getDeclaringType()
}
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override EmptyLocation getLocationImpl() { any() }
override string toStringImpl() { result = "parameter " + pos_ + " of " + sc }
}
}
@@ -1323,11 +1302,16 @@ private module ArgumentNodes {
override string toStringImpl() { result = "[implicit array creation] " + callCfn }
}
private class SummaryArgumentNode extends SummaryNode, ArgumentNodeImpl {
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNodeImpl {
private DataFlowCall call_;
private ArgumentPosition pos_;
SummaryArgumentNode() {
FlowSummaryImpl::Private::summaryArgumentNode(call_, this.getSummaryNode(), pos_)
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
call = call_ and pos = pos_
}
}
}
@@ -1469,11 +1453,11 @@ private module ReturnNodes {
}
}
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() {
FlowSummaryImpl::Private::summaryReturnNode(this, rk) and
FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) and
not rk instanceof JumpReturnKind
or
exists(Parameter p, int pos |
@@ -1494,9 +1478,9 @@ private module ReturnNodes {
* Holds if summary node `n` is a post-update node for `out`/`ref` parameter `p`.
* In this case we adjust it to instead be a return node.
*/
private predicate summaryPostUpdateNodeIsOutOrRef(SummaryNode n, Parameter p) {
exists(ParameterNodeImpl pn, DataFlowCallable c, ParameterPosition pos |
FlowSummaryImpl::Private::summaryPostUpdateNode(n, pn) and
private predicate summaryPostUpdateNodeIsOutOrRef(FlowSummaryNode n, Parameter p) {
exists(SummaryParameterNode pn, DataFlowCallable c, ParameterPosition pos |
FlowSummaryImpl::Private::summaryPostUpdateNode(n.getSummaryNode(), pn.getSummaryNode()) and
pn.isParameterOf(c, pos) and
p = c.asSummarizedCallable().getParameter(pos.getPosition()) and
p.isOutOrRef()
@@ -1609,37 +1593,43 @@ private module OutNodes {
}
}
private class SummaryOutNode extends SummaryNode, OutNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
private class SummaryOutNode extends FlowSummaryNode, OutNode {
private DataFlowCall call;
private ReturnKind kind_;
override DataFlowCall getCall(ReturnKind kind) {
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
SummaryOutNode() {
FlowSummaryImpl::Private::summaryOutNode(call, this.getSummaryNode(), kind_)
}
override DataFlowCall getCall(ReturnKind kind) { result = call and kind = kind_ }
}
}
import OutNodes
/** A data-flow node used to model flow summaries. */
class SummaryNode extends NodeImpl, TSummaryNode {
private FlowSummaryImpl::Public::SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
class FlowSummaryNode extends NodeImpl, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
SummaryNode() { this = TSummaryNode(c, state) }
FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override DataFlowCallable getEnclosingCallableImpl() { result.asSummarizedCallable() = c }
override DataFlowCallable getEnclosingCallableImpl() {
result.asSummarizedCallable() = this.getSummarizedCallable()
}
override DataFlowType getDataFlowType() {
result = FlowSummaryImpl::Private::summaryNodeType(this)
result = FlowSummaryImpl::Private::summaryNodeType(this.getSummaryNode())
}
override DotNet::Type getTypeImpl() { none() }
override ControlFlow::Node getControlFlowNodeImpl() { none() }
override Location getLocationImpl() { result = c.getLocation() }
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
override string toStringImpl() { result = "[summary] " + state + " in " + c }
override string toStringImpl() { result = this.getSummaryNode().toString() }
}
/** A field or a property. */
@@ -1719,12 +1709,13 @@ predicate jumpStep(Node pred, Node succ) {
)
or
exists(JumpReturnKind jrk, NonDelegateDataFlowCall call |
FlowSummaryImpl::Private::summaryReturnNode(pred, jrk) and
FlowSummaryImpl::Private::summaryReturnNode(pred.(FlowSummaryNode).getSummaryNode(), jrk) and
jrk.getTarget() = call.getATarget(_) and
succ = getAnOutNode(call, jrk.getTargetReturnKind())
)
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred, succ)
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred.(FlowSummaryNode).getSummaryNode(),
succ.(FlowSummaryNode).getSummaryNode())
}
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -1784,7 +1775,8 @@ predicate storeStep(Node node1, Content c, Node node2) {
c = getResultContent()
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
private class ReadStepConfiguration extends ControlFlowReachabilityConfiguration {
@@ -1907,7 +1899,8 @@ predicate readStep(Node node1, Content c, Node node2) {
)
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -1920,7 +1913,7 @@ predicate clearsContent(Node n, Content c) {
or
fieldOrPropertyStore(_, c, _, n.(ObjectInitializerNode).getInitializer(), false)
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
or
exists(WithExpr we, ObjectInitializer oi, FieldOrProperty f |
oi = we.getInitializer() and
@@ -1935,7 +1928,7 @@ predicate clearsContent(Node n, Content c) {
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
/**
@@ -2130,15 +2123,15 @@ private module PostUpdateNodes {
override string toStringImpl() { result = "[post] " + cfn.toString() }
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
private FlowSummaryImpl::Private::SummaryNode preUpdateNode;
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this, _) and
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), preUpdateNode) and
not summaryPostUpdateNodeIsOutOrRef(this, _)
}
override Node getPreUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this, result)
}
override Node getPreUpdateNode() { result.(FlowSummaryNode).getSummaryNode() = preUpdateNode }
}
}
@@ -2233,7 +2226,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
call.getControlFlowNode())
)
or
receiver = call.(SummaryCall).getReceiver()
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver()
) and
exists(kind)
}

View File

@@ -505,6 +505,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +533,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +562,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +613,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +621,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +644,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +659,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +667,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +675,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +688,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +703,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +716,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +737,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +749,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +764,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +773,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +787,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +799,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +816,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +842,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +854,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +866,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +893,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +905,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +915,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +937,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +962,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1001,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1016,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1029,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1043,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1411,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1424,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1444,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -24,11 +24,8 @@ DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() =
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(Node receiver) { receiver = result.getReceiver() }
SummaryCall summaryDataFlowCall(SummaryNode receiver) { receiver = result.getReceiver() }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) {
@@ -44,6 +41,19 @@ DataFlowType getContentType(Content c) {
)
}
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) {
exists(Type t | result = Gvn::getGlobalValueNumber(t) |
exists(int i |
pos.getPosition() = i and
t = c.getParameter(i).getType()
)
or
pos.isThisParameter() and
t = c.getDeclaringType()
)
}
private DataFlowType getReturnTypeBase(DotNet::Callable c, ReturnKind rk) {
exists(Type t | result = Gvn::getGlobalValueNumber(t) |
rk instanceof NormalReturnKind and

View File

@@ -156,7 +156,8 @@ private module Cached {
// tracking configurations where the source is a collection
readStep(nodeFrom, TElementContent(), nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false)
or
nodeTo = nodeFrom.(DataFlow::NonLocalJumpNode).getAJumpSuccessor(false)
}

View File

@@ -1,5 +1,3 @@
// semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs /r:System.Threading.Tasks.dll /r:System.Collections.Specialized.dll /r:System.Runtime.dll /r:System.Private.Uri.dll
using System;
using System.Threading.Tasks;
using System.Web.Mvc;
@@ -38,21 +36,3 @@ namespace RequestForgery.Controllers
}
}
}
// Missing stubs:
namespace System.Net.Http
{
public class HttpClient
{
public async Task SendAsync(HttpRequestMessage request) => throw null;
}
public class HttpRequestMessage
{
public HttpRequestMessage(HttpMethod method, string requestUri) => throw null;
}
public class HttpMethod
{
public static readonly HttpMethod Get;
}
}

View File

@@ -1,8 +1,8 @@
edges
| RequestForgery.cs:14:52:14:54 | url : String | RequestForgery.cs:16:66:16:68 | access to parameter url |
| RequestForgery.cs:12:52:12:54 | url : String | RequestForgery.cs:14:66:14:68 | access to parameter url |
nodes
| RequestForgery.cs:14:52:14:54 | url : String | semmle.label | url : String |
| RequestForgery.cs:16:66:16:68 | access to parameter url | semmle.label | access to parameter url |
| RequestForgery.cs:12:52:12:54 | url : String | semmle.label | url : String |
| RequestForgery.cs:14:66:14:68 | access to parameter url | semmle.label | access to parameter url |
subpaths
#select
| RequestForgery.cs:16:66:16:68 | access to parameter url | RequestForgery.cs:14:52:14:54 | url : String | RequestForgery.cs:16:66:16:68 | access to parameter url | The URL of this request depends on a $@. | RequestForgery.cs:14:52:14:54 | url | user-provided value |
| RequestForgery.cs:14:66:14:68 | access to parameter url | RequestForgery.cs:12:52:12:54 | url : String | RequestForgery.cs:14:66:14:68 | access to parameter url | The URL of this request depends on a $@. | RequestForgery.cs:12:52:12:54 | url | user-provided value |

View File

@@ -0,0 +1,3 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../resources/stubs/_frameworks/Microsoft.NETCore.App/Microsoft.NETCore.App.csproj
semmle-extractor-options: ${testdir}/../../resources/stubs/System.Web.cs

View File

@@ -51,5 +51,5 @@ viableLambda
| DelegateFlow.cs:125:9:125:25 | function pointer call | file://:0:0:0:0 | (none) | DelegateFlow.cs:7:17:7:18 | M2 |
| DelegateFlow.cs:132:9:132:11 | delegate call | DelegateFlow.cs:135:25:135:40 | call to method M19 | DelegateFlow.cs:135:29:135:36 | (...) => ... |
| DelegateFlow.cs:132:9:132:11 | delegate call | file://:0:0:0:0 | (none) | DelegateFlow.cs:131:17:131:24 | (...) => ... |
| file://:0:0:0:0 | [summary] call to parameter position 0 of Lazy in Lazy | DelegateFlow.cs:105:9:105:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:104:23:104:30 | (...) => ... |
| file://:0:0:0:0 | [summary] call to parameter position 0 of Lazy in Lazy | DelegateFlow.cs:107:9:107:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:106:13:106:20 | (...) => ... |
| file://:0:0:0:0 | [summary] call to [summary param] position 0 in Lazy in Lazy | DelegateFlow.cs:105:9:105:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:104:23:104:30 | (...) => ... |
| file://:0:0:0:0 | [summary] call to [summary param] position 0 in Lazy in Lazy | DelegateFlow.cs:107:9:107:24 | object creation of type Lazy<Int32> | DelegateFlow.cs:106:13:106:20 | (...) => ... |

View File

@@ -1087,7 +1087,7 @@ summary
| System.Collections.Generic;List<>;false;Add;(System.Object);;Argument[0];Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;Add;(T);;Argument[0];Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;AddRange;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;AsReadOnly;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;AsReadOnly;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections.Generic;List<>;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections.Generic;List<>;false;CopyTo;(T[]);;Argument[this];Argument[0].Element;taint;df-generated |
@@ -1101,13 +1101,11 @@ summary
| System.Collections.Generic;List<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual |
| System.Collections.Generic;List<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.List<>+Enumerator.Current];value;manual |
| System.Collections.Generic;List<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections.Generic;List<>;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;Insert;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;InsertRange;(System.Int32,System.Collections.Generic.IEnumerable<T>);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;List;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Generic;List<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections.Generic;List<>;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections.Generic;List<>;false;set_Item;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
@@ -1231,7 +1229,7 @@ summary
| System.Collections.Generic;SortedSet<>;false;GetViewBetween;(T,T);;Argument[1];ReturnValue;taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;GetViewBetween;(T,T);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;IntersectWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;SortedSet<>;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;SortedSet<>;false;SortedSet;(System.Collections.Generic.IComparer<T>);;Argument[0];Argument[this];taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;SortedSet;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[0];Argument[this];taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
@@ -1290,7 +1288,6 @@ summary
| System.Collections.Immutable;ImmutableArray<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;MoveToImmutable;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;set_Item;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableArray<>+Enumerator;false;get_Current;();;Argument[this];ReturnValue;taint;df-generated |
@@ -1487,12 +1484,10 @@ summary
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;Insert;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;InsertRange;(System.Int32,System.Collections.Generic.IEnumerable<T>);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;ToImmutable;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>+Builder;false;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;get_SyncRoot;();;Argument[this];ReturnValue;taint;df-generated |
@@ -1520,7 +1515,7 @@ summary
| System.Collections.Immutable;ImmutableList<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Insert;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;InsertRange;(System.Int32,System.Collections.Generic.IEnumerable<T>);;Argument[1].Element;Argument[this].Element;value;manual |
@@ -1537,8 +1532,8 @@ summary
| System.Collections.Immutable;ImmutableList<>;false;Replace;(T,T,System.Collections.Generic.IEqualityComparer<T>);;Argument[1];Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;Replace;(T,T,System.Collections.Generic.IEqualityComparer<T>);;Argument[1];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;Replace;(T,T,System.Collections.Generic.IEqualityComparer<T>);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;SetItem;(System.Int32,T);;Argument[1];Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;SetItem;(System.Int32,T);;Argument[1];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;SetItem;(System.Int32,T);;Argument[this];ReturnValue;taint;df-generated |
@@ -1676,7 +1671,7 @@ summary
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;IntersectWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;ToImmutable;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;TryGetValue;(T,T);;Argument[0];ReturnValue;taint;df-generated |
@@ -1703,7 +1698,7 @@ summary
| System.Collections.Immutable;ImmutableSortedSet<>;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Intersect;(System.Collections.Generic.IEnumerable<T>);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Remove;(T);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>;false;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);;Argument[this];ReturnValue;taint;df-generated |
@@ -1897,7 +1892,7 @@ summary
| System.Collections.Specialized;NotifyCollectionChangedEventArgs;false;get_OldItems;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Specialized;OrderedDictionary;false;Add;(System.Object,System.Object);;Argument[0];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual |
| System.Collections.Specialized;OrderedDictionary;false;Add;(System.Object,System.Object);;Argument[1];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual |
| System.Collections.Specialized;OrderedDictionary;false;AsReadOnly;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Specialized;OrderedDictionary;false;AsReadOnly;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Specialized;OrderedDictionary;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections.Specialized;OrderedDictionary;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections.Specialized;OrderedDictionary;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
@@ -1938,21 +1933,19 @@ summary
| System.Collections;ArrayList;false;AddRange;(System.Collections.ICollection);;Argument[0].Element;Argument[this].Element;value;manual |
| System.Collections;ArrayList;false;ArrayList;(System.Collections.ICollection);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections;ArrayList;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;ArrayList;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;CopyTo;(System.Array);;Argument[this];Argument[0].Element;taint;df-generated |
| System.Collections;ArrayList;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections;ArrayList;false;FixedSize;(System.Collections.ArrayList);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;FixedSize;(System.Collections.IList);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections;ArrayList;false;GetEnumerator;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections;ArrayList;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Insert;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections;ArrayList;false;InsertRange;(System.Int32,System.Collections.ICollection);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections;ArrayList;false;ReadOnly;(System.Collections.ArrayList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;ReadOnly;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;Repeat;(System.Object,System.Int32);;Argument[0];ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;SetRange;(System.Int32,System.Collections.ICollection);;Argument[1].Element;Argument[this];taint;df-generated |
| System.Collections;ArrayList;false;Synchronized;(System.Collections.ArrayList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;Synchronized;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated |
@@ -1960,7 +1953,7 @@ summary
| System.Collections;ArrayList;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections;ArrayList;false;set_Item;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections;BitArray;false;And;(System.Collections.BitArray);;Argument[this];ReturnValue;value;df-generated |
| System.Collections;BitArray;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;BitArray;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;BitArray;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections;BitArray;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections;BitArray;false;LeftShift;(System.Int32);;Argument[this];ReturnValue;value;df-generated |
@@ -2007,7 +2000,7 @@ summary
| System.Collections;Hashtable;false;Add;(System.Object,System.Object);;Argument[0];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual |
| System.Collections;Hashtable;false;Add;(System.Object,System.Object);;Argument[1];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual |
| System.Collections;Hashtable;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;Hashtable;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;Hashtable;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;Hashtable;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections;Hashtable;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections;Hashtable;false;GetEnumerator;();;Argument[this];ReturnValue;taint;df-generated |
@@ -2055,7 +2048,7 @@ summary
| System.Collections;IList;true;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections;IList;true;set_Item;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections;Queue;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;Queue;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;Queue;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;Queue;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections;Queue;false;Dequeue;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;Queue;false;Enqueue;(System.Object);;Argument[0];Argument[this];taint;df-generated |
@@ -2071,7 +2064,7 @@ summary
| System.Collections;SortedList;false;Add;(System.Object,System.Object);;Argument[0];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual |
| System.Collections;SortedList;false;Add;(System.Object,System.Object);;Argument[1];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual |
| System.Collections;SortedList;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;SortedList;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;SortedList;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;SortedList;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections;SortedList;false;GetByIndex;(System.Int32);;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];ReturnValue;value;manual |
| System.Collections;SortedList;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
@@ -2093,7 +2086,7 @@ summary
| System.Collections;SortedList;false;set_Item;(System.Object,System.Object);;Argument[0];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual |
| System.Collections;SortedList;false;set_Item;(System.Object,System.Object);;Argument[1];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];value;manual |
| System.Collections;Stack;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;Stack;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;Stack;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;Stack;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Collections;Stack;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections;Stack;false;Peek;();;Argument[this].Element;ReturnValue;value;manual |
@@ -3090,7 +3083,7 @@ summary
| System.Data;InternalDataCollectionBase;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System.Data;InternalDataCollectionBase;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Data;InternalDataCollectionBase;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Data;PropertyCollection;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Data;PropertyCollection;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Data;TypedTableBase<>;false;Cast<>;();;Argument[this];ReturnValue;taint;df-generated |
| System.Data;TypedTableBase<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual |
| System.Data;TypedTableBase<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
@@ -7346,8 +7339,6 @@ summary
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;Insert;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;ReadOnlyCollectionBuilder;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;set_Item;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
@@ -10702,7 +10693,7 @@ summary
| System;Array;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System;Array;false;Clear;(System.Array);;Argument[0].WithoutElement;Argument[0];value;manual |
| System;Array;false;Clear;(System.Array,System.Int32,System.Int32);;Argument[0].WithoutElement;Argument[0];value;manual |
| System;Array;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System;Array;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System;Array;false;CopyTo;(System.Array,System.Int32);;Argument[this].Element;Argument[0].Element;value;manual |
| System;Array;false;CopyTo;(System.Array,System.Int64);;Argument[this].Element;Argument[0].Element;value;manual |
| System;Array;false;Fill<>;(T[],T);;Argument[1];Argument[0].Element;taint;df-generated |

View File

@@ -707,7 +707,7 @@ summary
| System.Collections.Generic;LinkedListNode<>;false;set_Value;(T);;Argument[0];Argument[this];taint;df-generated |
| System.Collections.Generic;List<>+Enumerator;false;get_Current;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Generic;List<>;false;AddRange;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;AsReadOnly;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;AsReadOnly;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;CopyTo;(T[]);;Argument[this];Argument[0].Element;taint;df-generated |
| System.Collections.Generic;List<>;false;Find;(System.Predicate<T>);;Argument[this].Element;Argument[0].Parameter[0];value;manual |
| System.Collections.Generic;List<>;false;Find;(System.Predicate<T>);;Argument[this].Element;ReturnValue;value;manual |
@@ -716,11 +716,9 @@ summary
| System.Collections.Generic;List<>;false;FindLast;(System.Predicate<T>);;Argument[this].Element;Argument[0].Parameter[0];value;manual |
| System.Collections.Generic;List<>;false;FindLast;(System.Predicate<T>);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections.Generic;List<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.List<>+Enumerator.Current];value;manual |
| System.Collections.Generic;List<>;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;InsertRange;(System.Int32,System.Collections.Generic.IEnumerable<T>);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections.Generic;List<>;false;List;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Generic;List<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;List<>;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections.Generic;PriorityQueue<,>+UnorderedItemsCollection+Enumerator;false;get_Current;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Generic;PriorityQueue<,>+UnorderedItemsCollection;false;GetEnumerator;();;Argument[this];ReturnValue;taint;df-generated |
@@ -786,7 +784,7 @@ summary
| System.Collections.Generic;SortedSet<>;false;GetViewBetween;(T,T);;Argument[1];ReturnValue;taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;GetViewBetween;(T,T);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;IntersectWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;SortedSet<>;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Generic;SortedSet<>;false;SortedSet;(System.Collections.Generic.IComparer<T>);;Argument[0];Argument[this];taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;SortedSet;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[0];Argument[this];taint;df-generated |
| System.Collections.Generic;SortedSet<>;false;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
@@ -837,7 +835,6 @@ summary
| System.Collections.Immutable;ImmutableArray<>+Builder;false;AddRange<>;(TDerived[]);;Argument[0].Element;Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator<>.Current];value;manual |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;MoveToImmutable;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableArray<>+Builder;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableArray<>+Enumerator;false;get_Current;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableArray<>;false;Add;(T);;Argument[0];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableArray<>;false;AddRange;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue;taint;df-generated |
@@ -971,10 +968,8 @@ summary
| System.Collections.Immutable;ImmutableList<>+Builder;false;FindLast;(System.Predicate<T>);;Argument[this].Element;Argument[0].Parameter[0];value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;FindLast;(System.Predicate<T>);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;InsertRange;(System.Int32,System.Collections.Generic.IEnumerable<T>);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>+Builder;false;ToImmutable;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>+Builder;false;get_SyncRoot;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>+Enumerator;false;get_Current;();;Argument[this];ReturnValue;taint;df-generated |
@@ -992,7 +987,7 @@ summary
| System.Collections.Immutable;ImmutableList<>;false;FindLast;(System.Predicate<T>);;Argument[this].Element;Argument[0].Parameter[0];value;manual |
| System.Collections.Immutable;ImmutableList<>;false;FindLast;(System.Predicate<T>);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableList<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Insert;(System.Int32,T);;Argument[1];Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;InsertRange;(System.Int32,System.Collections.Generic.IEnumerable<T>);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Remove;(T);;Argument[this];ReturnValue;taint;df-generated |
@@ -1008,8 +1003,8 @@ summary
| System.Collections.Immutable;ImmutableList<>;false;Replace;(T,T,System.Collections.Generic.IEqualityComparer<T>);;Argument[1];Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;Replace;(T,T,System.Collections.Generic.IEqualityComparer<T>);;Argument[1];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;Replace;(T,T,System.Collections.Generic.IEqualityComparer<T>);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;Reverse;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableList<>;false;SetItem;(System.Int32,T);;Argument[1];Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;SetItem;(System.Int32,T);;Argument[1];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableList<>;false;SetItem;(System.Int32,T);;Argument[this];ReturnValue;taint;df-generated |
@@ -1106,7 +1101,7 @@ summary
| System.Collections.Immutable;ImmutableSortedSet;false;ToImmutableSortedSet<>;(System.Collections.Immutable.ImmutableSortedSet<TSource>+Builder);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;IntersectWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;SymmetricExceptWith;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;ToImmutable;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>+Builder;false;TryGetValue;(T,T);;Argument[0];ReturnValue;taint;df-generated |
@@ -1124,7 +1119,7 @@ summary
| System.Collections.Immutable;ImmutableSortedSet<>;false;GetEnumerator;();;Argument[this].Element;ReturnValue.Property[System.Collections.Immutable.ImmutableSortedSet<>+Enumerator.Current];value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Intersect;(System.Collections.Generic.IEnumerable<T>);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Remove;(T);;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>;false;Reverse;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Immutable;ImmutableSortedSet<>;false;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections.Immutable;ImmutableSortedSet<>;false;SymmetricExcept;(System.Collections.Generic.IEnumerable<T>);;Argument[this];ReturnValue;taint;df-generated |
@@ -1237,7 +1232,7 @@ summary
| System.Collections.Specialized;NotifyCollectionChangedEventArgs;false;NotifyCollectionChangedEventArgs;(System.Collections.Specialized.NotifyCollectionChangedAction,System.Object,System.Object,System.Int32);;Argument[2];Argument[this];taint;df-generated |
| System.Collections.Specialized;NotifyCollectionChangedEventArgs;false;get_NewItems;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Specialized;NotifyCollectionChangedEventArgs;false;get_OldItems;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections.Specialized;OrderedDictionary;false;AsReadOnly;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections.Specialized;OrderedDictionary;false;AsReadOnly;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections.Specialized;OrderedDictionary;false;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[this];Argument[0];taint;df-generated |
| System.Collections.Specialized;OrderedDictionary;false;OrderedDictionary;(System.Int32,System.Collections.IEqualityComparer);;Argument[1];Argument[this];taint;df-generated |
| System.Collections.Specialized;OrderedDictionary;false;OrderedDictionary;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[0];Argument[this];taint;df-generated |
@@ -1258,24 +1253,22 @@ summary
| System.Collections;ArrayList;false;Adapter;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;AddRange;(System.Collections.ICollection);;Argument[0].Element;Argument[this].Element;value;manual |
| System.Collections;ArrayList;false;ArrayList;(System.Collections.ICollection);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Collections;ArrayList;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;CopyTo;(System.Array);;Argument[this];Argument[0].Element;taint;df-generated |
| System.Collections;ArrayList;false;FixedSize;(System.Collections.ArrayList);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;FixedSize;(System.Collections.IList);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;GetEnumerator;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Property[System.Collections.IEnumerator.Current];value;manual |
| System.Collections;ArrayList;false;GetRange;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;GetRange;(System.Int32,System.Int32);;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;InsertRange;(System.Int32,System.Collections.ICollection);;Argument[1].Element;Argument[this].Element;value;manual |
| System.Collections;ArrayList;false;ReadOnly;(System.Collections.ArrayList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;ReadOnly;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;Repeat;(System.Object,System.Int32);;Argument[0];ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;ArrayList;false;SetRange;(System.Int32,System.Collections.ICollection);;Argument[1].Element;Argument[this];taint;df-generated |
| System.Collections;ArrayList;false;Synchronized;(System.Collections.ArrayList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;Synchronized;(System.Collections.IList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;ArrayList;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections;BitArray;false;And;(System.Collections.BitArray);;Argument[this];ReturnValue;value;df-generated |
| System.Collections;BitArray;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;BitArray;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;BitArray;false;LeftShift;(System.Int32);;Argument[this];ReturnValue;value;df-generated |
| System.Collections;BitArray;false;Not;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections;BitArray;false;Or;(System.Collections.BitArray);;Argument[this];ReturnValue;value;df-generated |
@@ -1300,7 +1293,7 @@ summary
| System.Collections;DictionaryEntry;false;get_Value;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;DictionaryEntry;false;set_Key;(System.Object);;Argument[0];Argument[this];taint;df-generated |
| System.Collections;DictionaryEntry;false;set_Value;(System.Object);;Argument[0];Argument[this];taint;df-generated |
| System.Collections;Hashtable;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;Hashtable;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;Hashtable;false;GetEnumerator;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;Hashtable;false;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[this];Argument[0];taint;df-generated |
| System.Collections;Hashtable;false;Hashtable;(System.Collections.IDictionary);;Argument[0].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Key];value;manual |
@@ -1341,7 +1334,7 @@ summary
| System.Collections;IList;true;get_Item;(System.Int32);;Argument[this].Element;ReturnValue;value;manual |
| System.Collections;IList;true;set_Item;(System.Int32,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Collections;Queue;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;Queue;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;Queue;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;Queue;false;Dequeue;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;Queue;false;Enqueue;(System.Object);;Argument[0];Argument[this];taint;df-generated |
| System.Collections;Queue;false;Peek;();;Argument[this].Element;ReturnValue;value;manual |
@@ -1350,7 +1343,7 @@ summary
| System.Collections;Queue;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections;ReadOnlyCollectionBase;false;get_InnerList;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;ReadOnlyCollectionBase;false;get_SyncRoot;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;SortedList;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;SortedList;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;SortedList;false;GetByIndex;(System.Int32);;Argument[this].Element.Property[System.Collections.Generic.KeyValuePair<,>.Value];ReturnValue;value;manual |
| System.Collections;SortedList;false;GetEnumerator;();;Argument[this];ReturnValue;taint;df-generated |
| System.Collections;SortedList;false;GetKey;(System.Int32);;Argument[this];ReturnValue;taint;df-generated |
@@ -1365,7 +1358,7 @@ summary
| System.Collections;SortedList;false;Synchronized;(System.Collections.SortedList);;Argument[0].Element;ReturnValue;taint;df-generated |
| System.Collections;SortedList;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Collections;Stack;false;Clear;();;Argument[this].WithoutElement;Argument[this];value;manual |
| System.Collections;Stack;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Collections;Stack;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Collections;Stack;false;Peek;();;Argument[this].Element;ReturnValue;value;manual |
| System.Collections;Stack;false;Pop;();;Argument[this].Element;ReturnValue;value;manual |
| System.Collections;Stack;false;Push;(System.Object);;Argument[0];Argument[this];taint;df-generated |
@@ -2244,7 +2237,7 @@ summary
| System.Data;ITableMappingCollection;true;get_Item;(System.String);;Argument[this].Element;ReturnValue;value;manual |
| System.Data;ITableMappingCollection;true;set_Item;(System.String,System.Object);;Argument[1];Argument[this].Element;value;manual |
| System.Data;InternalDataCollectionBase;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Data;PropertyCollection;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Data;PropertyCollection;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System.Data;TypedTableBase<>;false;Cast<>;();;Argument[this];ReturnValue;taint;df-generated |
| System.Data;TypedTableBaseExtensions;false;AsEnumerable<>;(System.Data.TypedTableBase<TRow>);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Data;TypedTableBaseExtensions;false;ElementAtOrDefault<>;(System.Data.TypedTableBase<TRow>,System.Int32);;Argument[0].Element;ReturnValue;value;manual |
@@ -6001,8 +5994,6 @@ summary
| System.Runtime.CompilerServices;PoolingAsyncValueTaskMethodBuilder<>;false;SetResult;(TResult);;Argument[0];Argument[this];taint;df-generated |
| System.Runtime.CompilerServices;PoolingAsyncValueTaskMethodBuilder<>;false;get_Task;();;Argument[this];ReturnValue;taint;df-generated |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;ReadOnlyCollectionBuilder;(System.Collections.Generic.IEnumerable<T>);;Argument[0].Element;Argument[this];taint;df-generated |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;Reverse;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;Reverse;(System.Int32,System.Int32);;Argument[0].Element;ReturnValue.Element;value;manual |
| System.Runtime.CompilerServices;ReadOnlyCollectionBuilder<>;false;get_SyncRoot;();;Argument[this];ReturnValue;value;df-generated |
| System.Runtime.CompilerServices;RuntimeWrappedException;false;GetObjectData;(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext);;Argument[this];Argument[0];taint;df-generated |
| System.Runtime.CompilerServices;RuntimeWrappedException;false;RuntimeWrappedException;(System.Object);;Argument[0];Argument[this];taint;df-generated |
@@ -9028,7 +9019,7 @@ summary
| System;Array;false;AsReadOnly<>;(T[]);;Argument[0].Element;ReturnValue.Element;value;manual |
| System;Array;false;Clear;(System.Array);;Argument[0].WithoutElement;Argument[0];value;manual |
| System;Array;false;Clear;(System.Array,System.Int32,System.Int32);;Argument[0].WithoutElement;Argument[0];value;manual |
| System;Array;false;Clone;();;Argument[0].Element;ReturnValue.Element;value;manual |
| System;Array;false;Clone;();;Argument[this].Element;ReturnValue.Element;value;manual |
| System;Array;false;CopyTo;(System.Array,System.Int64);;Argument[this].Element;Argument[0].Element;value;manual |
| System;Array;false;Fill<>;(T[],T);;Argument[1];Argument[0].Element;taint;df-generated |
| System;Array;false;Fill<>;(T[],T,System.Int32,System.Int32);;Argument[1];Argument[0].Element;taint;df-generated |

View File

@@ -135,21 +135,3 @@ namespace Test
}
}
}
namespace System.Net
{
public class HttpListenerResponse
{
public System.IO.Stream OutputStream => null;
}
class HttpListenerContext
{
public HttpListenerResponse Response => null;
}
class HttpListener
{
public HttpListenerContext GetContext() => null;
}
}

View File

@@ -0,0 +1 @@
semmle-extractor-options: ${testdir}/../../../../resources/stubs/System.Net.cs

View File

@@ -0,0 +1,2 @@
semmle-extractor-options: /nostdlib /noconfig
semmle-extractor-options: --load-sources-from-project:${testdir}/../../../../resources/stubs/System.Data.SqlClient/4.8.3/System.Data.SqlClient.csproj

View File

@@ -1,71 +0,0 @@
// This file contains auto-generated code.
namespace System
{
namespace Data
{
// Generated from `System.Data.IDbConnection` in `System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
public interface IDbConnection : System.IDisposable
{
string ConnectionString { get; set; }
}
namespace Common
{
// Generated from `System.Data.Common.DbConnectionStringBuilder` in `System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
public class DbConnectionStringBuilder : System.Collections.IEnumerable, System.Collections.IDictionary, System.Collections.ICollection
{
System.Collections.IDictionaryEnumerator System.Collections.IDictionary.GetEnumerator() => throw null;
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() => throw null;
bool System.Collections.ICollection.IsSynchronized { get => throw null; }
bool System.Collections.IDictionary.Contains(object keyword) => throw null;
object System.Collections.ICollection.SyncRoot { get => throw null; }
public object this[object keyword] { get => throw null; set => throw null; }
public bool IsReadOnly { get => throw null; }
public override string ToString() => throw null;
public string ConnectionString { get => throw null; set => throw null; }
public virtual System.Collections.ICollection Keys { get => throw null; }
public virtual System.Collections.ICollection Values { get => throw null; }
public virtual bool IsFixedSize { get => throw null; }
public virtual int Count { get => throw null; }
public virtual void Clear() => throw null;
void System.Collections.ICollection.CopyTo(System.Array array, int index) => throw null;
void System.Collections.IDictionary.Add(object keyword, object value) => throw null;
void System.Collections.IDictionary.Remove(object keyword) => throw null;
public void Dispose() => throw null;
}
// Generated from `System.Data.Common.DbConnection` in `System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
abstract public class DbConnection : System.IDisposable, System.Data.IDbConnection
{
public abstract string ConnectionString { get; set; }
public void Dispose() => throw null;
}
}
namespace SqlClient
{
// Generated from `System.Data.SqlClient.SqlConnectionStringBuilder` in `System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
public class SqlConnectionStringBuilder : System.Data.Common.DbConnectionStringBuilder
{
public SqlConnectionStringBuilder() => throw null;
public SqlConnectionStringBuilder(string connectionString) => throw null;
public bool Encrypt { get => throw null; set => throw null; }
public override System.Collections.ICollection Keys { get => throw null; }
public override System.Collections.ICollection Values { get => throw null; }
public override bool IsFixedSize { get => throw null; }
public override void Clear() => throw null;
}
// Generated from `System.Data.SqlClient.SqlConnection` in `System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089`
public class SqlConnection : System.Data.Common.DbConnection, System.ICloneable
{
object System.ICloneable.Clone() => throw null;
public SqlConnection() => throw null;
public SqlConnection(string connectionString) => throw null;
public override string ConnectionString { get => throw null; set => throw null; }
}
}
}
}

View File

@@ -11,12 +11,7 @@ private newtype TNode =
MkSsaNode(SsaDefinition ssa) or
MkGlobalFunctionNode(Function f) or
MkImplicitVarargsSlice(CallExpr c) { c.hasImplicitVarargs() } or
MkSummarizedParameterNode(SummarizedCallable c, int i) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, i)
} or
MkSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
}
MkFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn)
/** Nodes intended for only use inside the data-flow libraries. */
module Private {
@@ -30,9 +25,7 @@ module Private {
not exists(n.getEnclosingCallable()) and
result.asFileScope() = n.getFile()
or
n = MkSummarizedParameterNode(result.asSummarizedCallable(), _)
or
n = MkSummaryInternalNode(result.asSummarizedCallable(), _)
result.asSummarizedCallable() = n.(FlowSummaryNode).getSummarizedCallable()
}
/** Holds if `p` is a `ParameterNode` of `c` with position `pos`. */
@@ -52,7 +45,7 @@ module Private {
ReturnNode() {
this.(Public::ResultNode).getIndex() = kind.getIndex()
or
this.(SummaryNode).isReturn(kind)
this.(FlowSummaryNode).isReturn(kind)
}
/** Gets the kind of this returned value. */
@@ -72,33 +65,33 @@ module Private {
/**
* A data-flow node used to model flow summaries.
*/
class SummaryNode extends Node, MkSummaryInternalNode {
private SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
class FlowSummaryNode extends Node, MkFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = MkFlowSummaryNode(result) }
SummaryNode() { this = MkSummaryInternalNode(c, state) }
override predicate hasLocationInfo(string fp, int sl, int sc, int el, int ec) {
c.hasLocationInfo(fp, sl, sc, el, ec)
SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override string toString() { result = "[summary] " + state + " in " + c }
override predicate hasLocationInfo(string fp, int sl, int sc, int el, int ec) {
this.getSummarizedCallable().hasLocationInfo(fp, sl, sc, el, ec)
}
override string toString() { result = this.getSummaryNode().toString() }
/** Holds if this summary node is the `i`th argument of `call`. */
predicate isArgumentOf(DataFlowCall call, int i) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, i)
FlowSummaryImpl::Private::summaryArgumentNode(call, this.getSummaryNode(), i)
}
/** Holds if this summary node is a return node. */
predicate isReturn(ReturnKind kind) { FlowSummaryImpl::Private::summaryReturnNode(this, kind) }
predicate isReturn(ReturnKind kind) {
FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), kind)
}
/** Holds if this summary node is an out node for `call`. */
predicate isOut(DataFlowCall call) { FlowSummaryImpl::Private::summaryOutNode(call, this, _) }
}
/** Gets the summary node corresponding to the callable `c` and state `state`. */
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
result = MkSummaryInternalNode(c, state)
predicate isOut(DataFlowCall call) {
FlowSummaryImpl::Private::summaryOutNode(call, this.getSummaryNode(), _)
}
}
}
@@ -661,11 +654,14 @@ module Public {
* A summary node which represents a parameter in a function which doesn't
* already have a parameter nodes.
*/
class SummarizedParameterNode extends ParameterNode, MkSummarizedParameterNode {
SummarizedCallable c;
int i;
class SummarizedParameterNode extends ParameterNode, FlowSummaryNode {
SummarizedParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _)
}
SummarizedParameterNode() { this = MkSummarizedParameterNode(c, i) }
private int getPos() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result)
}
// There are no AST representations of summarized parameter nodes
override ControlFlow::Root getRoot() { none() }
@@ -673,19 +669,14 @@ module Public {
override string getNodeKind() { result = "external parameter node" }
override Type getType() {
result = c.getType().getParameterType(i)
result = this.getSummarizedCallable().getType().getParameterType(this.getPos())
or
i = -1 and result = c.asFunction().(Method).getReceiverType()
this.getPos() = -1 and
result = this.getSummarizedCallable().asFunction().(Method).getReceiverType()
}
override predicate isParameterOf(DataFlowCallable call, int idx) {
c = call.asSummarizedCallable() and i = idx
}
override string toString() { result = "parameter " + i + " of " + c.toString() }
override predicate hasLocationInfo(string fp, int sl, int sc, int el, int ec) {
c.hasLocationInfo(fp, sl, sc, el, ec)
this.getSummarizedCallable() = call.asSummarizedCallable() and this.getPos() = idx
}
}
@@ -1237,10 +1228,12 @@ module Public {
private import Private
private import Public
class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private Node pre;
class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
private FlowSummaryNode pre;
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), pre.getSummaryNode())
}
override Node getPreUpdateNode() { result = pre }
}

View File

@@ -129,7 +129,8 @@ predicate jumpStep(Node n1, Node n2) {
n2 = recvRead
)
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(n1, n2)
FlowSummaryImpl::Private::Steps::summaryJumpStep(n1.(FlowSummaryNode).getSummaryNode(),
n2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -153,7 +154,8 @@ predicate storeStep(Node node1, Content c, Node node2) {
node1 = node2.(AddressOperationNode).getOperand() and
c = any(DataFlow::PointerContent pc | pc.getPointerType() = node2.getType())
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
or
containerStoreStep(node1, node2, c)
}
@@ -173,7 +175,8 @@ predicate readStep(Node node1, Content c, Node node2) {
c = any(DataFlow::FieldContent fc | fc.getField() = read.getField())
)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
or
containerReadStep(node1, node2, c)
}
@@ -197,7 +200,7 @@ predicate clearsContent(Node n, Content c) {
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2) { none() }
@@ -380,7 +383,7 @@ Node getArgument(CallNode c, int i) {
}
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) { n instanceof SummaryNode or n instanceof SummarizedParameterNode }
predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
class LambdaCallKind = Unit;

View File

@@ -124,7 +124,8 @@ predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
// step through function model
any(FunctionModel m).flowStep(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
}
/**

View File

@@ -505,6 +505,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +533,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +562,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +613,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +621,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +644,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +659,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +667,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +675,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +688,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +703,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +716,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +737,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +749,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +764,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +773,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +787,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +799,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +816,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +842,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +854,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +866,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +893,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +905,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +915,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +937,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +962,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1001,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1016,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1029,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1043,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1411,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1424,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1444,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -17,7 +17,7 @@ private module FlowSummaries {
class SummarizedCallableBase = Callable;
DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c }
DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() = c or none() }
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { result = -1 }
@@ -28,10 +28,8 @@ string getParameterPosition(ParameterPosition pos) { result = pos.toString() }
/** Gets the textual representation of an argument position in the format used for flow summaries. */
string getArgumentPosition(ArgumentPosition pos) { result = pos.toString() }
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
DataFlowCall summaryDataFlowCall(Node receiver) {
DataFlowCall summaryDataFlowCall(SummaryNode receiver) {
// We do not currently have support for callback-based library models.
none()
}
@@ -39,6 +37,9 @@ DataFlowCall summaryDataFlowCall(Node receiver) {
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) { result = c.getType() }
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) { any() }
/** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() }

View File

@@ -5,6 +5,7 @@
private import go
private import FlowSummaryImpl as FlowSummaryImpl
private import codeql.util.Unit
private import DataFlowPrivate as DataFlowPrivate
/**
* Holds if taint can flow from `src` to `sink` in zero or more
@@ -95,7 +96,8 @@ predicate localAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
sliceStep(pred, succ) or
any(FunctionModel fm).taintStep(pred, succ) or
any(AdditionalTaintStep a).step(pred, succ) or
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred, succ, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(pred.(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), succ.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false)
}
/**

View File

@@ -1,7 +1,7 @@
| file://:0:0:0:0 | parameter -1 of AddCookie |
| file://:0:0:0:0 | parameter -1 of Clone |
| file://:0:0:0:0 | parameter -1 of Write |
| file://:0:0:0:0 | parameter -1 of WriteProxy |
| file://:0:0:0:0 | [summary param] -1 in AddCookie |
| file://:0:0:0:0 | [summary param] -1 in Clone |
| file://:0:0:0:0 | [summary param] -1 in Write |
| file://:0:0:0:0 | [summary param] -1 in WriteProxy |
| main.go:18:12:18:14 | argument corresponding to req |
| main.go:18:12:18:14 | definition of req |
| main.go:20:5:20:7 | req |

View File

@@ -1,286 +1,286 @@
| file://:0:0:0:0 | parameter 0 of AppendQuote | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuote |
| file://:0:0:0:0 | parameter 0 of AppendQuoteToASCII | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToASCII |
| file://:0:0:0:0 | parameter 0 of AppendQuoteToGraphic | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToGraphic |
| file://:0:0:0:0 | parameter 0 of AppendSlice | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendSlice |
| file://:0:0:0:0 | parameter 0 of As | file://:0:0:0:0 | [summary] to write: argument 1 in As |
| file://:0:0:0:0 | parameter 0 of Base | file://:0:0:0:0 | [summary] to write: return (return[0]) in Base |
| file://:0:0:0:0 | parameter 0 of BytePtrFromString | file://:0:0:0:0 | [summary] to write: return (return[0]) in BytePtrFromString |
| file://:0:0:0:0 | parameter 0 of ByteSliceFromString | file://:0:0:0:0 | [summary] to write: return (return[0]) in ByteSliceFromString |
| file://:0:0:0:0 | parameter 0 of Clean | file://:0:0:0:0 | [summary] to write: return (return[0]) in Clean |
| file://:0:0:0:0 | parameter 0 of Dir | file://:0:0:0:0 | [summary] to write: return (return[0]) in Dir |
| file://:0:0:0:0 | parameter 0 of Expand | file://:0:0:0:0 | [summary] to write: return (return[0]) in Expand |
| file://:0:0:0:0 | parameter 0 of ExpandEnv | file://:0:0:0:0 | [summary] to write: return (return[0]) in ExpandEnv |
| file://:0:0:0:0 | parameter 0 of Ext | file://:0:0:0:0 | [summary] to write: return (return[0]) in Ext |
| file://:0:0:0:0 | parameter 0 of Fields | file://:0:0:0:0 | [summary] to write: return (return[0]) in Fields |
| file://:0:0:0:0 | parameter 0 of FieldsFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldsFunc |
| file://:0:0:0:0 | parameter 0 of FileInfoToDirEntry | file://:0:0:0:0 | [summary] to write: return (return[0]) in FileInfoToDirEntry |
| file://:0:0:0:0 | parameter 0 of Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
| file://:0:0:0:0 | parameter 0 of Indirect | file://:0:0:0:0 | [summary] to write: return (return[0]) in Indirect |
| file://:0:0:0:0 | parameter 0 of Join | file://:0:0:0:0 | [summary] to write: return (return[0]) in Join |
| file://:0:0:0:0 | parameter 0 of LimitReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in LimitReader |
| file://:0:0:0:0 | parameter 0 of LoadOrStore | file://:0:0:0:0 | [summary] to write: argument -1 in LoadOrStore |
| file://:0:0:0:0 | parameter 0 of LoadOrStore | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadOrStore |
| file://:0:0:0:0 | parameter 0 of LoadPointer | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadPointer |
| file://:0:0:0:0 | parameter 0 of LoadUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadUintptr |
| file://:0:0:0:0 | parameter 0 of New | file://:0:0:0:0 | [summary] to write: return (return[0]) in New |
| file://:0:0:0:0 | parameter 0 of NewFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in NewFile |
| file://:0:0:0:0 | parameter 0 of NewReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in NewReader |
| file://:0:0:0:0 | parameter 0 of NewSectionReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in NewSectionReader |
| file://:0:0:0:0 | parameter 0 of NopCloser | file://:0:0:0:0 | [summary] to write: return (return[0]) in NopCloser |
| file://:0:0:0:0 | parameter 0 of Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
| file://:0:0:0:0 | parameter 0 of Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
| file://:0:0:0:0 | parameter 0 of ParseQuery | file://:0:0:0:0 | [summary] to write: return (return[0]) in ParseQuery |
| file://:0:0:0:0 | parameter 0 of ParseRequestURI | file://:0:0:0:0 | [summary] to write: return (return[0]) in ParseRequestURI |
| file://:0:0:0:0 | parameter 0 of PathEscape | file://:0:0:0:0 | [summary] to write: return (return[0]) in PathEscape |
| file://:0:0:0:0 | parameter 0 of PathUnescape | file://:0:0:0:0 | [summary] to write: return (return[0]) in PathUnescape |
| file://:0:0:0:0 | parameter 0 of Put | file://:0:0:0:0 | [summary] to write: argument -1 in Put |
| file://:0:0:0:0 | parameter 0 of QueryEscape | file://:0:0:0:0 | [summary] to write: return (return[0]) in QueryEscape |
| file://:0:0:0:0 | parameter 0 of QueryUnescape | file://:0:0:0:0 | [summary] to write: return (return[0]) in QueryUnescape |
| file://:0:0:0:0 | parameter 0 of Quote | file://:0:0:0:0 | [summary] to write: return (return[0]) in Quote |
| file://:0:0:0:0 | parameter 0 of QuoteToASCII | file://:0:0:0:0 | [summary] to write: return (return[0]) in QuoteToASCII |
| file://:0:0:0:0 | parameter 0 of QuoteToGraphic | file://:0:0:0:0 | [summary] to write: return (return[0]) in QuoteToGraphic |
| file://:0:0:0:0 | parameter 0 of QuotedPrefix | file://:0:0:0:0 | [summary] to write: return (return[0]) in QuotedPrefix |
| file://:0:0:0:0 | parameter 0 of ReadAll | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadAll |
| file://:0:0:0:0 | parameter 0 of ReadAtLeast | file://:0:0:0:0 | [summary] to write: argument 1 in ReadAtLeast |
| file://:0:0:0:0 | parameter 0 of ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
| file://:0:0:0:0 | parameter 0 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
| file://:0:0:0:0 | parameter 0 of ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
| file://:0:0:0:0 | parameter 0 of ReadFull | file://:0:0:0:0 | [summary] to write: argument 1 in ReadFull |
| file://:0:0:0:0 | parameter 0 of Repeat | file://:0:0:0:0 | [summary] to write: return (return[0]) in Repeat |
| file://:0:0:0:0 | parameter 0 of Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
| file://:0:0:0:0 | parameter 0 of Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
| file://:0:0:0:0 | parameter 0 of ReplaceAll | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReplaceAll |
| file://:0:0:0:0 | parameter 0 of Reset | file://:0:0:0:0 | [summary] to write: argument -1 in Reset |
| file://:0:0:0:0 | parameter 0 of ResolveReference | file://:0:0:0:0 | [summary] to write: return (return[0]) in ResolveReference |
| file://:0:0:0:0 | parameter 0 of Reverse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Reverse |
| file://:0:0:0:0 | parameter 0 of Send | file://:0:0:0:0 | [summary] to write: argument -1 in Send |
| file://:0:0:0:0 | parameter 0 of Set | file://:0:0:0:0 | [summary] to write: argument -1 in Set |
| file://:0:0:0:0 | parameter 0 of SetBytes | file://:0:0:0:0 | [summary] to write: argument -1 in SetBytes |
| file://:0:0:0:0 | parameter 0 of SetMapIndex | file://:0:0:0:0 | [summary] to write: argument -1 in SetMapIndex |
| file://:0:0:0:0 | parameter 0 of SetPointer | file://:0:0:0:0 | [summary] to write: argument -1 in SetPointer |
| file://:0:0:0:0 | parameter 0 of SetString | file://:0:0:0:0 | [summary] to write: argument -1 in SetString |
| file://:0:0:0:0 | parameter 0 of Split | file://:0:0:0:0 | [summary] to write: return (return[0]) in Split |
| file://:0:0:0:0 | parameter 0 of Split | file://:0:0:0:0 | [summary] to write: return (return[0]) in Split |
| file://:0:0:0:0 | parameter 0 of Split | file://:0:0:0:0 | [summary] to write: return (return[1]) in Split |
| file://:0:0:0:0 | parameter 0 of SplitAfter | file://:0:0:0:0 | [summary] to write: return (return[0]) in SplitAfter |
| file://:0:0:0:0 | parameter 0 of SplitAfterN | file://:0:0:0:0 | [summary] to write: return (return[0]) in SplitAfterN |
| file://:0:0:0:0 | parameter 0 of SplitN | file://:0:0:0:0 | [summary] to write: return (return[0]) in SplitN |
| file://:0:0:0:0 | parameter 0 of Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | parameter 0 of Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | parameter 0 of Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | parameter 0 of Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | parameter 0 of StringBytePtr | file://:0:0:0:0 | [summary] to write: return (return[0]) in StringBytePtr |
| file://:0:0:0:0 | parameter 0 of StringByteSlice | file://:0:0:0:0 | [summary] to write: return (return[0]) in StringByteSlice |
| file://:0:0:0:0 | parameter 0 of Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
| file://:0:0:0:0 | parameter 0 of Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | parameter 0 of Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | parameter 0 of Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | parameter 0 of Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | parameter 0 of SwapPointer | file://:0:0:0:0 | [summary] to write: return (return[0]) in SwapPointer |
| file://:0:0:0:0 | parameter 0 of SwapUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in SwapUintptr |
| file://:0:0:0:0 | parameter 0 of TeeReader | file://:0:0:0:0 | [summary] to write: argument 1 in TeeReader |
| file://:0:0:0:0 | parameter 0 of TeeReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in TeeReader |
| file://:0:0:0:0 | parameter 0 of Title | file://:0:0:0:0 | [summary] to write: return (return[0]) in Title |
| file://:0:0:0:0 | parameter 0 of ToLower | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToLower |
| file://:0:0:0:0 | parameter 0 of ToTitle | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToTitle |
| file://:0:0:0:0 | parameter 0 of ToUpper | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToUpper |
| file://:0:0:0:0 | parameter 0 of ToValidUTF8 | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToValidUTF8 |
| file://:0:0:0:0 | parameter 0 of Trim | file://:0:0:0:0 | [summary] to write: return (return[0]) in Trim |
| file://:0:0:0:0 | parameter 0 of TrimFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimFunc |
| file://:0:0:0:0 | parameter 0 of TrimLeft | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimLeft |
| file://:0:0:0:0 | parameter 0 of TrimLeftFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimLeftFunc |
| file://:0:0:0:0 | parameter 0 of TrimPrefix | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimPrefix |
| file://:0:0:0:0 | parameter 0 of TrimRight | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimRight |
| file://:0:0:0:0 | parameter 0 of TrimRightFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimRightFunc |
| file://:0:0:0:0 | parameter 0 of TrimSpace | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimSpace |
| file://:0:0:0:0 | parameter 0 of TrimSuffix | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimSuffix |
| file://:0:0:0:0 | parameter 0 of TrySend | file://:0:0:0:0 | [summary] to write: argument -1 in TrySend |
| file://:0:0:0:0 | parameter 0 of Unquote | file://:0:0:0:0 | [summary] to write: return (return[0]) in Unquote |
| file://:0:0:0:0 | parameter 0 of UnquoteChar | file://:0:0:0:0 | [summary] to write: return (return[2]) in UnquoteChar |
| file://:0:0:0:0 | parameter 0 of Unwrap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Unwrap |
| file://:0:0:0:0 | parameter 0 of User | file://:0:0:0:0 | [summary] to write: return (return[0]) in User |
| file://:0:0:0:0 | parameter 0 of UserPassword | file://:0:0:0:0 | [summary] to write: return (return[0]) in UserPassword |
| file://:0:0:0:0 | parameter 0 of ValueOf | file://:0:0:0:0 | [summary] to write: return (return[0]) in ValueOf |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
| file://:0:0:0:0 | parameter 0 of WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 0 of WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | parameter 1 of AddUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in AddUintptr |
| file://:0:0:0:0 | parameter 1 of AddUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in AddUintptr |
| file://:0:0:0:0 | parameter 1 of AppendQuote | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuote |
| file://:0:0:0:0 | parameter 1 of AppendQuoteToASCII | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToASCII |
| file://:0:0:0:0 | parameter 1 of AppendQuoteToGraphic | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToGraphic |
| file://:0:0:0:0 | parameter 1 of AppendSlice | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendSlice |
| file://:0:0:0:0 | parameter 1 of Copy | file://:0:0:0:0 | [summary] to write: argument 0 in Copy |
| file://:0:0:0:0 | parameter 1 of Copy | file://:0:0:0:0 | [summary] to write: argument 0 in Copy |
| file://:0:0:0:0 | parameter 1 of CopyBuffer | file://:0:0:0:0 | [summary] to write: argument 0 in CopyBuffer |
| file://:0:0:0:0 | parameter 1 of CopyN | file://:0:0:0:0 | [summary] to write: argument 0 in CopyN |
| file://:0:0:0:0 | parameter 1 of Join | file://:0:0:0:0 | [summary] to write: return (return[0]) in Join |
| file://:0:0:0:0 | parameter 1 of LoadOrStore | file://:0:0:0:0 | [summary] to write: argument -1 in LoadOrStore |
| file://:0:0:0:0 | parameter 1 of LoadOrStore | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadOrStore |
| file://:0:0:0:0 | parameter 1 of Map | file://:0:0:0:0 | [summary] to write: return (return[0]) in Map |
| file://:0:0:0:0 | parameter 1 of SetMapIndex | file://:0:0:0:0 | [summary] to write: argument -1 in SetMapIndex |
| file://:0:0:0:0 | parameter 1 of Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | parameter 1 of StorePointer | file://:0:0:0:0 | [summary] to write: argument 0 in StorePointer |
| file://:0:0:0:0 | parameter 1 of StoreUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in StoreUintptr |
| file://:0:0:0:0 | parameter 1 of Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | parameter 1 of SwapPointer | file://:0:0:0:0 | [summary] to write: argument 0 in SwapPointer |
| file://:0:0:0:0 | parameter 1 of SwapUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in SwapUintptr |
| file://:0:0:0:0 | parameter 1 of ToLowerSpecial | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToLowerSpecial |
| file://:0:0:0:0 | parameter 1 of ToTitleSpecial | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToTitleSpecial |
| file://:0:0:0:0 | parameter 1 of ToUpperSpecial | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToUpperSpecial |
| file://:0:0:0:0 | parameter 1 of ToValidUTF8 | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToValidUTF8 |
| file://:0:0:0:0 | parameter 1 of UserPassword | file://:0:0:0:0 | [summary] to write: return (return[0]) in UserPassword |
| file://:0:0:0:0 | parameter 1 of WriteString | file://:0:0:0:0 | [summary] to write: argument 0 in WriteString |
| file://:0:0:0:0 | parameter 1 of WriteString | file://:0:0:0:0 | [summary] to write: argument 0 in WriteString |
| file://:0:0:0:0 | parameter 2 of CompareAndSwap | file://:0:0:0:0 | [summary] to write: argument -1 in CompareAndSwap |
| file://:0:0:0:0 | parameter 2 of CompareAndSwapPointer | file://:0:0:0:0 | [summary] to write: argument 0 in CompareAndSwapPointer |
| file://:0:0:0:0 | parameter 2 of CompareAndSwapUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in CompareAndSwapUintptr |
| file://:0:0:0:0 | parameter 2 of Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
| file://:0:0:0:0 | parameter 2 of ReplaceAll | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReplaceAll |
| file://:0:0:0:0 | parameter -1 of Addr | file://:0:0:0:0 | [summary] to write: return (return[0]) in Addr |
| file://:0:0:0:0 | parameter -1 of Bytes | file://:0:0:0:0 | [summary] to write: return (return[0]) in Bytes |
| file://:0:0:0:0 | parameter -1 of Convert | file://:0:0:0:0 | [summary] to write: return (return[0]) in Convert |
| file://:0:0:0:0 | parameter -1 of Elem | file://:0:0:0:0 | [summary] to write: return (return[0]) in Elem |
| file://:0:0:0:0 | parameter -1 of Encode | file://:0:0:0:0 | [summary] to write: return (return[0]) in Encode |
| file://:0:0:0:0 | parameter -1 of EscapedPath | file://:0:0:0:0 | [summary] to write: return (return[0]) in EscapedPath |
| file://:0:0:0:0 | parameter -1 of Fd | file://:0:0:0:0 | [summary] to write: return (return[0]) in Fd |
| file://:0:0:0:0 | parameter -1 of Field | file://:0:0:0:0 | [summary] to write: return (return[0]) in Field |
| file://:0:0:0:0 | parameter -1 of FieldByIndex | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldByIndex |
| file://:0:0:0:0 | parameter -1 of FieldByName | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldByName |
| file://:0:0:0:0 | parameter -1 of FieldByNameFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldByNameFunc |
| file://:0:0:0:0 | parameter -1 of Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
| file://:0:0:0:0 | parameter -1 of Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
| file://:0:0:0:0 | parameter -1 of Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
| file://:0:0:0:0 | parameter -1 of Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
| file://:0:0:0:0 | parameter -1 of Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
| file://:0:0:0:0 | parameter -1 of GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
| file://:0:0:0:0 | parameter -1 of GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
| file://:0:0:0:0 | parameter -1 of Hostname | file://:0:0:0:0 | [summary] to write: return (return[0]) in Hostname |
| file://:0:0:0:0 | parameter -1 of Index | file://:0:0:0:0 | [summary] to write: return (return[0]) in Index |
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
| file://:0:0:0:0 | parameter -1 of Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
| file://:0:0:0:0 | parameter -1 of Interface | file://:0:0:0:0 | [summary] to write: return (return[0]) in Interface |
| file://:0:0:0:0 | parameter -1 of InterfaceData | file://:0:0:0:0 | [summary] to write: return (return[0]) in InterfaceData |
| file://:0:0:0:0 | parameter -1 of Key | file://:0:0:0:0 | [summary] to write: return (return[0]) in Key |
| file://:0:0:0:0 | parameter -1 of Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | parameter -1 of Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | parameter -1 of Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | parameter -1 of Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | parameter -1 of LoadOrStore | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadOrStore |
| file://:0:0:0:0 | parameter -1 of Lookup | file://:0:0:0:0 | [summary] to write: return (return[0]) in Lookup |
| file://:0:0:0:0 | parameter -1 of MapIndex | file://:0:0:0:0 | [summary] to write: return (return[0]) in MapIndex |
| file://:0:0:0:0 | parameter -1 of MapKeys | file://:0:0:0:0 | [summary] to write: return (return[0]) in MapKeys |
| file://:0:0:0:0 | parameter -1 of MapRange | file://:0:0:0:0 | [summary] to write: return (return[0]) in MapRange |
| file://:0:0:0:0 | parameter -1 of MarshalBinary | file://:0:0:0:0 | [summary] to write: return (return[0]) in MarshalBinary |
| file://:0:0:0:0 | parameter -1 of Method | file://:0:0:0:0 | [summary] to write: return (return[0]) in Method |
| file://:0:0:0:0 | parameter -1 of MethodByName | file://:0:0:0:0 | [summary] to write: return (return[0]) in MethodByName |
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
| file://:0:0:0:0 | parameter -1 of Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
| file://:0:0:0:0 | parameter -1 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
| file://:0:0:0:0 | parameter -1 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
| file://:0:0:0:0 | parameter -1 of Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
| file://:0:0:0:0 | parameter -1 of Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
| file://:0:0:0:0 | parameter -1 of Password | file://:0:0:0:0 | [summary] to write: return (return[0]) in Password |
| file://:0:0:0:0 | parameter -1 of Pointer | file://:0:0:0:0 | [summary] to write: return (return[0]) in Pointer |
| file://:0:0:0:0 | parameter -1 of Port | file://:0:0:0:0 | [summary] to write: return (return[0]) in Port |
| file://:0:0:0:0 | parameter -1 of Query | file://:0:0:0:0 | [summary] to write: return (return[0]) in Query |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | parameter -1 of ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | parameter -1 of ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
| file://:0:0:0:0 | parameter -1 of ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
| file://:0:0:0:0 | parameter -1 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
| file://:0:0:0:0 | parameter -1 of ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
| file://:0:0:0:0 | parameter -1 of Recv | file://:0:0:0:0 | [summary] to write: return (return[0]) in Recv |
| file://:0:0:0:0 | parameter -1 of RequestURI | file://:0:0:0:0 | [summary] to write: return (return[0]) in RequestURI |
| file://:0:0:0:0 | parameter -1 of ResolveReference | file://:0:0:0:0 | [summary] to write: return (return[0]) in ResolveReference |
| file://:0:0:0:0 | parameter -1 of Slice | file://:0:0:0:0 | [summary] to write: return (return[0]) in Slice |
| file://:0:0:0:0 | parameter -1 of Slice3 | file://:0:0:0:0 | [summary] to write: return (return[0]) in Slice3 |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | parameter -1 of Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
| file://:0:0:0:0 | parameter -1 of Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | parameter -1 of Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | parameter -1 of SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
| file://:0:0:0:0 | parameter -1 of SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
| file://:0:0:0:0 | parameter -1 of Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
| file://:0:0:0:0 | parameter -1 of Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
| file://:0:0:0:0 | parameter -1 of TryRecv | file://:0:0:0:0 | [summary] to write: return (return[0]) in TryRecv |
| file://:0:0:0:0 | parameter -1 of UnsafeAddr | file://:0:0:0:0 | [summary] to write: return (return[0]) in UnsafeAddr |
| file://:0:0:0:0 | parameter -1 of Username | file://:0:0:0:0 | [summary] to write: return (return[0]) in Username |
| file://:0:0:0:0 | parameter -1 of Value | file://:0:0:0:0 | [summary] to write: return (return[0]) in Value |
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | parameter -1 of WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | [summary param] 0 in AppendQuote | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuote |
| file://:0:0:0:0 | [summary param] 0 in AppendQuoteToASCII | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToASCII |
| file://:0:0:0:0 | [summary param] 0 in AppendQuoteToGraphic | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToGraphic |
| file://:0:0:0:0 | [summary param] 0 in AppendSlice | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendSlice |
| file://:0:0:0:0 | [summary param] 0 in As | file://:0:0:0:0 | [summary] to write: argument 1 in As |
| file://:0:0:0:0 | [summary param] 0 in Base | file://:0:0:0:0 | [summary] to write: return (return[0]) in Base |
| file://:0:0:0:0 | [summary param] 0 in BytePtrFromString | file://:0:0:0:0 | [summary] to write: return (return[0]) in BytePtrFromString |
| file://:0:0:0:0 | [summary param] 0 in ByteSliceFromString | file://:0:0:0:0 | [summary] to write: return (return[0]) in ByteSliceFromString |
| file://:0:0:0:0 | [summary param] 0 in Clean | file://:0:0:0:0 | [summary] to write: return (return[0]) in Clean |
| file://:0:0:0:0 | [summary param] 0 in Dir | file://:0:0:0:0 | [summary] to write: return (return[0]) in Dir |
| file://:0:0:0:0 | [summary param] 0 in Expand | file://:0:0:0:0 | [summary] to write: return (return[0]) in Expand |
| file://:0:0:0:0 | [summary param] 0 in ExpandEnv | file://:0:0:0:0 | [summary] to write: return (return[0]) in ExpandEnv |
| file://:0:0:0:0 | [summary param] 0 in Ext | file://:0:0:0:0 | [summary] to write: return (return[0]) in Ext |
| file://:0:0:0:0 | [summary param] 0 in Fields | file://:0:0:0:0 | [summary] to write: return (return[0]) in Fields |
| file://:0:0:0:0 | [summary param] 0 in FieldsFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldsFunc |
| file://:0:0:0:0 | [summary param] 0 in FileInfoToDirEntry | file://:0:0:0:0 | [summary] to write: return (return[0]) in FileInfoToDirEntry |
| file://:0:0:0:0 | [summary param] 0 in Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
| file://:0:0:0:0 | [summary param] 0 in Indirect | file://:0:0:0:0 | [summary] to write: return (return[0]) in Indirect |
| file://:0:0:0:0 | [summary param] 0 in Join | file://:0:0:0:0 | [summary] to write: return (return[0]) in Join |
| file://:0:0:0:0 | [summary param] 0 in LimitReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in LimitReader |
| file://:0:0:0:0 | [summary param] 0 in LoadOrStore | file://:0:0:0:0 | [summary] to write: argument -1 in LoadOrStore |
| file://:0:0:0:0 | [summary param] 0 in LoadOrStore | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadOrStore |
| file://:0:0:0:0 | [summary param] 0 in LoadPointer | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadPointer |
| file://:0:0:0:0 | [summary param] 0 in LoadUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadUintptr |
| file://:0:0:0:0 | [summary param] 0 in New | file://:0:0:0:0 | [summary] to write: return (return[0]) in New |
| file://:0:0:0:0 | [summary param] 0 in NewFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in NewFile |
| file://:0:0:0:0 | [summary param] 0 in NewReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in NewReader |
| file://:0:0:0:0 | [summary param] 0 in NewSectionReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in NewSectionReader |
| file://:0:0:0:0 | [summary param] 0 in NopCloser | file://:0:0:0:0 | [summary] to write: return (return[0]) in NopCloser |
| file://:0:0:0:0 | [summary param] 0 in Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
| file://:0:0:0:0 | [summary param] 0 in Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
| file://:0:0:0:0 | [summary param] 0 in ParseQuery | file://:0:0:0:0 | [summary] to write: return (return[0]) in ParseQuery |
| file://:0:0:0:0 | [summary param] 0 in ParseRequestURI | file://:0:0:0:0 | [summary] to write: return (return[0]) in ParseRequestURI |
| file://:0:0:0:0 | [summary param] 0 in PathEscape | file://:0:0:0:0 | [summary] to write: return (return[0]) in PathEscape |
| file://:0:0:0:0 | [summary param] 0 in PathUnescape | file://:0:0:0:0 | [summary] to write: return (return[0]) in PathUnescape |
| file://:0:0:0:0 | [summary param] 0 in Put | file://:0:0:0:0 | [summary] to write: argument -1 in Put |
| file://:0:0:0:0 | [summary param] 0 in QueryEscape | file://:0:0:0:0 | [summary] to write: return (return[0]) in QueryEscape |
| file://:0:0:0:0 | [summary param] 0 in QueryUnescape | file://:0:0:0:0 | [summary] to write: return (return[0]) in QueryUnescape |
| file://:0:0:0:0 | [summary param] 0 in Quote | file://:0:0:0:0 | [summary] to write: return (return[0]) in Quote |
| file://:0:0:0:0 | [summary param] 0 in QuoteToASCII | file://:0:0:0:0 | [summary] to write: return (return[0]) in QuoteToASCII |
| file://:0:0:0:0 | [summary param] 0 in QuoteToGraphic | file://:0:0:0:0 | [summary] to write: return (return[0]) in QuoteToGraphic |
| file://:0:0:0:0 | [summary param] 0 in QuotedPrefix | file://:0:0:0:0 | [summary] to write: return (return[0]) in QuotedPrefix |
| file://:0:0:0:0 | [summary param] 0 in ReadAll | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadAll |
| file://:0:0:0:0 | [summary param] 0 in ReadAtLeast | file://:0:0:0:0 | [summary] to write: argument 1 in ReadAtLeast |
| file://:0:0:0:0 | [summary param] 0 in ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
| file://:0:0:0:0 | [summary param] 0 in ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
| file://:0:0:0:0 | [summary param] 0 in ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
| file://:0:0:0:0 | [summary param] 0 in ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
| file://:0:0:0:0 | [summary param] 0 in ReadFrom | file://:0:0:0:0 | [summary] to write: argument -1 in ReadFrom |
| file://:0:0:0:0 | [summary param] 0 in ReadFull | file://:0:0:0:0 | [summary] to write: argument 1 in ReadFull |
| file://:0:0:0:0 | [summary param] 0 in Repeat | file://:0:0:0:0 | [summary] to write: return (return[0]) in Repeat |
| file://:0:0:0:0 | [summary param] 0 in Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
| file://:0:0:0:0 | [summary param] 0 in Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
| file://:0:0:0:0 | [summary param] 0 in ReplaceAll | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReplaceAll |
| file://:0:0:0:0 | [summary param] 0 in Reset | file://:0:0:0:0 | [summary] to write: argument -1 in Reset |
| file://:0:0:0:0 | [summary param] 0 in ResolveReference | file://:0:0:0:0 | [summary] to write: return (return[0]) in ResolveReference |
| file://:0:0:0:0 | [summary param] 0 in Reverse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Reverse |
| file://:0:0:0:0 | [summary param] 0 in Send | file://:0:0:0:0 | [summary] to write: argument -1 in Send |
| file://:0:0:0:0 | [summary param] 0 in Set | file://:0:0:0:0 | [summary] to write: argument -1 in Set |
| file://:0:0:0:0 | [summary param] 0 in SetBytes | file://:0:0:0:0 | [summary] to write: argument -1 in SetBytes |
| file://:0:0:0:0 | [summary param] 0 in SetMapIndex | file://:0:0:0:0 | [summary] to write: argument -1 in SetMapIndex |
| file://:0:0:0:0 | [summary param] 0 in SetPointer | file://:0:0:0:0 | [summary] to write: argument -1 in SetPointer |
| file://:0:0:0:0 | [summary param] 0 in SetString | file://:0:0:0:0 | [summary] to write: argument -1 in SetString |
| file://:0:0:0:0 | [summary param] 0 in Split | file://:0:0:0:0 | [summary] to write: return (return[0]) in Split |
| file://:0:0:0:0 | [summary param] 0 in Split | file://:0:0:0:0 | [summary] to write: return (return[0]) in Split |
| file://:0:0:0:0 | [summary param] 0 in Split | file://:0:0:0:0 | [summary] to write: return (return[1]) in Split |
| file://:0:0:0:0 | [summary param] 0 in SplitAfter | file://:0:0:0:0 | [summary] to write: return (return[0]) in SplitAfter |
| file://:0:0:0:0 | [summary param] 0 in SplitAfterN | file://:0:0:0:0 | [summary] to write: return (return[0]) in SplitAfterN |
| file://:0:0:0:0 | [summary param] 0 in SplitN | file://:0:0:0:0 | [summary] to write: return (return[0]) in SplitN |
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | [summary param] 0 in Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | [summary param] 0 in StringBytePtr | file://:0:0:0:0 | [summary] to write: return (return[0]) in StringBytePtr |
| file://:0:0:0:0 | [summary param] 0 in StringByteSlice | file://:0:0:0:0 | [summary] to write: return (return[0]) in StringByteSlice |
| file://:0:0:0:0 | [summary param] 0 in Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
| file://:0:0:0:0 | [summary param] 0 in Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | [summary param] 0 in Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | [summary param] 0 in Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | [summary param] 0 in Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | [summary param] 0 in SwapPointer | file://:0:0:0:0 | [summary] to write: return (return[0]) in SwapPointer |
| file://:0:0:0:0 | [summary param] 0 in SwapUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in SwapUintptr |
| file://:0:0:0:0 | [summary param] 0 in TeeReader | file://:0:0:0:0 | [summary] to write: argument 1 in TeeReader |
| file://:0:0:0:0 | [summary param] 0 in TeeReader | file://:0:0:0:0 | [summary] to write: return (return[0]) in TeeReader |
| file://:0:0:0:0 | [summary param] 0 in Title | file://:0:0:0:0 | [summary] to write: return (return[0]) in Title |
| file://:0:0:0:0 | [summary param] 0 in ToLower | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToLower |
| file://:0:0:0:0 | [summary param] 0 in ToTitle | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToTitle |
| file://:0:0:0:0 | [summary param] 0 in ToUpper | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToUpper |
| file://:0:0:0:0 | [summary param] 0 in ToValidUTF8 | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToValidUTF8 |
| file://:0:0:0:0 | [summary param] 0 in Trim | file://:0:0:0:0 | [summary] to write: return (return[0]) in Trim |
| file://:0:0:0:0 | [summary param] 0 in TrimFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimFunc |
| file://:0:0:0:0 | [summary param] 0 in TrimLeft | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimLeft |
| file://:0:0:0:0 | [summary param] 0 in TrimLeftFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimLeftFunc |
| file://:0:0:0:0 | [summary param] 0 in TrimPrefix | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimPrefix |
| file://:0:0:0:0 | [summary param] 0 in TrimRight | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimRight |
| file://:0:0:0:0 | [summary param] 0 in TrimRightFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimRightFunc |
| file://:0:0:0:0 | [summary param] 0 in TrimSpace | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimSpace |
| file://:0:0:0:0 | [summary param] 0 in TrimSuffix | file://:0:0:0:0 | [summary] to write: return (return[0]) in TrimSuffix |
| file://:0:0:0:0 | [summary param] 0 in TrySend | file://:0:0:0:0 | [summary] to write: argument -1 in TrySend |
| file://:0:0:0:0 | [summary param] 0 in Unquote | file://:0:0:0:0 | [summary] to write: return (return[0]) in Unquote |
| file://:0:0:0:0 | [summary param] 0 in UnquoteChar | file://:0:0:0:0 | [summary] to write: return (return[2]) in UnquoteChar |
| file://:0:0:0:0 | [summary param] 0 in Unwrap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Unwrap |
| file://:0:0:0:0 | [summary param] 0 in User | file://:0:0:0:0 | [summary] to write: return (return[0]) in User |
| file://:0:0:0:0 | [summary param] 0 in UserPassword | file://:0:0:0:0 | [summary] to write: return (return[0]) in UserPassword |
| file://:0:0:0:0 | [summary param] 0 in ValueOf | file://:0:0:0:0 | [summary] to write: return (return[0]) in ValueOf |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in Write | file://:0:0:0:0 | [summary] to write: argument -1 in Write |
| file://:0:0:0:0 | [summary param] 0 in WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
| file://:0:0:0:0 | [summary param] 0 in WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
| file://:0:0:0:0 | [summary param] 0 in WriteAt | file://:0:0:0:0 | [summary] to write: argument -1 in WriteAt |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 0 in WriteString | file://:0:0:0:0 | [summary] to write: argument -1 in WriteString |
| file://:0:0:0:0 | [summary param] 1 in AddUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in AddUintptr |
| file://:0:0:0:0 | [summary param] 1 in AddUintptr | file://:0:0:0:0 | [summary] to write: return (return[0]) in AddUintptr |
| file://:0:0:0:0 | [summary param] 1 in AppendQuote | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuote |
| file://:0:0:0:0 | [summary param] 1 in AppendQuoteToASCII | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToASCII |
| file://:0:0:0:0 | [summary param] 1 in AppendQuoteToGraphic | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendQuoteToGraphic |
| file://:0:0:0:0 | [summary param] 1 in AppendSlice | file://:0:0:0:0 | [summary] to write: return (return[0]) in AppendSlice |
| file://:0:0:0:0 | [summary param] 1 in Copy | file://:0:0:0:0 | [summary] to write: argument 0 in Copy |
| file://:0:0:0:0 | [summary param] 1 in Copy | file://:0:0:0:0 | [summary] to write: argument 0 in Copy |
| file://:0:0:0:0 | [summary param] 1 in CopyBuffer | file://:0:0:0:0 | [summary] to write: argument 0 in CopyBuffer |
| file://:0:0:0:0 | [summary param] 1 in CopyN | file://:0:0:0:0 | [summary] to write: argument 0 in CopyN |
| file://:0:0:0:0 | [summary param] 1 in Join | file://:0:0:0:0 | [summary] to write: return (return[0]) in Join |
| file://:0:0:0:0 | [summary param] 1 in LoadOrStore | file://:0:0:0:0 | [summary] to write: argument -1 in LoadOrStore |
| file://:0:0:0:0 | [summary param] 1 in LoadOrStore | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadOrStore |
| file://:0:0:0:0 | [summary param] 1 in Map | file://:0:0:0:0 | [summary] to write: return (return[0]) in Map |
| file://:0:0:0:0 | [summary param] 1 in SetMapIndex | file://:0:0:0:0 | [summary] to write: argument -1 in SetMapIndex |
| file://:0:0:0:0 | [summary param] 1 in Store | file://:0:0:0:0 | [summary] to write: argument -1 in Store |
| file://:0:0:0:0 | [summary param] 1 in StorePointer | file://:0:0:0:0 | [summary] to write: argument 0 in StorePointer |
| file://:0:0:0:0 | [summary param] 1 in StoreUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in StoreUintptr |
| file://:0:0:0:0 | [summary param] 1 in Swap | file://:0:0:0:0 | [summary] to write: argument -1 in Swap |
| file://:0:0:0:0 | [summary param] 1 in SwapPointer | file://:0:0:0:0 | [summary] to write: argument 0 in SwapPointer |
| file://:0:0:0:0 | [summary param] 1 in SwapUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in SwapUintptr |
| file://:0:0:0:0 | [summary param] 1 in ToLowerSpecial | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToLowerSpecial |
| file://:0:0:0:0 | [summary param] 1 in ToTitleSpecial | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToTitleSpecial |
| file://:0:0:0:0 | [summary param] 1 in ToUpperSpecial | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToUpperSpecial |
| file://:0:0:0:0 | [summary param] 1 in ToValidUTF8 | file://:0:0:0:0 | [summary] to write: return (return[0]) in ToValidUTF8 |
| file://:0:0:0:0 | [summary param] 1 in UserPassword | file://:0:0:0:0 | [summary] to write: return (return[0]) in UserPassword |
| file://:0:0:0:0 | [summary param] 1 in WriteString | file://:0:0:0:0 | [summary] to write: argument 0 in WriteString |
| file://:0:0:0:0 | [summary param] 1 in WriteString | file://:0:0:0:0 | [summary] to write: argument 0 in WriteString |
| file://:0:0:0:0 | [summary param] 2 in CompareAndSwap | file://:0:0:0:0 | [summary] to write: argument -1 in CompareAndSwap |
| file://:0:0:0:0 | [summary param] 2 in CompareAndSwapPointer | file://:0:0:0:0 | [summary] to write: argument 0 in CompareAndSwapPointer |
| file://:0:0:0:0 | [summary param] 2 in CompareAndSwapUintptr | file://:0:0:0:0 | [summary] to write: argument 0 in CompareAndSwapUintptr |
| file://:0:0:0:0 | [summary param] 2 in Replace | file://:0:0:0:0 | [summary] to write: return (return[0]) in Replace |
| file://:0:0:0:0 | [summary param] 2 in ReplaceAll | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReplaceAll |
| file://:0:0:0:0 | [summary param] -1 in Addr | file://:0:0:0:0 | [summary] to write: return (return[0]) in Addr |
| file://:0:0:0:0 | [summary param] -1 in Bytes | file://:0:0:0:0 | [summary] to write: return (return[0]) in Bytes |
| file://:0:0:0:0 | [summary param] -1 in Convert | file://:0:0:0:0 | [summary] to write: return (return[0]) in Convert |
| file://:0:0:0:0 | [summary param] -1 in Elem | file://:0:0:0:0 | [summary] to write: return (return[0]) in Elem |
| file://:0:0:0:0 | [summary param] -1 in Encode | file://:0:0:0:0 | [summary] to write: return (return[0]) in Encode |
| file://:0:0:0:0 | [summary param] -1 in EscapedPath | file://:0:0:0:0 | [summary] to write: return (return[0]) in EscapedPath |
| file://:0:0:0:0 | [summary param] -1 in Fd | file://:0:0:0:0 | [summary] to write: return (return[0]) in Fd |
| file://:0:0:0:0 | [summary param] -1 in Field | file://:0:0:0:0 | [summary] to write: return (return[0]) in Field |
| file://:0:0:0:0 | [summary param] -1 in FieldByIndex | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldByIndex |
| file://:0:0:0:0 | [summary param] -1 in FieldByName | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldByName |
| file://:0:0:0:0 | [summary param] -1 in FieldByNameFunc | file://:0:0:0:0 | [summary] to write: return (return[0]) in FieldByNameFunc |
| file://:0:0:0:0 | [summary param] -1 in Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
| file://:0:0:0:0 | [summary param] -1 in Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
| file://:0:0:0:0 | [summary param] -1 in Get | file://:0:0:0:0 | [summary] to write: return (return[0]) in Get |
| file://:0:0:0:0 | [summary param] -1 in Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
| file://:0:0:0:0 | [summary param] -1 in Glob | file://:0:0:0:0 | [summary] to write: return (return[0]) in Glob |
| file://:0:0:0:0 | [summary param] -1 in GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
| file://:0:0:0:0 | [summary param] -1 in GoString | file://:0:0:0:0 | [summary] to write: return (return[0]) in GoString |
| file://:0:0:0:0 | [summary param] -1 in Hostname | file://:0:0:0:0 | [summary] to write: return (return[0]) in Hostname |
| file://:0:0:0:0 | [summary param] -1 in Index | file://:0:0:0:0 | [summary] to write: return (return[0]) in Index |
| file://:0:0:0:0 | [summary param] -1 in Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
| file://:0:0:0:0 | [summary param] -1 in Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
| file://:0:0:0:0 | [summary param] -1 in Info | file://:0:0:0:0 | [summary] to write: return (return[0]) in Info |
| file://:0:0:0:0 | [summary param] -1 in Interface | file://:0:0:0:0 | [summary] to write: return (return[0]) in Interface |
| file://:0:0:0:0 | [summary param] -1 in InterfaceData | file://:0:0:0:0 | [summary] to write: return (return[0]) in InterfaceData |
| file://:0:0:0:0 | [summary param] -1 in Key | file://:0:0:0:0 | [summary] to write: return (return[0]) in Key |
| file://:0:0:0:0 | [summary param] -1 in Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | [summary param] -1 in Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | [summary param] -1 in Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | [summary param] -1 in Load | file://:0:0:0:0 | [summary] to write: return (return[0]) in Load |
| file://:0:0:0:0 | [summary param] -1 in LoadOrStore | file://:0:0:0:0 | [summary] to write: return (return[0]) in LoadOrStore |
| file://:0:0:0:0 | [summary param] -1 in Lookup | file://:0:0:0:0 | [summary] to write: return (return[0]) in Lookup |
| file://:0:0:0:0 | [summary param] -1 in MapIndex | file://:0:0:0:0 | [summary] to write: return (return[0]) in MapIndex |
| file://:0:0:0:0 | [summary param] -1 in MapKeys | file://:0:0:0:0 | [summary] to write: return (return[0]) in MapKeys |
| file://:0:0:0:0 | [summary param] -1 in MapRange | file://:0:0:0:0 | [summary] to write: return (return[0]) in MapRange |
| file://:0:0:0:0 | [summary param] -1 in MarshalBinary | file://:0:0:0:0 | [summary] to write: return (return[0]) in MarshalBinary |
| file://:0:0:0:0 | [summary param] -1 in Method | file://:0:0:0:0 | [summary] to write: return (return[0]) in Method |
| file://:0:0:0:0 | [summary param] -1 in MethodByName | file://:0:0:0:0 | [summary] to write: return (return[0]) in MethodByName |
| file://:0:0:0:0 | [summary param] -1 in Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
| file://:0:0:0:0 | [summary param] -1 in Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
| file://:0:0:0:0 | [summary param] -1 in Name | file://:0:0:0:0 | [summary] to write: return (return[0]) in Name |
| file://:0:0:0:0 | [summary param] -1 in Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
| file://:0:0:0:0 | [summary param] -1 in Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
| file://:0:0:0:0 | [summary param] -1 in Open | file://:0:0:0:0 | [summary] to write: return (return[0]) in Open |
| file://:0:0:0:0 | [summary param] -1 in Parse | file://:0:0:0:0 | [summary] to write: return (return[0]) in Parse |
| file://:0:0:0:0 | [summary param] -1 in Password | file://:0:0:0:0 | [summary] to write: return (return[0]) in Password |
| file://:0:0:0:0 | [summary param] -1 in Pointer | file://:0:0:0:0 | [summary] to write: return (return[0]) in Pointer |
| file://:0:0:0:0 | [summary param] -1 in Port | file://:0:0:0:0 | [summary] to write: return (return[0]) in Port |
| file://:0:0:0:0 | [summary param] -1 in Query | file://:0:0:0:0 | [summary] to write: return (return[0]) in Query |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in Read | file://:0:0:0:0 | [summary] to write: argument 0 in Read |
| file://:0:0:0:0 | [summary param] -1 in ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | [summary param] -1 in ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | [summary param] -1 in ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | [summary param] -1 in ReadAt | file://:0:0:0:0 | [summary] to write: argument 0 in ReadAt |
| file://:0:0:0:0 | [summary param] -1 in ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
| file://:0:0:0:0 | [summary param] -1 in ReadDir | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadDir |
| file://:0:0:0:0 | [summary param] -1 in ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
| file://:0:0:0:0 | [summary param] -1 in ReadFile | file://:0:0:0:0 | [summary] to write: return (return[0]) in ReadFile |
| file://:0:0:0:0 | [summary param] -1 in Recv | file://:0:0:0:0 | [summary] to write: return (return[0]) in Recv |
| file://:0:0:0:0 | [summary param] -1 in RequestURI | file://:0:0:0:0 | [summary] to write: return (return[0]) in RequestURI |
| file://:0:0:0:0 | [summary param] -1 in ResolveReference | file://:0:0:0:0 | [summary] to write: return (return[0]) in ResolveReference |
| file://:0:0:0:0 | [summary param] -1 in Slice | file://:0:0:0:0 | [summary] to write: return (return[0]) in Slice |
| file://:0:0:0:0 | [summary param] -1 in Slice3 | file://:0:0:0:0 | [summary] to write: return (return[0]) in Slice3 |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in String | file://:0:0:0:0 | [summary] to write: return (return[0]) in String |
| file://:0:0:0:0 | [summary param] -1 in Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
| file://:0:0:0:0 | [summary param] -1 in Sub | file://:0:0:0:0 | [summary] to write: return (return[0]) in Sub |
| file://:0:0:0:0 | [summary param] -1 in Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | [summary param] -1 in Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | [summary param] -1 in Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | [summary param] -1 in Swap | file://:0:0:0:0 | [summary] to write: return (return[0]) in Swap |
| file://:0:0:0:0 | [summary param] -1 in SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
| file://:0:0:0:0 | [summary param] -1 in SyscallConn | file://:0:0:0:0 | [summary] to write: return (return[0]) in SyscallConn |
| file://:0:0:0:0 | [summary param] -1 in Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
| file://:0:0:0:0 | [summary param] -1 in Token | file://:0:0:0:0 | [summary] to write: return (return[0]) in Token |
| file://:0:0:0:0 | [summary param] -1 in TryRecv | file://:0:0:0:0 | [summary] to write: return (return[0]) in TryRecv |
| file://:0:0:0:0 | [summary param] -1 in UnsafeAddr | file://:0:0:0:0 | [summary] to write: return (return[0]) in UnsafeAddr |
| file://:0:0:0:0 | [summary param] -1 in Username | file://:0:0:0:0 | [summary] to write: return (return[0]) in Username |
| file://:0:0:0:0 | [summary param] -1 in Value | file://:0:0:0:0 | [summary] to write: return (return[0]) in Value |
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| file://:0:0:0:0 | [summary param] -1 in WriteTo | file://:0:0:0:0 | [summary] to write: argument 0 in WriteTo |
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[0] |
| main.go:26:11:26:17 | type assertion | main.go:26:2:26:17 | ... := ...[1] |
| main.go:38:13:38:13 | 1 | main.go:38:7:38:20 | slice literal |

File diff suppressed because it is too large Load Diff

View File

@@ -149,8 +149,9 @@ class SummarizedCallableBase extends TSummarizedCallableBase {
or
result = this.asSyntheticCallable().getParameterType(pos)
or
exists(SyntheticCallable sc | sc = this.asSyntheticCallable() |
Impl::Private::summaryParameterNodeRange(this, pos) and
exists(SyntheticCallable sc, Impl::Private::SummaryNode p | sc = this.asSyntheticCallable() |
Impl::Private::summaryParameterNode(p, pos) and
this = p.getSummarizedCallable() and
not exists(sc.getParameterType(pos)) and
result instanceof TypeObject
)

View File

@@ -54,12 +54,7 @@ private module Cached {
fa.getField() instanceof InstanceField and ia.isImplicitFieldQualifier(fa)
)
} or
TSummaryInternalNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, int pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TFieldValueNode(Field f)
cached
@@ -132,8 +127,6 @@ module Public {
or
result = this.(ImplicitPostUpdateNode).getPreUpdateNode().getType()
or
result = this.(SummaryParameterNode).getTypeImpl()
or
result = this.(FieldValueNode).getField().getType()
}
@@ -378,8 +371,7 @@ module Private {
result.asCallable() = n.(ImplicitInstanceAccess).getInstanceAccess().getEnclosingCallable() or
result.asCallable() = n.(MallocNode).getClassInstanceExpr().getEnclosingCallable() or
result = nodeGetEnclosingCallable(n.(ImplicitPostUpdateNode).getPreUpdateNode()) or
n = TSummaryInternalNode(result.asSummarizedCallable(), _) or
n = TSummaryParameterNode(result.asSummarizedCallable(), _) or
result.asSummarizedCallable() = n.(FlowSummaryNode).getSummarizedCallable() or
result.asFieldScope() = n.(FieldValueNode).getField()
}
@@ -407,7 +399,7 @@ module Private {
or
this = getInstanceArgument(_)
or
this.(SummaryNode).isArgumentOf(_, _)
this.(FlowSummaryNode).isArgumentOf(_, _)
}
/**
@@ -424,7 +416,7 @@ module Private {
or
pos = -1 and this = getInstanceArgument(call.asCall())
or
this.(SummaryNode).isArgumentOf(call, pos)
this.(FlowSummaryNode).isArgumentOf(call, pos)
}
/** Gets the call in which this node is an argument. */
@@ -435,7 +427,7 @@ module Private {
class ReturnNode extends Node {
ReturnNode() {
exists(ReturnStmt ret | this.asExpr() = ret.getResult()) or
this.(SummaryNode).isReturn()
this.(FlowSummaryNode).isReturn()
}
/** Gets the kind of this returned value. */
@@ -447,61 +439,57 @@ module Private {
OutNode() {
this.asExpr() instanceof MethodAccess
or
this.(SummaryNode).isOut(_)
this.(FlowSummaryNode).isOut(_)
}
/** Gets the underlying call. */
DataFlowCall getCall() {
result.asCall() = this.asExpr()
or
this.(SummaryNode).isOut(result)
this.(FlowSummaryNode).isOut(result)
}
}
/**
* A data-flow node used to model flow summaries.
*/
class SummaryNode extends Node, TSummaryInternalNode {
private SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
class FlowSummaryNode extends Node, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
SummaryNode() { this = TSummaryInternalNode(c, state) }
SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override Location getLocation() { result = c.getLocation() }
override Location getLocation() { result = this.getSummarizedCallable().getLocation() }
override string toString() { result = "[summary] " + state + " in " + c }
override string toString() { result = this.getSummaryNode().toString() }
/** Holds if this summary node is the `i`th argument of `call`. */
predicate isArgumentOf(DataFlowCall call, int i) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, i)
FlowSummaryImpl::Private::summaryArgumentNode(call, this.getSummaryNode(), i)
}
/** Holds if this summary node is a return node. */
predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this, _) }
predicate isReturn() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), _) }
/** Holds if this summary node is an out node for `call`. */
predicate isOut(DataFlowCall call) { FlowSummaryImpl::Private::summaryOutNode(call, this, _) }
predicate isOut(DataFlowCall call) {
FlowSummaryImpl::Private::summaryOutNode(call, this.getSummaryNode(), _)
}
}
SummaryNode getSummaryNode(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
result = TSummaryInternalNode(c, state)
}
class SummaryParameterNode extends ParameterNode, TSummaryParameterNode {
private SummarizedCallable sc;
private int pos_;
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
override Location getLocation() { result = sc.getLocation() }
override string toString() { result = "[summary param] " + pos_ + " in " + sc }
override predicate isParameterOf(DataFlowCallable c, int pos) {
c.asSummarizedCallable() = sc and pos = pos_
class SummaryParameterNode extends ParameterNode, FlowSummaryNode {
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _)
}
Type getTypeImpl() { result = sc.getParameterType(pos_) }
private int getPosition() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result)
}
override predicate isParameterOf(DataFlowCallable c, int pos) {
c.asSummarizedCallable() = this.getSummarizedCallable() and pos = this.getPosition()
}
}
}
@@ -523,10 +511,12 @@ private class MallocNode extends Node, TMallocNode {
ClassInstanceExpr getClassInstanceExpr() { result = cie }
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNode {
private Node pre;
private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNode {
private FlowSummaryNode pre;
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), pre.getSummaryNode())
}
override Node getPreUpdateNode() { result = pre }
}

View File

@@ -85,7 +85,8 @@ predicate jumpStep(Node node1, Node node2) {
any(AdditionalValueStep a).step(node1, node2) and
node1.getEnclosingCallable() != node2.getEnclosingCallable()
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(node1, node2)
FlowSummaryImpl::Private::Steps::summaryJumpStep(node1.(FlowSummaryNode).getSummaryNode(),
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -114,7 +115,8 @@ predicate storeStep(Node node1, Content f, Node node2) {
or
f instanceof ArrayContent and arrayStoreStep(node1, node2)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, f, node2)
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), f,
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -145,7 +147,8 @@ predicate readStep(Node node1, Content f, Node node2) {
or
f instanceof CollectionContent and collectionReadStep(node1, node2)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, f, node2)
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), f,
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -160,7 +163,7 @@ predicate clearsContent(Node n, Content c) {
c.(FieldContent).getField() = fa.getField()
)
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
/**
@@ -168,7 +171,7 @@ predicate clearsContent(Node n, Content c) {
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
/**
@@ -200,7 +203,7 @@ pragma[noinline]
DataFlowType getNodeType(Node n) {
result = getErasedRepr(n.getTypeBound())
or
result = FlowSummaryImpl::Private::summaryNodeType(n)
result = FlowSummaryImpl::Private::summaryNodeType(n.(FlowSummaryNode).getSummaryNode())
}
/** Gets a string representation of a type returned by `getErasedRepr`. */
@@ -268,7 +271,7 @@ class DataFlowExpr = Expr;
private newtype TDataFlowCall =
TCall(Call c) or
TSummaryCall(SummarizedCallable c, Node receiver) {
TSummaryCall(SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -318,12 +321,12 @@ class SrcCall extends DataFlowCall, TCall {
/** A synthesized call inside a `SummarizedCallable`. */
class SummaryCall extends DataFlowCall, TSummaryCall {
private SummarizedCallable c;
private Node receiver;
private FlowSummaryImpl::Private::SummaryNode receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
Node getReceiver() { result = receiver }
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
override DataFlowCallable getEnclosingCallable() { result.asSummarizedCallable() = c }
@@ -383,10 +386,7 @@ predicate forceHighPrecision(Content c) {
}
/** Holds if `n` should be hidden from path explanations. */
predicate nodeIsHidden(Node n) {
n instanceof SummaryNode or
n instanceof SummaryParameterNode
}
predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode }
class LambdaCallKind = Method; // the "apply" method in the functional interface
@@ -404,7 +404,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
receiver = call.(SummaryCall).getReceiver() and
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver() and
getNodeDataFlowType(receiver)
.getSourceDeclaration()
.(FunctionalInterface)

View File

@@ -183,7 +183,8 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2) {
node1.(ArgumentNode).argumentOf(any(DataFlowCall c | c.asCall() = ma), argNo)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1, node2, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(node1.(FlowSummaryNode).getSummaryNode(),
node2.(FlowSummaryNode).getSummaryNode(), true)
}
/**

View File

@@ -505,6 +505,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +533,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +562,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +613,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +621,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +644,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +659,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +667,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +675,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +688,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +703,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +716,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +737,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +749,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +764,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +773,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +787,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +799,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +816,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +842,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +854,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +866,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +893,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +905,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +915,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +937,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +962,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1001,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1016,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1029,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1043,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1411,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1424,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1444,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -26,15 +26,17 @@ DataFlowCallable inject(SummarizedCallable c) { result.asSummarizedCallable() =
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { result = -1 }
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = getSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(Node receiver) { result.getReceiver() = receiver }
SummaryCall summaryDataFlowCall(SummaryNode receiver) { result.getReceiver() = receiver }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) { result = c.getType() }
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) {
result = getErasedRepr(c.getParameterType(pos))
}
/** Gets the return type of kind `rk` for callable `c`. */
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) {
result = getErasedRepr(c.getReturnType()) and

View File

@@ -86,6 +86,7 @@ module LocalTaintFlow<nodeSig/1 source, nodeSig/1 sink> {
cached
private module Cached {
private import DataFlowImplCommon as DataFlowImplCommon
private import DataFlowPrivate as DataFlowPrivate
cached
predicate forceCachingInSameStage() { DataFlowImplCommon::forceCachingInSameStage() }
@@ -136,7 +137,8 @@ private module Cached {
)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), sink.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false)
}
/**

View File

@@ -0,0 +1,444 @@
/**
* For internal use only.
*/
private import java
private import semmle.code.Location as Location
private import semmle.code.java.dataflow.DataFlow
private import semmle.code.java.dataflow.TaintTracking
private import semmle.code.java.security.PathCreation
private import semmle.code.java.dataflow.ExternalFlow as ExternalFlow
private import semmle.code.java.dataflow.internal.FlowSummaryImpl as FlowSummaryImpl
private import semmle.code.java.security.ExternalAPIs as ExternalAPIs
private import semmle.code.java.Expr as Expr
private import semmle.code.java.security.QueryInjection
private import semmle.code.java.security.RequestForgery
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
private import AutomodelJavaUtil as AutomodelJavaUtil
private import semmle.code.java.security.PathSanitizer as PathSanitizer
private import AutomodelSharedGetCallable as AutomodelSharedGetCallable
import AutomodelSharedCharacteristics as SharedCharacteristics
import AutomodelEndpointTypes as AutomodelEndpointTypes
newtype JavaRelatedLocationType = CallContext()
/**
* A class representing nodes that are arguments to calls.
*/
private class ArgumentNode extends DataFlow::Node {
ArgumentNode() { this.asExpr() = [any(Call c).getAnArgument(), any(Call c).getQualifier()] }
}
/**
* A candidates implementation.
*
* Some important notes:
* - This mode is using arguments as endpoints.
* - We use the `CallContext` (the surrounding call expression) as related location.
*/
module ApplicationCandidatesImpl implements SharedCharacteristics::CandidateSig {
// for documentation of the implementations here, see the QLDoc in the CandidateSig signature module.
class Endpoint = ArgumentNode;
class EndpointType = AutomodelEndpointTypes::EndpointType;
class NegativeEndpointType = AutomodelEndpointTypes::NegativeSinkType;
class RelatedLocation = Location::Top;
class RelatedLocationType = JavaRelatedLocationType;
// Sanitizers are currently not modeled in MaD. TODO: check if this has large negative impact.
predicate isSanitizer(Endpoint e, EndpointType t) {
exists(t) and
(
e.getType() instanceof BoxedType
or
e.getType() instanceof PrimitiveType
or
e.getType() instanceof NumberType
)
or
t instanceof AutomodelEndpointTypes::TaintedPathSinkType and
e instanceof PathSanitizer::PathInjectionSanitizer
}
RelatedLocation asLocation(Endpoint e) { result = e.asExpr() }
predicate isKnownKind = AutomodelJavaUtil::isKnownKind/3;
predicate isSink(Endpoint e, string kind) {
exists(string package, string type, string name, string signature, string ext, string input |
sinkSpec(e, package, type, name, signature, ext, input) and
ExternalFlow::sinkModel(package, type, _, name, [signature, ""], ext, input, kind, _)
)
or
isCustomSink(e, kind)
}
predicate isNeutral(Endpoint e) {
exists(string package, string type, string name, string signature |
sinkSpec(e, package, type, name, signature, _, _) and
ExternalFlow::neutralModel(package, type, name, [signature, ""], _, _)
)
}
additional predicate sinkSpec(
Endpoint e, string package, string type, string name, string signature, string ext, string input
) {
ApplicationModeGetCallable::getCallable(e).hasQualifiedName(package, type, name) and
signature = ExternalFlow::paramsString(ApplicationModeGetCallable::getCallable(e)) and
ext = "" and
(
exists(Call c, int argIdx |
e.asExpr() = c.getArgument(argIdx) and
input = AutomodelJavaUtil::getArgumentForIndex(argIdx)
)
or
exists(Call c |
e.asExpr() = c.getQualifier() and input = AutomodelJavaUtil::getArgumentForIndex(-1)
)
)
}
/**
* Gets the related location for the given endpoint.
*
* The only related location we model is the the call expression surrounding to
* which the endpoint is either argument or qualifier (known as the call context).
*/
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) {
type = CallContext() and
result = any(Call c | e.asExpr() = [c.getAnArgument(), c.getQualifier()])
}
}
private class JavaCallable = Callable;
private module ApplicationModeGetCallable implements AutomodelSharedGetCallable::GetCallableSig {
class Callable = JavaCallable;
class Endpoint = ApplicationCandidatesImpl::Endpoint;
/**
* Returns the API callable being modeled.
*/
Callable getCallable(Endpoint e) {
exists(Call c |
e.asExpr() = [c.getAnArgument(), c.getQualifier()] and
result = c.getCallee()
)
}
}
/**
* Contains endpoints that are defined in QL code rather than as a MaD model. Ideally this predicate
* should be empty.
*/
private predicate isCustomSink(Endpoint e, string kind) {
e.asExpr() instanceof ArgumentToExec and kind = "command injection"
or
e instanceof RequestForgerySink and kind = "request forgery"
or
e instanceof QueryInjectionSink and kind = "sql"
}
module CharacteristicsImpl =
SharedCharacteristics::SharedCharacteristics<ApplicationCandidatesImpl>;
class EndpointCharacteristic = CharacteristicsImpl::EndpointCharacteristic;
class Endpoint = ApplicationCandidatesImpl::Endpoint;
/*
* Predicates that are used to surface prompt examples and candidates for classification with an ML model.
*/
/**
* A MetadataExtractor that extracts metadata for application mode.
*/
class ApplicationModeMetadataExtractor extends string {
ApplicationModeMetadataExtractor() { this = "ApplicationModeMetadataExtractor" }
predicate hasMetadata(
Endpoint e, string package, string type, string subtypes, string name, string signature,
string input
) {
exists(Call call, Callable callable, int argIdx |
call.getCallee() = callable and
(
e.asExpr() = call.getArgument(argIdx)
or
e.asExpr() = call.getQualifier() and argIdx = -1
) and
input = AutomodelJavaUtil::getArgumentForIndex(argIdx) and
package = callable.getDeclaringType().getPackage().getName() and
// we're using the erased types because the MaD convention is to not specify type parameters.
// Whether something is or isn't a sink doesn't usually depend on the type parameters.
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
name = callable.getName() and
signature = ExternalFlow::paramsString(callable)
)
}
}
/*
* EndpointCharacteristic classes that are specific to Automodel for Java.
*/
/**
* A negative characteristic that indicates that an is-style boolean method is unexploitable even if it is a sink.
*
* A sink is highly unlikely to be exploitable if its callable's name starts with `is` and the callable has a boolean return
* type (e.g. `isDirectory`). These kinds of calls normally do only checks, and appear before the proper call that does
* the dangerous/interesting thing, so we want the latter to be modeled as the sink.
*
* TODO: this might filter too much, it's possible that methods with more than one parameter contain interesting sinks
*/
private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
UnexploitableIsCharacteristic() { this = "unexploitable (is-style boolean method)" }
override predicate appliesToEndpoint(Endpoint e) {
not ApplicationCandidatesImpl::isSink(e, _) and
ApplicationModeGetCallable::getCallable(e).getName().matches("is%") and
ApplicationModeGetCallable::getCallable(e).getReturnType() instanceof BooleanType
}
}
/**
* A negative characteristic that indicates that an existence-checking boolean method is unexploitable even if it is a
* sink.
*
* A sink is highly unlikely to be exploitable if its callable's name is `exists` or `notExists` and the callable has a
* boolean return type. These kinds of calls normally do only checks, and appear before the proper call that does the
* dangerous/interesting thing, so we want the latter to be modeled as the sink.
*/
private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
UnexploitableExistsCharacteristic() { this = "unexploitable (existence-checking boolean method)" }
override predicate appliesToEndpoint(Endpoint e) {
not ApplicationCandidatesImpl::isSink(e, _) and
exists(Callable callable |
callable = ApplicationModeGetCallable::getCallable(e) and
callable.getName().toLowerCase() = ["exists", "notexists"] and
callable.getReturnType() instanceof BooleanType
)
}
}
/**
* A negative characteristic that indicates that an endpoint is an argument to an exception, which is not a sink.
*/
private class ExceptionCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
ExceptionCharacteristic() { this = "exception" }
override predicate appliesToEndpoint(Endpoint e) {
ApplicationModeGetCallable::getCallable(e).getDeclaringType().getASupertype*() instanceof
TypeThrowable
}
}
/**
* A negative characteristic that indicates that an endpoint is a MaD taint step. MaD modeled taint steps are global,
* so they are not sinks for any query. Non-MaD taint steps might be specific to a particular query, so we don't
* filter those out.
*/
private class IsMaDTaintStepCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
IsMaDTaintStepCharacteristic() { this = "taint step" }
override predicate appliesToEndpoint(Endpoint e) {
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(e, _, _) or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(e, _, _) or
FlowSummaryImpl::Private::Steps::summaryGetterStep(e, _, _, _) or
FlowSummaryImpl::Private::Steps::summarySetterStep(e, _, _, _)
}
}
/**
* A negative characteristic that filters out qualifiers that are classes (i.e. static calls). These
* are unlikely to have any non-trivial flow going into them.
*
* Technically, an accessed type _could_ come from outside of the source code, but there's not
* much likelihood of that being user-controlled.
*/
private class ClassQualifierCharacteristic extends CharacteristicsImpl::NotASinkCharacteristic {
ClassQualifierCharacteristic() { this = "class qualifier" }
override predicate appliesToEndpoint(Endpoint e) {
exists(Call c |
e.asExpr() = c.getQualifier() and
c.getQualifier() instanceof TypeAccess
)
}
}
/**
* A call to a method that's known locally will not be considered as a candidate to model.
*
* The reason is that we would expect data/taint flow into the method implementation to uncover
* any sinks that are present there.
*/
private class ArgumentToLocalCall extends CharacteristicsImpl::UninterestingToModelCharacteristic {
ArgumentToLocalCall() { this = "argument to local call" }
override predicate appliesToEndpoint(Endpoint e) {
ApplicationModeGetCallable::getCallable(e).fromSource()
}
}
/**
* A Characteristic that marks endpoints as uninteresting to model, according to the Java ModelExclusions module.
*/
private class ExcludedFromModeling extends CharacteristicsImpl::UninterestingToModelCharacteristic {
ExcludedFromModeling() { this = "excluded from modeling" }
override predicate appliesToEndpoint(Endpoint e) {
ModelExclusions::isUninterestingForModels(ApplicationModeGetCallable::getCallable(e))
}
}
/**
* A negative characteristic that filters out non-public methods. Non-public methods are not interesting to include in
* the standard Java modeling, because they cannot be called from outside the package.
*/
private class NonPublicMethodCharacteristic extends CharacteristicsImpl::UninterestingToModelCharacteristic
{
NonPublicMethodCharacteristic() { this = "non-public method" }
override predicate appliesToEndpoint(Endpoint e) {
not ApplicationModeGetCallable::getCallable(e).isPublic()
}
}
/**
* A negative characteristic that indicates that an endpoint is a non-sink argument to a method whose sinks have already
* been modeled.
*
* WARNING: These endpoints should not be used as negative samples for training, because some sinks may have been missed
* when the method was modeled. Specifically, as we start using ATM to merge in new declarations, we can be less sure
* that a method with one argument modeled as a MaD sink has also had its remaining arguments manually reviewed. The
* ML model might have predicted argument 0 of some method to be a sink but not argument 1, when in fact argument 1 is
* also a sink.
*/
private class OtherArgumentToModeledMethodCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic
{
OtherArgumentToModeledMethodCharacteristic() {
this = "other argument to a method that has already been modeled"
}
override predicate appliesToEndpoint(Endpoint e) {
not ApplicationCandidatesImpl::isSink(e, _) and
exists(DataFlow::Node otherSink |
ApplicationCandidatesImpl::isSink(otherSink, _) and
e.asExpr() = otherSink.asExpr().(Argument).getCall().getAnArgument() and
e != otherSink
)
}
}
/**
* A characteristic that marks functional expression as likely not sinks.
*
* These expressions may well _contain_ sinks, but rarely are sinks themselves.
*/
private class FunctionValueCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic {
FunctionValueCharacteristic() { this = "function value" }
override predicate appliesToEndpoint(Endpoint e) { e.asExpr() instanceof FunctionalExpr }
}
/**
* A negative characteristic that indicates that an endpoint is not a `to` node for any known taint step. Such a node
* cannot be tainted, because taint can't flow into it.
*
* WARNING: These endpoints should not be used as negative samples for training, because they may include sinks for
* which our taint tracking modeling is incomplete.
*/
private class CannotBeTaintedCharacteristic extends CharacteristicsImpl::LikelyNotASinkCharacteristic
{
CannotBeTaintedCharacteristic() { this = "cannot be tainted" }
override predicate appliesToEndpoint(Endpoint e) { not this.isKnownOutNodeForStep(e) }
/**
* Holds if the node `n` is known as the predecessor in a modeled flow step.
*/
private predicate isKnownOutNodeForStep(Endpoint e) {
e.asExpr() instanceof Call or // we just assume flow in that case
TaintTracking::localTaintStep(_, e) or
FlowSummaryImpl::Private::Steps::summaryThroughStepValue(_, e, _) or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(_, e, _) or
FlowSummaryImpl::Private::Steps::summaryGetterStep(_, _, e, _) or
FlowSummaryImpl::Private::Steps::summarySetterStep(_, _, e, _)
}
}
/**
* Holds if the given endpoint has a self-contradictory combination of characteristics. Detects errors in our endpoint
* characteristics. Lists the problematic characteristics and their implications for all such endpoints, together with
* an error message indicating why this combination is problematic.
*
* Copied from
* javascript/ql/experimental/adaptivethreatmodeling/test/endpoint_large_scale/ContradictoryEndpointCharacteristics.ql
*/
predicate erroneousEndpoints(
Endpoint endpoint, EndpointCharacteristic characteristic,
AutomodelEndpointTypes::EndpointType endpointType, float confidence, string errorMessage,
boolean ignoreKnownModelingErrors
) {
// An endpoint's characteristics should not include positive indicators with medium/high confidence for more than one
// sink/source type (including the negative type).
exists(
EndpointCharacteristic characteristic2, AutomodelEndpointTypes::EndpointType endpointClass2,
float confidence2
|
endpointType != endpointClass2 and
(
endpointType instanceof AutomodelEndpointTypes::SinkType and
endpointClass2 instanceof AutomodelEndpointTypes::SinkType
or
endpointType instanceof AutomodelEndpointTypes::SourceType and
endpointClass2 instanceof AutomodelEndpointTypes::SourceType
) and
characteristic.appliesToEndpoint(endpoint) and
characteristic2.appliesToEndpoint(endpoint) and
characteristic.hasImplications(endpointType, true, confidence) and
characteristic2.hasImplications(endpointClass2, true, confidence2) and
confidence > SharedCharacteristics::mediumConfidence() and
confidence2 > SharedCharacteristics::mediumConfidence() and
(
ignoreKnownModelingErrors = true and
not knownOverlappingCharacteristics(characteristic, characteristic2)
or
ignoreKnownModelingErrors = false
)
) and
errorMessage = "Endpoint has high-confidence positive indicators for multiple classes"
or
// An endpoint's characteristics should not include positive indicators with medium/high confidence for some class and
// also include negative indicators with medium/high confidence for this same class.
exists(EndpointCharacteristic characteristic2, float confidence2 |
characteristic.appliesToEndpoint(endpoint) and
characteristic2.appliesToEndpoint(endpoint) and
characteristic.hasImplications(endpointType, true, confidence) and
characteristic2.hasImplications(endpointType, false, confidence2) and
confidence > SharedCharacteristics::mediumConfidence() and
confidence2 > SharedCharacteristics::mediumConfidence()
) and
ignoreKnownModelingErrors = false and
errorMessage = "Endpoint has high-confidence positive and negative indicators for the same class"
}
/**
* Holds if `characteristic1` and `characteristic2` are among the pairs of currently known positive characteristics that
* have some overlap in their results. This indicates a problem with the underlying Java modeling. Specifically,
* `PathCreation` is prone to FPs.
*/
private predicate knownOverlappingCharacteristics(
EndpointCharacteristic characteristic1, EndpointCharacteristic characteristic2
) {
characteristic1 != characteristic2 and
characteristic1 = ["mad taint step", "create path", "read file", "known non-sink"] and
characteristic2 = ["mad taint step", "create path", "read file", "known non-sink"]
}

View File

@@ -0,0 +1,49 @@
/**
* Surfaces the endpoints that are not already known to be sinks, and are therefore used as candidates for
* classification with an ML model.
*
* Note: This query does not actually classify the endpoints using the model.
*
* @name Automodel candidates (application mode)
* @description A query to extract automodel candidates in application mode.
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-application-candidates
* @tags internal extract automodel application-mode candidates
*/
private import AutomodelApplicationModeCharacteristics
private import AutomodelJavaUtil
from
Endpoint endpoint, string message, ApplicationModeMetadataExtractor meta, DollarAtString package,
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
DollarAtString input
where
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
u.appliesToEndpoint(endpoint)
) and
// If a node is already a known sink for any of our existing ATM queries and is already modeled as a MaD sink, we
// don't include it as a candidate. Otherwise, we might include it as a candidate for query A, but the model will
// label it as a sink for one of the sink types of query B, for which it's already a known sink. This would result in
// overlap between our detected sinks and the pre-existing modeling. We assume that, if a sink has already been
// modeled in a MaD model, then it doesn't belong to any additional sink types, and we don't need to reexamine it.
not CharacteristicsImpl::isSink(endpoint, _) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
// The message is the concatenation of all sink types for which this endpoint is known neither to be a sink nor to be
// a non-sink, and we surface only endpoints that have at least one such sink type.
message =
strictconcat(AutomodelEndpointTypes::SinkType sinkType |
not CharacteristicsImpl::isKnownSink(endpoint, sinkType) and
CharacteristicsImpl::isSinkCandidate(endpoint, sinkType)
|
sinkType, ", "
)
select endpoint, message + "\nrelated locations: $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", // method name
signature, "signature", //
input, "input" //

View File

@@ -0,0 +1,73 @@
/**
* Surfaces endpoints that are non-sinks with high confidence, for use as negative examples in the prompt.
*
* @name Negative examples (application mode)
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-application-negative-examples
* @tags internal extract automodel application-mode negative examples
*/
private import java
private import AutomodelApplicationModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelJavaUtil
/**
* Gets a sample of endpoints (of at most `limit` samples) for which the given characteristic applies.
*
* The main purpose of this helper predicate is to avoid selecting too many samples, as this may
* cause the SARIF file to exceed the maximum size limit.
*/
bindingset[limit]
Endpoint getSampleForCharacteristic(EndpointCharacteristic c, int limit) {
exists(int n, int num_endpoints | num_endpoints = count(Endpoint e | c.appliesToEndpoint(e)) |
result =
rank[n](Endpoint e, Location loc |
loc = e.getLocation() and c.appliesToEndpoint(e)
|
e
order by
loc.getFile().getAbsolutePath(), loc.getStartLine(), loc.getStartColumn(),
loc.getEndLine(), loc.getEndColumn()
) and
// To avoid selecting samples that are too close together (as the ranking above goes by file
// path first), we select `limit` evenly spaced samples from the ranked list of endpoints. By
// default this would always include the first sample, so we add a random-chosen prime offset
// to the first sample index, and reduce modulo the number of endpoints.
// Finally, we add 1 to the result, as ranking results in a 1-indexed relation.
n = 1 + (([0 .. limit - 1] * (num_endpoints / limit).floor() + 46337) % num_endpoints)
)
}
from
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
ApplicationModeMetadataExtractor meta, DollarAtString package, DollarAtString type,
DollarAtString subtypes, DollarAtString name, DollarAtString signature, DollarAtString input
where
endpoint = getSampleForCharacteristic(characteristic, 100) and
confidence >= SharedCharacteristics::highConfidence() and
characteristic.hasImplications(any(NegativeSinkType negative), true, confidence) and
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
not erroneousEndpoints(endpoint, _, _, _, _, false) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
// It's valid for a node to satisfy the logic for both `isSink` and `isSanitizer`, but in that case it will be
// treated by the actual query as a sanitizer, since the final logic is something like
// `isSink(n) and not isSanitizer(n)`. We don't want to include such nodes as negative examples in the prompt, because
// they're ambiguous and might confuse the model, so we explicitly exclude all known sinks from the negative examples.
not exists(EndpointCharacteristic characteristic2, float confidence2, SinkType positiveType |
not positiveType instanceof NegativeSinkType and
characteristic2.appliesToEndpoint(endpoint) and
confidence2 >= SharedCharacteristics::maximalConfidence() and
characteristic2.hasImplications(positiveType, true, confidence2)
) and
message = characteristic
select endpoint, message + "\nrelated locations: $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input" //

View File

@@ -0,0 +1,33 @@
/**
* Surfaces endpoints that are sinks with high confidence, for use as positive examples in the prompt.
*
* @name Positive examples (application mode)
* @kind problem
* @problem.severity recommendation
* @id java/ml/extract-automodel-application-positive-examples
* @tags internal extract automodel application-mode positive examples
*/
private import AutomodelApplicationModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelJavaUtil
from
Endpoint endpoint, SinkType sinkType, ApplicationModeMetadataExtractor meta,
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
DollarAtString signature, DollarAtString input
where
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
not erroneousEndpoints(endpoint, _, _, _, _, false) and
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input) and
// Extract positive examples of sinks belonging to the existing ATM query configurations.
CharacteristicsImpl::isKnownSink(endpoint, sinkType)
select endpoint, sinkType + "\nrelated locations: $@." + "\nmetadata: $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, CallContext()), "CallContext", //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input" //

View File

@@ -14,23 +14,11 @@ private import semmle.code.java.Expr as Expr
private import semmle.code.java.security.QueryInjection
private import semmle.code.java.security.RequestForgery
private import semmle.code.java.dataflow.internal.ModelExclusions as ModelExclusions
private import AutomodelJavaUtil as AutomodelJavaUtil
private import AutomodelSharedGetCallable as AutomodelSharedGetCallable
import AutomodelSharedCharacteristics as SharedCharacteristics
import AutomodelEndpointTypes as AutomodelEndpointTypes
/**
* A meta data extractor. Any Java extraction mode needs to implement exactly
* one instance of this class.
*/
abstract class MetadataExtractor extends string {
bindingset[this]
MetadataExtractor() { any() }
abstract predicate hasMetadata(
DataFlow::ParameterNode e, string package, string type, boolean subtypes, string name,
string signature, int input, string parameterName
);
}
newtype JavaRelatedLocationType =
MethodDoc() or
ClassDoc()
@@ -60,31 +48,7 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
RelatedLocation asLocation(Endpoint e) { result = e.asParameter() }
predicate isKnownKind(string kind, string humanReadableKind, EndpointType type) {
kind = "read-file" and
humanReadableKind = "read file" and
type instanceof AutomodelEndpointTypes::TaintedPathSinkType
or
kind = "create-file" and
humanReadableKind = "create file" and
type instanceof AutomodelEndpointTypes::TaintedPathSinkType
or
kind = "sql" and
humanReadableKind = "mad modeled sql" and
type instanceof AutomodelEndpointTypes::SqlSinkType
or
kind = "open-url" and
humanReadableKind = "open url" and
type instanceof AutomodelEndpointTypes::RequestForgerySinkType
or
kind = "jdbc-url" and
humanReadableKind = "jdbc url" and
type instanceof AutomodelEndpointTypes::RequestForgerySinkType
or
kind = "command-injection" and
humanReadableKind = "command injection" and
type instanceof AutomodelEndpointTypes::CommandInjectionSinkType
}
predicate isKnownKind = AutomodelJavaUtil::isKnownKind/3;
predicate isSink(Endpoint e, string kind) {
exists(string package, string type, string name, string signature, string ext, string input |
@@ -103,33 +67,41 @@ module FrameworkCandidatesImpl implements SharedCharacteristics::CandidateSig {
additional predicate sinkSpec(
Endpoint e, string package, string type, string name, string signature, string ext, string input
) {
FrameworkCandidatesImpl::getCallable(e).hasQualifiedName(package, type, name) and
signature = ExternalFlow::paramsString(getCallable(e)) and
FrameworkModeGetCallable::getCallable(e).hasQualifiedName(package, type, name) and
signature = ExternalFlow::paramsString(FrameworkModeGetCallable::getCallable(e)) and
ext = "" and
exists(int paramIdx | e.isParameterOf(_, paramIdx) |
if paramIdx = -1 then input = "Argument[this]" else input = "Argument[" + paramIdx + "]"
input = AutomodelJavaUtil::getArgumentForIndex(paramIdx)
)
}
/**
* Returns the related location for the given endpoint.
* Gets the related location for the given endpoint.
*
* Related locations can be JavaDoc comments of the class or the method.
*/
RelatedLocation getRelatedLocation(Endpoint e, RelatedLocationType type) {
type = MethodDoc() and
result = FrameworkCandidatesImpl::getCallable(e).(Documentable).getJavadoc()
result = FrameworkModeGetCallable::getCallable(e).(Documentable).getJavadoc()
or
type = ClassDoc() and
result = FrameworkCandidatesImpl::getCallable(e).getDeclaringType().(Documentable).getJavadoc()
result = FrameworkModeGetCallable::getCallable(e).getDeclaringType().(Documentable).getJavadoc()
}
}
private class JavaCallable = Callable;
private module FrameworkModeGetCallable implements AutomodelSharedGetCallable::GetCallableSig {
class Callable = JavaCallable;
class Endpoint = FrameworkCandidatesImpl::Endpoint;
/**
* Returns the callable that contains the given endpoint.
*
* Each Java mode should implement this predicate.
*/
additional Callable getCallable(Endpoint e) { result = e.getEnclosingCallable() }
Callable getCallable(Endpoint e) { result = e.getEnclosingCallable() }
}
module CharacteristicsImpl = SharedCharacteristics::SharedCharacteristics<FrameworkCandidatesImpl>;
@@ -145,35 +117,19 @@ class Endpoint = FrameworkCandidatesImpl::Endpoint;
/**
* A MetadataExtractor that extracts metadata for framework mode.
*/
class FrameworkModeMetadataExtractor extends MetadataExtractor {
class FrameworkModeMetadataExtractor extends string {
FrameworkModeMetadataExtractor() { this = "FrameworkModeMetadataExtractor" }
/**
* By convention, the subtypes property of the MaD declaration should only be
* true when there _can_ exist any subtypes with a different implementation.
*
* It would technically be ok to always use the value 'true', but this would
* break convention.
*/
boolean considerSubtypes(Callable callable) {
if
callable.isStatic() or
callable.getDeclaringType().isStatic() or
callable.isFinal() or
callable.getDeclaringType().isFinal()
then result = false
else result = true
}
override predicate hasMetadata(
Endpoint e, string package, string type, boolean subtypes, string name, string signature,
int input, string parameterName
predicate hasMetadata(
Endpoint e, string package, string type, string subtypes, string name, string signature,
string input, string parameterName
) {
exists(Callable callable |
e.asParameter() = callable.getParameter(input) and
exists(Callable callable, int paramIdx |
e.asParameter() = callable.getParameter(paramIdx) and
input = AutomodelJavaUtil::getArgumentForIndex(paramIdx) and
package = callable.getDeclaringType().getPackage().getName() and
type = callable.getDeclaringType().getErasure().(RefType).nestedName() and
subtypes = this.considerSubtypes(callable) and
subtypes = AutomodelJavaUtil::considerSubtypes(callable).toString() and
name = callable.getName() and
parameterName = e.asParameter().getName() and
signature = ExternalFlow::paramsString(callable)
@@ -199,8 +155,8 @@ private class UnexploitableIsCharacteristic extends CharacteristicsImpl::NotASin
override predicate appliesToEndpoint(Endpoint e) {
not FrameworkCandidatesImpl::isSink(e, _) and
FrameworkCandidatesImpl::getCallable(e).getName().matches("is%") and
FrameworkCandidatesImpl::getCallable(e).getReturnType() instanceof BooleanType
FrameworkModeGetCallable::getCallable(e).getName().matches("is%") and
FrameworkModeGetCallable::getCallable(e).getReturnType() instanceof BooleanType
}
}
@@ -218,7 +174,7 @@ private class UnexploitableExistsCharacteristic extends CharacteristicsImpl::Not
override predicate appliesToEndpoint(Endpoint e) {
not FrameworkCandidatesImpl::isSink(e, _) and
exists(Callable callable |
callable = FrameworkCandidatesImpl::getCallable(e) and
callable = FrameworkModeGetCallable::getCallable(e) and
callable.getName().toLowerCase() = ["exists", "notexists"] and
callable.getReturnType() instanceof BooleanType
)
@@ -232,7 +188,7 @@ private class ExceptionCharacteristic extends CharacteristicsImpl::NotASinkChara
ExceptionCharacteristic() { this = "exception" }
override predicate appliesToEndpoint(Endpoint e) {
FrameworkCandidatesImpl::getCallable(e).getDeclaringType().getASupertype*() instanceof
FrameworkModeGetCallable::getCallable(e).getDeclaringType().getASupertype*() instanceof
TypeThrowable
}
}
@@ -258,7 +214,7 @@ private class NonPublicMethodCharacteristic extends CharacteristicsImpl::Uninter
NonPublicMethodCharacteristic() { this = "non-public method" }
override predicate appliesToEndpoint(Endpoint e) {
not FrameworkCandidatesImpl::getCallable(e).isPublic()
not FrameworkModeGetCallable::getCallable(e).isPublic()
}
}

View File

@@ -4,20 +4,21 @@
*
* Note: This query does not actually classify the endpoints using the model.
*
* @name Automodel candidates
* @description A query to extract automodel candidates.
* @name Automodel candidates (framework mode)
* @description A query to extract automodel candidates in framework mode.
* @kind problem
* @severity info
* @id java/ml/extract-automodel-candidates
* @tags internal automodel extract candidates
* @problem.severity recommendation
* @id java/ml/extract-automodel-framework-candidates
* @tags internal extract automodel framework-mode candidates
*/
private import AutomodelFrameworkModeCharacteristics
private import AutomodelSharedUtil
private import AutomodelJavaUtil
from
Endpoint endpoint, string message, MetadataExtractor meta, string package, string type,
boolean subtypes, string name, string signature, int input, string parameterName
Endpoint endpoint, string message, FrameworkModeMetadataExtractor meta, DollarAtString package,
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
DollarAtString input, DollarAtString parameterName
where
not exists(CharacteristicsImpl::UninterestingToModelCharacteristic u |
u.appliesToEndpoint(endpoint)
@@ -42,10 +43,10 @@ select endpoint,
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
type.(DollarAtString), "type", //
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
input.toString().(DollarAtString), "input", //
parameterName.(DollarAtString), "parameterName" //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
parameterName, "parameterName" //

View File

@@ -1,21 +1,22 @@
/**
* Surfaces endpoints that are non-sinks with high confidence, for use as negative examples in the prompt.
*
* @name Negative examples (experimental)
* @name Negative examples (framework mode)
* @kind problem
* @severity info
* @id java/ml/non-sink
* @tags internal automodel extract examples negative
* @problem.severity recommendation
* @id java/ml/extract-automodel-framework-negative-examples
* @tags internal extract automodel framework-mode negative examples
*/
private import AutomodelFrameworkModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelSharedUtil
private import AutomodelJavaUtil
from
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence, string message,
MetadataExtractor meta, string package, string type, boolean subtypes, string name,
string signature, int input, string parameterName
Endpoint endpoint, EndpointCharacteristic characteristic, float confidence,
DollarAtString message, FrameworkModeMetadataExtractor meta, DollarAtString package,
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
DollarAtString input, DollarAtString parameterName
where
characteristic.appliesToEndpoint(endpoint) and
confidence >= SharedCharacteristics::highConfidence() and
@@ -39,10 +40,10 @@ select endpoint,
message + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
type.(DollarAtString), "type", //
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
input.toString().(DollarAtString), "input", //
parameterName.(DollarAtString), "parameterName" //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
parameterName, "parameterName" //

View File

@@ -1,20 +1,21 @@
/**
* Surfaces endpoints that are sinks with high confidence, for use as positive examples in the prompt.
*
* @name Positive examples (experimental)
* @name Positive examples (framework mode)
* @kind problem
* @severity info
* @id java/ml/known-sink
* @tags internal automodel extract examples positive
* @problem.severity recommendation
* @id java/ml/extract-automodel-framework-positive-examples
* @tags internal extract automodel framework-mode positive examples
*/
private import AutomodelFrameworkModeCharacteristics
private import AutomodelEndpointTypes
private import AutomodelSharedUtil
private import AutomodelJavaUtil
from
Endpoint endpoint, SinkType sinkType, MetadataExtractor meta, string package, string type,
boolean subtypes, string name, string signature, int input, string parameterName
Endpoint endpoint, SinkType sinkType, FrameworkModeMetadataExtractor meta, DollarAtString package,
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
DollarAtString input, DollarAtString parameterName
where
// Exclude endpoints that have contradictory endpoint characteristics, because we only want examples we're highly
// certain about in the prompt.
@@ -26,10 +27,10 @@ select endpoint,
sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@.", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
package.(DollarAtString), "package", //
type.(DollarAtString), "type", //
subtypes.toString().(DollarAtString), "subtypes", //
name.(DollarAtString), "name", //
signature.(DollarAtString), "signature", //
input.toString().(DollarAtString), "input", //
parameterName.(DollarAtString), "parameterName" //
package, "package", //
type, "type", //
subtypes, "subtypes", //
name, "name", //
signature, "signature", //
input, "input", //
parameterName, "parameterName" //

View File

@@ -0,0 +1,81 @@
private import java
private import AutomodelEndpointTypes as AutomodelEndpointTypes
/**
* A helper class to represent a string value that can be returned by a query using $@ notation.
*
* It extends `string`, but adds a mock `hasLocationInfo` method that returns the string itself as the file name.
*
* Use this, when you want to return a string value from a query using $@ notation - the string value
* will be included in the sarif file.
*
*
* Background information on `hasLocationInfo`:
* https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-location-information
*/
class DollarAtString extends string {
bindingset[this]
DollarAtString() { any() }
bindingset[this]
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = this and sl = 1 and sc = 1 and el = 1 and ec = 1
}
}
/**
* Holds for all combinations of MaD kinds (`kind`) and their human readable
* descriptions.
*/
predicate isKnownKind(
string kind, string humanReadableKind, AutomodelEndpointTypes::EndpointType type
) {
kind = "read-file" and
humanReadableKind = "read file" and
type instanceof AutomodelEndpointTypes::TaintedPathSinkType
or
kind = "create-file" and
humanReadableKind = "create file" and
type instanceof AutomodelEndpointTypes::TaintedPathSinkType
or
kind = "sql" and
humanReadableKind = "mad modeled sql" and
type instanceof AutomodelEndpointTypes::SqlSinkType
or
kind = "open-url" and
humanReadableKind = "open url" and
type instanceof AutomodelEndpointTypes::RequestForgerySinkType
or
kind = "jdbc-url" and
humanReadableKind = "jdbc url" and
type instanceof AutomodelEndpointTypes::RequestForgerySinkType
or
kind = "command-injection" and
humanReadableKind = "command injection" and
type instanceof AutomodelEndpointTypes::CommandInjectionSinkType
}
/** Gets the models-as-data description for the method argument with the index `index`. */
bindingset[index]
string getArgumentForIndex(int index) {
index = -1 and result = "Argument[this]"
or
index >= 0 and result = "Argument[" + index + "]"
}
/**
* By convention, the subtypes property of the MaD declaration should only be
* true when there _can_ exist any subtypes with a different implementation.
*
* It would technically be ok to always use the value 'true', but this would
* break convention.
*/
boolean considerSubtypes(Callable callable) {
if
callable.isStatic() or
callable.getDeclaringType().isStatic() or
callable.isFinal() or
callable.getDeclaringType().isFinal()
then result = false
else result = true
}

View File

@@ -0,0 +1,21 @@
/**
* An automodel extraction mode instantiates this interface to define how to access
* the callable that's associated with an endpoint.
*/
signature module GetCallableSig {
/**
* A callable is the definition of a method, function, etc. - something that can be called.
*/
class Callable;
/**
* An endpoint is a potential candidate for modeling. This will typically be bound to the language's
* DataFlow node class, or a subtype thereof.
*/
class Endpoint;
/**
* Gets the callable that's associated with the given endpoint.
*/
Callable getCallable(Endpoint endpoint);
}

View File

@@ -1,21 +0,0 @@
/**
* A helper class to represent a string value that can be returned by a query using $@ notation.
*
* It extends `string`, but adds a mock `hasLocationInfo` method that returns the string itself as the file name.
*
* Use this, when you want to return a string value from a query using $@ notation - the string value
* will be included in the sarif file.
*
*
* Background information on `hasLocationInfo`:
* https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/#providing-location-information
*/
class DollarAtString extends string {
bindingset[this]
DollarAtString() { any() }
bindingset[this]
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = this and sl = 1 and sc = 1 and el = 1 and ec = 1
}
}

View File

@@ -12,15 +12,20 @@ predicate taintFlowUpdate(DataFlow::ParameterNode p1, DataFlow::ParameterNode p2
exists(DataFlow::PostUpdateNode ret | localTaint(p1, ret) | ret.getPreUpdateNode() = p2)
}
predicate summaryStep(FlowSummaryNode src, FlowSummaryNode sink) {
FlowSummaryImpl::Private::Steps::summaryLocalStep(src.getSummaryNode(), sink.getSummaryNode(),
false) or
FlowSummaryImpl::Private::Steps::summaryReadStep(src.getSummaryNode(), _, sink.getSummaryNode()) or
FlowSummaryImpl::Private::Steps::summaryStoreStep(src.getSummaryNode(), _, sink.getSummaryNode())
}
from DataFlow::Node src, DataFlow::Node sink
where
(
localAdditionalTaintStep(src, sink) or
FlowSummaryImpl::Private::Steps::summaryThroughStepTaint(src, sink, _)
) and
not FlowSummaryImpl::Private::Steps::summaryLocalStep(src, sink, false) and
not FlowSummaryImpl::Private::Steps::summaryReadStep(src, _, sink) and
not FlowSummaryImpl::Private::Steps::summaryStoreStep(src, _, sink)
not summaryStep(src, sink)
or
exists(ArgumentNode arg, MethodAccess call, DataFlow::ParameterNode p, int i |
src = arg and

View File

@@ -1316,7 +1316,9 @@ newtype TDataFlowCall =
TNormalCall(CallNode call, Function target, CallType type) { resolveCall(call, target, type) } or
TPotentialLibraryCall(CallNode call) or
/** A synthesized call inside a summarized callable */
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
TSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -1448,12 +1450,12 @@ class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall
*/
class SummaryCall extends DataFlowCall, TSummaryCall {
private FlowSummaryImpl::Public::SummarizedCallable c;
private Node receiver;
private FlowSummaryImpl::Private::SummaryNode receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
Node getReceiver() { result = receiver }
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
@@ -1486,44 +1488,35 @@ abstract class ParameterNodeImpl extends Node {
}
/** A parameter for a library callable with a flow summary. */
class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
private FlowSummaryImpl::Public::SummarizedCallable sc;
private ParameterPosition pos;
class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode {
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _)
}
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos) }
private ParameterPosition getPosition() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result)
}
override Parameter getParameter() { none() }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition ppos) {
sc = c.asLibraryCallable() and ppos = pos
}
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc }
override string toString() { result = "parameter " + pos + " of " + sc }
// Hack to return "empty location"
override predicate hasLocationInfo(
string file, int startline, int startcolumn, int endline, int endcolumn
) {
file = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
this.getSummarizedCallable() = c.asLibraryCallable() and ppos = this.getPosition()
}
}
/** A data-flow node used to model flow summaries. */
class SummaryNode extends Node, TSummaryNode {
private FlowSummaryImpl::Public::SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
class FlowSummaryNode extends Node, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
SummaryNode() { this = TSummaryNode(c, state) }
FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
override DataFlowCallable getEnclosingCallable() {
result.asLibraryCallable() = this.getSummarizedCallable()
}
override string toString() { result = "[summary] " + state + " in " + c }
override string toString() { result = this.getSummaryNode().toString() }
// Hack to return "empty location"
override predicate hasLocationInfo(
@@ -1537,26 +1530,30 @@ class SummaryNode extends Node, TSummaryNode {
}
}
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this, rk) }
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) }
override ReturnKind getKind() { result = rk }
}
private class SummaryArgumentNode extends SummaryNode, ArgumentNode {
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
SummaryArgumentNode() {
FlowSummaryImpl::Private::summaryArgumentNode(_, this.getSummaryNode(), _)
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
FlowSummaryImpl::Private::summaryArgumentNode(call, this.getSummaryNode(), pos)
}
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNodeImpl {
private Node pre;
private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNodeImpl {
private FlowSummaryNode pre;
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), pre.getSummaryNode())
}
override Node getPreUpdateNode() { result = pre }
}
@@ -1625,11 +1622,11 @@ private module OutNodes {
}
}
private class SummaryOutNode extends SummaryNode, OutNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
private class SummaryOutNode extends FlowSummaryNode, OutNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this.getSummaryNode(), _) }
override DataFlowCall getCall(ReturnKind kind) {
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
FlowSummaryImpl::Private::summaryOutNode(result, this.getSummaryNode(), kind)
}
}
}

View File

@@ -441,14 +441,16 @@ predicate importTimeSummaryFlowStep(Node nodeFrom, Node nodeTo) {
// This will miss statements inside functions called from the top level.
isTopLevel(nodeFrom) and
isTopLevel(nodeTo) and
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
}
predicate runtimeSummaryFlowStep(Node nodeFrom, Node nodeTo) {
// Anything not at the top level can be executed at runtime.
not isTopLevel(nodeFrom) and
not isTopLevel(nodeTo) and
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
}
/** `ModuleVariable`s are accessed via jump steps at runtime. */
@@ -529,7 +531,8 @@ predicate jumpStep(Node nodeFrom, Node nodeTo) {
or
jumpStepNotSharedWithTypeTracker(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(nodeFrom, nodeTo)
FlowSummaryImpl::Private::Steps::summaryJumpStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -602,7 +605,8 @@ predicate storeStep(Node nodeFrom, Content c, Node nodeTo) {
or
any(Orm::AdditionalOrmSteps es).storeStep(nodeFrom, c, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom, c, nodeTo)
FlowSummaryImpl::Private::Steps::summaryStoreStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
synthStarArgsElementParameterNodeStoreStep(nodeFrom, c, nodeTo)
or
@@ -802,7 +806,8 @@ predicate readStep(Node nodeFrom, Content c, Node nodeTo) {
or
attributeReadStep(nodeFrom, c, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom, c, nodeTo)
FlowSummaryImpl::Private::Steps::summaryReadStep(nodeFrom.(FlowSummaryNode).getSummaryNode(), c,
nodeTo.(FlowSummaryNode).getSummaryNode())
or
synthDictSplatParameterNodeReadStep(nodeFrom, c, nodeTo)
}
@@ -872,7 +877,7 @@ predicate clearsContent(Node n, Content c) {
or
dictClearStep(n, c)
or
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
or
dictSplatParameterNodeClearStep(n, c)
}
@@ -929,9 +934,7 @@ predicate forceHighPrecision(Content c) { none() }
predicate nodeIsHidden(Node n) {
n instanceof ModuleVariableNode
or
n instanceof SummaryNode
or
n instanceof SummaryParameterNode
n instanceof FlowSummaryNode
or
n instanceof SynthStarArgsElementParameterNode
or
@@ -958,7 +961,7 @@ predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c)
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
receiver = call.(SummaryCall).getReceiver() and
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver() and
exists(kind)
}

View File

@@ -105,14 +105,7 @@ newtype TNode =
// So for now we live with having these synthetic ORM nodes for _all_ classes, which
// is a bit wasteful, but we don't think it will hurt too much.
TSyntheticOrmModelNode(Class cls) or
TSummaryNode(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state
) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
/** A synthetic node to capture positional arguments that are passed to a `*args` parameter. */
TSynthStarArgsElementParameterNode(DataFlowCallable callable) {
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))

View File

@@ -505,6 +505,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +533,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +562,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +613,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +621,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +644,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +659,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +667,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +675,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +688,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +703,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +716,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +737,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +749,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +764,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +773,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +787,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +799,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +816,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +842,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +854,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +866,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +893,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +905,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +915,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +937,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +962,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1001,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1016,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1029,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1043,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1411,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1424,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1444,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -47,15 +47,15 @@ DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { none() } // disables implicit summary flow to `this` for callbacks
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(Node receiver) { receiver = result.getReceiver() }
SummaryCall summaryDataFlowCall(SummaryNode receiver) { receiver = result.getReceiver() }
/** Gets the type of content `c`. */
DataFlowType getContentType(Content c) { any() }
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) { any() }
/** Gets the return type of kind `rk` for callable `c`. */
bindingset[c, rk]
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() }

View File

@@ -57,7 +57,9 @@ private module Cached {
or
asyncWithStep(nodeFrom, nodeTo)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom
.(DataFlowPrivate::FlowSummaryNode)
.getSummaryNode(), nodeTo.(DataFlowPrivate::FlowSummaryNode).getSummaryNode(), false)
}
}

View File

@@ -5,12 +5,12 @@ import codeql.ruby.dataflow.internal.DataFlowPrivate
import codeql.ruby.dataflow.internal.DataFlowImplConsistency::Consistency
private class MyConsistencyConfiguration extends ConsistencyConfiguration {
override predicate postWithInFlowExclude(Node n) { n instanceof SummaryNode }
override predicate postWithInFlowExclude(Node n) { n instanceof FlowSummaryNode }
override predicate argHasPostUpdateExclude(ArgumentNode n) {
n instanceof BlockArgumentNode
or
n instanceof SummaryNode
n instanceof FlowSummaryNode
or
n instanceof SynthHashSplatArgumentNode
or

View File

@@ -153,12 +153,12 @@ class DataFlowCall extends TDataFlowCall {
*/
class SummaryCall extends DataFlowCall, TSummaryCall {
private FlowSummaryImpl::Public::SummarizedCallable c;
private DataFlow::Node receiver;
private FlowSummaryImpl::Private::SummaryNode receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
DataFlow::Node getReceiver() { result = receiver }
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
@@ -377,7 +377,9 @@ private module Cached {
cached
newtype TDataFlowCall =
TNormalCall(CfgNodes::ExprNodes::CallCfgNode c) or
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, DataFlow::Node receiver) {
TSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}

View File

@@ -309,24 +309,16 @@ private module Cached {
n = any(CfgNodes::ExprNodes::InstanceVariableAccessCfgNode v).getReceiver()
)
} or
TSummaryNode(
FlowSummaryImpl::Public::SummarizedCallable c,
FlowSummaryImpl::Private::SummaryNodeState state
) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TSummaryParameterNode(FlowSummaryImpl::Public::SummarizedCallable c, ParameterPosition pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TSynthHashSplatArgumentNode(CfgNodes::ExprNodes::CallCfgNode c) {
exists(Argument arg | arg.isArgumentOf(c, any(ArgumentPosition pos | pos.isKeyword(_))))
or
c.getAnArgument() instanceof CfgNodes::ExprNodes::PairCfgNode
}
class TParameterNode =
class TSourceParameterNode =
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or
TSynthHashSplatParameterNode or TSummaryParameterNode;
TSynthHashSplatParameterNode;
cached
Location getLocation(NodeImpl n) { result = n.getLocationImpl() }
@@ -355,7 +347,8 @@ private module Cached {
exprFrom = nodeFrom.(PostUpdateNode).getPreUpdateNode().asExpr()
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
}
/** This is the local flow predicate that is exposed. */
@@ -412,7 +405,9 @@ private module Cached {
cached
predicate isLocalSourceNode(Node n) {
n instanceof TParameterNode
n instanceof TSourceParameterNode
or
n instanceof SummaryParameterNode
or
// Expressions that can't be reached from another entry definition or expression
n instanceof ExprNode and
@@ -514,9 +509,7 @@ predicate nodeIsHidden(Node n) {
or
isDesugarNode(n.(ExprNode).getExprNode().getExpr())
or
n instanceof SummaryNode
or
n instanceof SummaryParameterNode
n instanceof FlowSummaryNode
or
n instanceof SynthHashSplatParameterNode
or
@@ -757,47 +750,41 @@ private module ParameterNodes {
}
/** A parameter for a library callable with a flow summary. */
class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
private FlowSummaryImpl::Public::SummarizedCallable sc;
class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode {
private ParameterPosition pos_;
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos_) }
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), pos_)
}
override Parameter getParameter() { none() }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
sc = c.asLibraryCallable() and pos = pos_
this.getSummarizedCallable() = c.asLibraryCallable() and pos = pos_
}
override CfgScope getCfgScope() { none() }
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = sc }
override EmptyLocation getLocationImpl() { any() }
override string toStringImpl() { result = "parameter " + pos_ + " of " + sc }
}
}
import ParameterNodes
/** A data-flow node used to model flow summaries. */
class SummaryNode extends NodeImpl, TSummaryNode {
FlowSummaryImpl::Public::SummarizedCallable c;
FlowSummaryImpl::Private::SummaryNodeState state;
SummaryNode() { this = TSummaryNode(c, state) }
class FlowSummaryNode extends NodeImpl, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
/** Gets the summarized callable that this node belongs to. */
FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() { result = c }
FlowSummaryImpl::Public::SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override CfgScope getCfgScope() { none() }
override DataFlowCallable getEnclosingCallable() { result.asLibraryCallable() = c }
override DataFlowCallable getEnclosingCallable() {
result.asLibraryCallable() = this.getSummarizedCallable()
}
override EmptyLocation getLocationImpl() { any() }
override string toStringImpl() { result = "[summary] " + state + " in " + c }
override string toStringImpl() { result = this.getSummaryNode().toString() }
}
/** A data-flow node that represents a call argument. */
@@ -857,15 +844,20 @@ private module ArgumentNodes {
}
}
private class SummaryArgumentNode extends SummaryNode, ArgumentNode {
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
private class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
private DataFlowCall call_;
private ArgumentPosition pos_;
SummaryArgumentNode() {
FlowSummaryImpl::Private::summaryArgumentNode(call_, this.getSummaryNode(), pos_)
}
override predicate sourceArgumentOf(CfgNodes::ExprNodes::CallCfgNode call, ArgumentPosition pos) {
none()
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
call = call_ and pos = pos_
}
}
@@ -1029,16 +1021,16 @@ private module ReturnNodes {
override ReturnKind getKind() { result instanceof NewReturnKind }
}
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this, rk) }
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) }
override ReturnKind getKind() {
result = rk
or
exists(NewCall new |
TLibraryCallable(c) = viableLibraryCallable(new) and
TLibraryCallable(this.getSummarizedCallable()) = viableLibraryCallable(new) and
result instanceof NewReturnKind
)
}
@@ -1071,12 +1063,15 @@ private module OutNodes {
}
}
private class SummaryOutNode extends SummaryNode, OutNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
private class SummaryOutNode extends FlowSummaryNode, OutNode {
private DataFlowCall call;
private ReturnKind kind_;
override DataFlowCall getCall(ReturnKind kind) {
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
SummaryOutNode() {
FlowSummaryImpl::Private::summaryOutNode(call, this.getSummaryNode(), kind_)
}
override DataFlowCall getCall(ReturnKind kind) { result = call and kind = kind_ }
}
}
@@ -1091,7 +1086,8 @@ predicate jumpStep(Node pred, Node succ) {
or
succ.asExpr().getExpr().(ConstantReadAccess).getValue() = pred.asExpr().getExpr()
or
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred, succ)
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred.(FlowSummaryNode).getSummaryNode(),
succ.(FlowSummaryNode).getSummaryNode())
or
any(AdditionalJumpStep s).step(pred, succ)
}
@@ -1156,7 +1152,8 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
))
).getReceiver()
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
or
storeStepCommon(node1, c, node2)
}
@@ -1190,7 +1187,8 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
or
node2 = node1.(SynthHashSplatParameterNode).getAKeywordParameter(c)
or
FlowSummaryImpl::Private::Steps::summaryReadStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
/**
@@ -1199,7 +1197,7 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
* in `x.f = newValue`.
*/
predicate clearsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryClearsContent(n.(FlowSummaryNode).getSummaryNode(), c)
or
// Filter out keyword arguments that are part of the method signature from
// the hash-splat parameter
@@ -1220,7 +1218,7 @@ predicate clearsContent(Node n, ContentSet c) {
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c) {
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n, c)
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
}
private newtype TDataFlowType =
@@ -1277,10 +1275,12 @@ private module PostUpdateNodes {
override string toStringImpl() { result = "[post] " + e.toString() }
}
private class SummaryPostUpdateNode extends SummaryNode, PostUpdateNodeImpl {
private Node pre;
private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNodeImpl {
private FlowSummaryNode pre;
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, pre) }
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), pre.getSummaryNode())
}
override Node getPreUpdateNode() { result = pre }
}
@@ -1355,7 +1355,7 @@ predicate lambdaSourceCall(CfgNodes::ExprNodes::CallCfgNode call, LambdaCallKind
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
lambdaSourceCall(call.asCall(), kind, receiver)
or
receiver = call.(SummaryCall).getReceiver() and
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver() and
if receiver.(ParameterNodeImpl).isParameterOf(_, any(ParameterPosition pos | pos.isBlock()))
then kind = TYieldCallKind()
else kind = TLambdaCallKind()

View File

@@ -191,7 +191,7 @@ class ExprNode extends Node, TExprNode {
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParameterNode extends LocalSourceNode, TParameterNode instanceof ParameterNodeImpl {
class ParameterNode extends LocalSourceNode instanceof ParameterNodeImpl {
/** Gets the parameter corresponding to this node, if any. */
final Parameter getParameter() { result = super.getParameter() }

View File

@@ -505,6 +505,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +533,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +562,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +613,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +621,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +644,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +659,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +667,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +675,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +688,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +703,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +716,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +737,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +749,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +764,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +773,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +787,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +799,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +816,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +842,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +854,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +866,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +893,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +905,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +915,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +937,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +962,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1001,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1016,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1029,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1043,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1411,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1424,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1444,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -18,15 +18,15 @@ DataFlowCallable inject(SummarizedCallable c) { result.asLibraryCallable() = c }
/** Gets the parameter position representing a callback itself, if any. */
ArgumentPosition callbackSelfParameterPosition() { none() } // disables implicit summary flow to `self` for callbacks
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(Node receiver) { receiver = result.getReceiver() }
SummaryCall summaryDataFlowCall(SummaryNode receiver) { receiver = result.getReceiver() }
/** Gets the type of content `c`. */
DataFlowType getContentType(ContentSet c) { any() }
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) { any() }
/** Gets the return type of kind `rk` for callable `c`. */
bindingset[c, rk]
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() }

View File

@@ -96,7 +96,8 @@ private module Cached {
)
)
or
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false)
or
any(FlowSteps::AdditionalTaintStep s).step(nodeFrom, nodeTo)
or

View File

@@ -6,5 +6,5 @@ query predicate ret(SourceReturnNode node) { any() }
query predicate arg(ArgumentNode n, DataFlowCall call, ArgumentPosition pos) {
n.argumentOf(call, pos) and
not n instanceof SummaryNode
not n instanceof FlowSummaryNode
}

View File

@@ -2797,43 +2797,43 @@
| UseUseExplosion.rb:21:3686:21:3696 | else ... | UseUseExplosion.rb:21:9:21:3700 | if ... |
| UseUseExplosion.rb:21:3691:21:3696 | call to use | UseUseExplosion.rb:21:3686:21:3696 | else ... |
| UseUseExplosion.rb:24:5:25:7 | use | UseUseExplosion.rb:1:1:26:3 | C |
| file://:0:0:0:0 | [summary param] position 0 in & | file://:0:0:0:0 | [summary] read: argument position 0.any element in & |
| file://:0:0:0:0 | [summary param] position 0 in + | file://:0:0:0:0 | [summary] read: argument position 0.any element in + |
| file://:0:0:0:0 | [summary param] position 0 in ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge |
| file://:0:0:0:0 | [summary param] position 0 in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: argument self in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] position 0 in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] position 0 in Arel.sql | file://:0:0:0:0 | [summary] to write: return (return) in Arel.sql |
| file://:0:0:0:0 | [summary param] position 0 in Base64.decode64() | file://:0:0:0:0 | [summary] to write: return (return) in Base64.decode64() |
| file://:0:0:0:0 | [summary param] position 0 in ERB.new | file://:0:0:0:0 | [summary] to write: return (return) in ERB.new |
| file://:0:0:0:0 | [summary param] position 0 in File.absolute_path | file://:0:0:0:0 | [summary] to write: return (return) in File.absolute_path |
| file://:0:0:0:0 | [summary param] position 0 in File.dirname | file://:0:0:0:0 | [summary] to write: return (return) in File.dirname |
| file://:0:0:0:0 | [summary param] position 0 in File.expand_path | file://:0:0:0:0 | [summary] to write: return (return) in File.expand_path |
| file://:0:0:0:0 | [summary param] position 0 in File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |
| file://:0:0:0:0 | [summary param] position 0 in File.path | file://:0:0:0:0 | [summary] to write: return (return) in File.path |
| file://:0:0:0:0 | [summary param] position 0 in File.realdirpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realdirpath |
| file://:0:0:0:0 | [summary param] position 0 in File.realpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realpath |
| file://:0:0:0:0 | [summary param] position 0 in Hash[] | file://:0:0:0:0 | [summary] read: argument position 0.any element in Hash[] |
| file://:0:0:0:0 | [summary param] position 0 in Mysql2::Client.escape() | file://:0:0:0:0 | [summary] to write: return (return) in Mysql2::Client.escape() |
| file://:0:0:0:0 | [summary param] position 0 in Mysql2::Client.new() | file://:0:0:0:0 | [summary] to write: return (return) in Mysql2::Client.new() |
| file://:0:0:0:0 | [summary param] position 0 in PG.new() | file://:0:0:0:0 | [summary] to write: return (return) in PG.new() |
| file://:0:0:0:0 | [summary param] position 0 in SQLite3::Database.quote() | file://:0:0:0:0 | [summary] to write: return (return) in SQLite3::Database.quote() |
| file://:0:0:0:0 | [summary param] position 0 in Sequel.connect | file://:0:0:0:0 | [summary] to write: return (return) in Sequel.connect |
| file://:0:0:0:0 | [summary param] position 0 in String.try_convert | file://:0:0:0:0 | [summary] to write: return (return) in String.try_convert |
| file://:0:0:0:0 | [summary param] position 0 in \| | file://:0:0:0:0 | [summary] read: argument position 0.any element in \| |
| file://:0:0:0:0 | [summary param] position 1.. in File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |
| file://:0:0:0:0 | [summary param] self in & | file://:0:0:0:0 | [summary] read: argument self.any element in & |
| file://:0:0:0:0 | [summary param] self in * | file://:0:0:0:0 | [summary] read: argument self.any element in * |
| file://:0:0:0:0 | [summary param] self in - | file://:0:0:0:0 | [summary] read: argument self.any element in - |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#<various> | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#<various> |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: argument self in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] self in ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge! |
| file://:0:0:0:0 | [summary param] self in ActiveSupportStringTransform | file://:0:0:0:0 | [summary] to write: return (return) in ActiveSupportStringTransform |
| file://:0:0:0:0 | [summary param] self in [] | file://:0:0:0:0 | [summary] to write: return (return) in [] |
| file://:0:0:0:0 | [summary param] self in \| | file://:0:0:0:0 | [summary] read: argument self.any element in \| |
| file://:0:0:0:0 | [summary param] self in assoc-unknown-arg | file://:0:0:0:0 | [summary] read: argument self.any element in assoc-unknown-arg |
| file://:0:0:0:0 | [summary param] self in each(0) | file://:0:0:0:0 | [summary] read: argument self.any element in each(0) |
| file://:0:0:0:0 | [summary] read: argument position 0.any element in Hash[] | file://:0:0:0:0 | [summary] read: argument position 0.any element.element 1 or unknown in Hash[] |
| file://:0:0:0:0 | parameter position 0 of & | file://:0:0:0:0 | [summary] read: argument position 0.any element in & |
| file://:0:0:0:0 | parameter position 0 of + | file://:0:0:0:0 | [summary] read: argument position 0.any element in + |
| file://:0:0:0:0 | parameter position 0 of ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge |
| file://:0:0:0:0 | parameter position 0 of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: argument self in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter position 0 of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter position 0 of Arel.sql | file://:0:0:0:0 | [summary] to write: return (return) in Arel.sql |
| file://:0:0:0:0 | parameter position 0 of Base64.decode64() | file://:0:0:0:0 | [summary] to write: return (return) in Base64.decode64() |
| file://:0:0:0:0 | parameter position 0 of ERB.new | file://:0:0:0:0 | [summary] to write: return (return) in ERB.new |
| file://:0:0:0:0 | parameter position 0 of File.absolute_path | file://:0:0:0:0 | [summary] to write: return (return) in File.absolute_path |
| file://:0:0:0:0 | parameter position 0 of File.dirname | file://:0:0:0:0 | [summary] to write: return (return) in File.dirname |
| file://:0:0:0:0 | parameter position 0 of File.expand_path | file://:0:0:0:0 | [summary] to write: return (return) in File.expand_path |
| file://:0:0:0:0 | parameter position 0 of File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |
| file://:0:0:0:0 | parameter position 0 of File.path | file://:0:0:0:0 | [summary] to write: return (return) in File.path |
| file://:0:0:0:0 | parameter position 0 of File.realdirpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realdirpath |
| file://:0:0:0:0 | parameter position 0 of File.realpath | file://:0:0:0:0 | [summary] to write: return (return) in File.realpath |
| file://:0:0:0:0 | parameter position 0 of Hash[] | file://:0:0:0:0 | [summary] read: argument position 0.any element in Hash[] |
| file://:0:0:0:0 | parameter position 0 of Mysql2::Client.escape() | file://:0:0:0:0 | [summary] to write: return (return) in Mysql2::Client.escape() |
| file://:0:0:0:0 | parameter position 0 of Mysql2::Client.new() | file://:0:0:0:0 | [summary] to write: return (return) in Mysql2::Client.new() |
| file://:0:0:0:0 | parameter position 0 of PG.new() | file://:0:0:0:0 | [summary] to write: return (return) in PG.new() |
| file://:0:0:0:0 | parameter position 0 of SQLite3::Database.quote() | file://:0:0:0:0 | [summary] to write: return (return) in SQLite3::Database.quote() |
| file://:0:0:0:0 | parameter position 0 of Sequel.connect | file://:0:0:0:0 | [summary] to write: return (return) in Sequel.connect |
| file://:0:0:0:0 | parameter position 0 of String.try_convert | file://:0:0:0:0 | [summary] to write: return (return) in String.try_convert |
| file://:0:0:0:0 | parameter position 0 of \| | file://:0:0:0:0 | [summary] read: argument position 0.any element in \| |
| file://:0:0:0:0 | parameter position 1.. of File.join | file://:0:0:0:0 | [summary] to write: return (return) in File.join |
| file://:0:0:0:0 | parameter self of & | file://:0:0:0:0 | [summary] read: argument self.any element in & |
| file://:0:0:0:0 | parameter self of * | file://:0:0:0:0 | [summary] read: argument self.any element in * |
| file://:0:0:0:0 | parameter self of - | file://:0:0:0:0 | [summary] read: argument self.any element in - |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#<various> | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#<various> |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#merge | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: argument self in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter self of ActionController::Parameters#merge! | file://:0:0:0:0 | [summary] to write: return (return) in ActionController::Parameters#merge! |
| file://:0:0:0:0 | parameter self of ActiveSupportStringTransform | file://:0:0:0:0 | [summary] to write: return (return) in ActiveSupportStringTransform |
| file://:0:0:0:0 | parameter self of [] | file://:0:0:0:0 | [summary] to write: return (return) in [] |
| file://:0:0:0:0 | parameter self of \| | file://:0:0:0:0 | [summary] read: argument self.any element in \| |
| file://:0:0:0:0 | parameter self of assoc-unknown-arg | file://:0:0:0:0 | [summary] read: argument self.any element in assoc-unknown-arg |
| file://:0:0:0:0 | parameter self of each(0) | file://:0:0:0:0 | [summary] read: argument self.any element in each(0) |
| local_dataflow.rb:1:1:7:3 | self (foo) | local_dataflow.rb:3:8:3:10 | self |
| local_dataflow.rb:1:1:7:3 | self in foo | local_dataflow.rb:1:1:7:3 | self (foo) |
| local_dataflow.rb:1:1:150:3 | self (local_dataflow.rb) | local_dataflow.rb:49:1:53:3 | self |

View File

@@ -57,17 +57,17 @@ pathnameInstances
| Pathname.rb:39:12:39:19 | foo_path |
| Pathname.rb:41:1:41:3 | p08 |
| Pathname.rb:42:1:42:3 | p01 |
| file://:0:0:0:0 | parameter position 0 of + |
| file://:0:0:0:0 | parameter self of + |
| file://:0:0:0:0 | parameter self of Pathname;Method[cleanpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[expand_path] |
| file://:0:0:0:0 | parameter self of Pathname;Method[realpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | parameter self of Pathname;Method[sub_ext] |
| file://:0:0:0:0 | parameter self of Pathname;Method[to_path] |
| file://:0:0:0:0 | parameter self of join |
| file://:0:0:0:0 | parameter self of sub |
| file://:0:0:0:0 | parameter self of to_s |
| file://:0:0:0:0 | [summary param] position 0 in + |
| file://:0:0:0:0 | [summary param] self in + |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[cleanpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[expand_path] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[realpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[sub_ext] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[to_path] |
| file://:0:0:0:0 | [summary param] self in join |
| file://:0:0:0:0 | [summary param] self in sub |
| file://:0:0:0:0 | [summary param] self in to_s |
fileSystemAccesses
| Pathname.rb:26:12:26:24 | call to open | Pathname.rb:26:12:26:19 | foo_path |
| Pathname.rb:28:11:28:22 | call to opendir | Pathname.rb:28:11:28:14 | pwd1 |
@@ -134,17 +134,17 @@ fileNameSources
| Pathname.rb:39:12:39:19 | foo_path |
| Pathname.rb:41:1:41:3 | p08 |
| Pathname.rb:42:1:42:3 | p01 |
| file://:0:0:0:0 | parameter position 0 of + |
| file://:0:0:0:0 | parameter self of + |
| file://:0:0:0:0 | parameter self of Pathname;Method[cleanpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[expand_path] |
| file://:0:0:0:0 | parameter self of Pathname;Method[realpath] |
| file://:0:0:0:0 | parameter self of Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | parameter self of Pathname;Method[sub_ext] |
| file://:0:0:0:0 | parameter self of Pathname;Method[to_path] |
| file://:0:0:0:0 | parameter self of join |
| file://:0:0:0:0 | parameter self of sub |
| file://:0:0:0:0 | parameter self of to_s |
| file://:0:0:0:0 | [summary param] position 0 in + |
| file://:0:0:0:0 | [summary param] self in + |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[cleanpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[expand_path] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[realpath] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[relative_path_from] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[sub_ext] |
| file://:0:0:0:0 | [summary param] self in Pathname;Method[to_path] |
| file://:0:0:0:0 | [summary param] self in join |
| file://:0:0:0:0 | [summary param] self in sub |
| file://:0:0:0:0 | [summary param] self in to_s |
fileSystemReadAccesses
| Pathname.rb:32:12:32:24 | call to read | Pathname.rb:32:12:32:24 | call to read |
fileSystemWriteAccesses

View File

@@ -9,6 +9,7 @@
#include <filesystem>
#include "swift/extractor/trap/generated/TrapEntries.h"
#include "swift/extractor/infra/file/PathHash.h"
namespace codeql {

View File

@@ -9,7 +9,26 @@ swift_cc_library(
hdrs = glob(
["*.h"],
exclude = ["FsLogger.h"],
),
) + [":path_hash_workaround"],
visibility = ["//swift:__subpackages__"],
deps = ["//swift/logging"],
)
genrule(
name = "path_hash_workaround",
srcs = [
"PathHash.h.workaround",
"PathHash.h.fixed",
],
outs = ["PathHash.h"],
# see if https://cplusplus.github.io/LWG/issue3657 is fixed with the current compiler or not
# if fixed, PathHash.h.workaround will not compile
cmd = "\n".join([
"if clang -c -x c++ -std=c++20 -Wno-pragma-once-outside-header \\",
" $(rootpath PathHash.h.workaround) -o /dev/null &> /dev/null; then",
" cp $(rootpath PathHash.h.workaround) $@",
"else",
" cp $(rootpath PathHash.h.fixed) $@",
"fi",
]),
)

View File

@@ -0,0 +1,4 @@
#pragma once
#include <filesystem>
#include <functional>

View File

@@ -0,0 +1,17 @@
#pragma once
#include <filesystem>
#include <functional>
// workaround for https://cplusplus.github.io/LWG/issue3657
// notice that theoretically by the standard you are not allowed to specialize on std types...
// but it works, and this is recognized as a defect of the standard.
// Using a non-standard Hasher type would be a huge pain, as the automatic hash implementation of
// std::variant would not kick in (we use std::filesystem::path in a variant used as a map key).
namespace std {
template <>
struct hash<filesystem::path> {
size_t operator()(const filesystem::path& path) const { return hash_value(path); }
};
} // namespace std

View File

@@ -75,7 +75,9 @@ newtype TDataFlowCall =
TPropertySetterCall(PropertySetterCfgNode setter) or
TPropertyObserverCall(PropertyObserverCfgNode observer) or
TKeyPathCall(KeyPathApplicationExprCfgNode keyPathApplication) or
TSummaryCall(FlowSummaryImpl::Public::SummarizedCallable c, Node receiver) {
TSummaryCall(
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
) {
FlowSummaryImpl::Private::summaryCallbackRange(c, receiver)
}
@@ -232,12 +234,12 @@ class PropertyObserverCall extends DataFlowCall, TPropertyObserverCall {
class SummaryCall extends DataFlowCall, TSummaryCall {
private FlowSummaryImpl::Public::SummarizedCallable c;
private Node receiver;
private FlowSummaryImpl::Private::SummaryNode receiver;
SummaryCall() { this = TSummaryCall(c, receiver) }
/** Gets the data flow node that this call targets. */
Node getReceiver() { result = receiver }
FlowSummaryImpl::Private::SummaryNode getReceiver() { result = receiver }
override DataFlowCallable getEnclosingCallable() { result = TSummarizedCallable(c) }

View File

@@ -90,16 +90,11 @@ private module Cached {
TPatternNode(CfgNode n, Pattern p) { hasPatternNode(n, p) } or
TSsaDefinitionNode(Ssa::Definition def) or
TInoutReturnNode(ParamDecl param) { modifiableParam(param) } or
TSummaryNode(FlowSummary::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNodeState state) {
FlowSummaryImpl::Private::summaryNodeRange(c, state)
} or
TFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or
TSourceParameterNode(ParamDecl param) or
TKeyPathParameterNode(EntryNode entry) { entry.getScope() instanceof KeyPathExpr } or
TKeyPathReturnNode(ExitNode exit) { exit.getScope() instanceof KeyPathExpr } or
TKeyPathComponentNode(KeyPathComponent component) or
TSummaryParameterNode(FlowSummary::SummarizedCallable c, ParameterPosition pos) {
FlowSummaryImpl::Private::summaryParameterNodeRange(c, pos)
} or
TExprPostUpdateNode(CfgNode n) {
// Obviously, the base of setters needs a post-update node
n = any(PropertySetterCfgNode setter).getBase()
@@ -223,7 +218,8 @@ private module Cached {
nodeFrom.(KeyPathParameterNode).getComponent(0)
or
// flow through a flow summary (extension of `SummaryModelCsv`)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, true)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), true)
}
/**
@@ -318,22 +314,19 @@ private module ParameterNodes {
override ParamDecl getParameter() { result = param }
}
class SummaryParameterNode extends ParameterNodeImpl, TSummaryParameterNode {
FlowSummary::SummarizedCallable sc;
ParameterPosition pos;
SummaryParameterNode() { this = TSummaryParameterNode(sc, pos) }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition p) {
c.getUnderlyingCallable() = sc and
p = pos
class SummaryParameterNode extends ParameterNodeImpl, FlowSummaryNode {
SummaryParameterNode() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), _)
}
override Location getLocationImpl() { result = sc.getLocation() }
private ParameterPosition getPosition() {
FlowSummaryImpl::Private::summaryParameterNode(this.getSummaryNode(), result)
}
override string toStringImpl() { result = "[summary param] " + pos + " in " + sc }
override DataFlowCallable getEnclosingCallable() { this.isParameterOf(result, _) }
override predicate isParameterOf(DataFlowCallable c, ParameterPosition p) {
c.getUnderlyingCallable() = this.getSummarizedCallable() and
p = this.getPosition()
}
}
class KeyPathParameterNode extends ParameterNodeImpl, TKeyPathParameterNode {
@@ -362,17 +355,20 @@ private module ParameterNodes {
import ParameterNodes
/** A data-flow node used to model flow summaries. */
class SummaryNode extends NodeImpl, TSummaryNode {
private FlowSummaryImpl::Public::SummarizedCallable c;
private FlowSummaryImpl::Private::SummaryNodeState state;
class FlowSummaryNode extends NodeImpl, TFlowSummaryNode {
FlowSummaryImpl::Private::SummaryNode getSummaryNode() { this = TFlowSummaryNode(result) }
SummaryNode() { this = TSummaryNode(c, state) }
FlowSummary::SummarizedCallable getSummarizedCallable() {
result = this.getSummaryNode().getSummarizedCallable()
}
override DataFlowCallable getEnclosingCallable() { result.asSummarizedCallable() = c }
override DataFlowCallable getEnclosingCallable() {
result.asSummarizedCallable() = this.getSummarizedCallable()
}
override UnknownLocation getLocationImpl() { any() }
override Location getLocationImpl() { result = this.getSummarizedCallable().getLocation() }
override string toStringImpl() { result = "[summary] " + state + " in " + c }
override string toStringImpl() { result = this.getSummaryNode().toString() }
}
/** A data-flow node that represents a call argument. */
@@ -448,11 +444,13 @@ private module ArgumentNodes {
}
}
class SummaryArgumentNode extends SummaryNode, ArgumentNode {
SummaryArgumentNode() { FlowSummaryImpl::Private::summaryArgumentNode(_, this, _) }
class SummaryArgumentNode extends FlowSummaryNode, ArgumentNode {
SummaryArgumentNode() {
FlowSummaryImpl::Private::summaryArgumentNode(_, this.getSummaryNode(), _)
}
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
FlowSummaryImpl::Private::summaryArgumentNode(call, this, pos)
FlowSummaryImpl::Private::summaryArgumentNode(call, this.getSummaryNode(), pos)
}
}
@@ -521,10 +519,10 @@ private module ReturnNodes {
override string toStringImpl() { result = param.toString() + "[return]" }
}
private class SummaryReturnNode extends SummaryNode, ReturnNode {
private class SummaryReturnNode extends FlowSummaryNode, ReturnNode {
private ReturnKind rk;
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this, rk) }
SummaryReturnNode() { FlowSummaryImpl::Private::summaryReturnNode(this.getSummaryNode(), rk) }
override ReturnKind getKind() { result = rk }
}
@@ -577,11 +575,11 @@ private module OutNodes {
}
}
class SummaryOutNode extends OutNode, SummaryNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this, _) }
class SummaryOutNode extends OutNode, FlowSummaryNode {
SummaryOutNode() { FlowSummaryImpl::Private::summaryOutNode(_, this.getSummaryNode(), _) }
override DataFlowCall getCall(ReturnKind kind) {
FlowSummaryImpl::Private::summaryOutNode(result, this, kind)
FlowSummaryImpl::Private::summaryOutNode(result, this.getSummaryNode(), kind)
}
}
@@ -642,7 +640,8 @@ private module OutNodes {
import OutNodes
predicate jumpStep(Node pred, Node succ) {
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred, succ)
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred.(FlowSummaryNode).getSummaryNode(),
succ.(FlowSummaryNode).getSummaryNode())
}
predicate storeStep(Node node1, ContentSet c, Node node2) {
@@ -692,7 +691,8 @@ predicate storeStep(Node node1, ContentSet c, Node node2) {
init.isFailable()
)
or
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1, c, node2)
FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
}
predicate isLValue(Expr e) { any(AssignExpr assign).getDest() = e }
@@ -830,11 +830,14 @@ private module PostUpdateNodes {
override DataFlowCallable getEnclosingCallable() { result = TDataFlowFunc(n.getScope()) }
}
class SummaryPostUpdateNode extends SummaryNode, PostUpdateNodeImpl {
SummaryPostUpdateNode() { FlowSummaryImpl::Private::summaryPostUpdateNode(this, _) }
class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNodeImpl {
SummaryPostUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(), _)
}
override Node getPreUpdateNode() {
FlowSummaryImpl::Private::summaryPostUpdateNode(this, result)
FlowSummaryImpl::Private::summaryPostUpdateNode(this.getSummaryNode(),
result.(FlowSummaryNode).getSummaryNode())
}
}
}
@@ -883,7 +886,7 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
receiver.asExpr() = call.asCall().getExpr().(ApplyExpr).getFunction()
or
kind = TLambdaCallKind() and
receiver = call.(SummaryCall).getReceiver()
receiver.(FlowSummaryNode).getSummaryNode() = call.(SummaryCall).getReceiver()
or
kind = TLambdaCallKind() and
receiver.asExpr() = call.asKeyPath().getExpr().(KeyPathApplicationExpr).getKeyPath()

View File

@@ -505,6 +505,9 @@ module Private {
or
// Add the post-update node corresponding to the requested argument node
outputState(c, s) and isCallbackParameter(s)
or
// Add the parameter node for parameter side-effects
outputState(c, s) and s = SummaryComponentStack::argument(_)
}
private newtype TSummaryNodeState =
@@ -530,7 +533,7 @@ module Private {
* this state represents that the components in `s` _remain to be written_ to
* the output.
*/
class SummaryNodeState extends TSummaryNodeState {
private class SummaryNodeState extends TSummaryNodeState {
/** Holds if this state is a valid input state for `c`. */
pragma[nomagic]
predicate isInputState(SummarizedCallable c, SummaryComponentStack s) {
@@ -559,6 +562,42 @@ module Private {
}
}
private newtype TSummaryNode =
TSummaryInternalNode(SummarizedCallable c, SummaryNodeState state) {
summaryNodeRange(c, state)
} or
TSummaryParameterNode(SummarizedCallable c, ParameterPosition pos) {
summaryParameterNodeRange(c, pos)
}
abstract class SummaryNode extends TSummaryNode {
abstract string toString();
abstract SummarizedCallable getSummarizedCallable();
}
private class SummaryInternalNode extends SummaryNode, TSummaryInternalNode {
private SummarizedCallable c;
private SummaryNodeState state;
SummaryInternalNode() { this = TSummaryInternalNode(c, state) }
override string toString() { result = "[summary] " + state + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
private class SummaryParamNode extends SummaryNode, TSummaryParameterNode {
private SummarizedCallable c;
private ParameterPosition pos;
SummaryParamNode() { this = TSummaryParameterNode(c, pos) }
override string toString() { result = "[summary param] " + pos + " in " + c }
override SummarizedCallable getSummarizedCallable() { result = c }
}
/**
* Holds if `state` represents having read from a parameter at position
* `pos` in `c`. In this case we are not synthesizing a data-flow node,
@@ -574,7 +613,7 @@ module Private {
* Holds if a synthesized summary node is needed for the state `state` in summarized
* callable `c`.
*/
predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
private predicate summaryNodeRange(SummarizedCallable c, SummaryNodeState state) {
state.isInputState(c, _) and
not parameterReadState(c, state, _)
or
@@ -582,22 +621,22 @@ module Private {
}
pragma[noinline]
private Node summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeInputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state | state.isInputState(c, s) |
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
or
exists(ParameterPosition pos |
parameterReadState(c, state, pos) and
result.(ParamNode).isParameterOf(inject(c), pos)
result = TSummaryParameterNode(c, pos)
)
)
}
pragma[noinline]
private Node summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
private SummaryNode summaryNodeOutputState(SummarizedCallable c, SummaryComponentStack s) {
exists(SummaryNodeState state |
state.isOutputState(c, s) and
result = summaryNode(c, state)
result = TSummaryInternalNode(c, state)
)
}
@@ -605,12 +644,14 @@ module Private {
* Holds if a write targets `post`, which is a post-update node for a
* parameter at position `pos` in `c`.
*/
private predicate isParameterPostUpdate(Node post, SummarizedCallable c, ParameterPosition pos) {
private predicate isParameterPostUpdate(
SummaryNode post, SummarizedCallable c, ParameterPosition pos
) {
post = summaryNodeOutputState(c, SummaryComponentStack::argument(pos))
}
/** Holds if a parameter node at position `pos` is required for `c`. */
predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
private predicate summaryParameterNodeRange(SummarizedCallable c, ParameterPosition pos) {
parameterReadState(c, _, pos)
or
// Same as `isParameterPostUpdate(_, c, pos)`, but can be used in a negative context
@@ -618,7 +659,7 @@ module Private {
}
private predicate callbackOutput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ReturnKind rk
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ReturnKind rk
) {
any(SummaryNodeState state).isInputState(c, s) and
s.head() = TReturnSummaryComponent(rk) and
@@ -626,7 +667,7 @@ module Private {
}
private predicate callbackInput(
SummarizedCallable c, SummaryComponentStack s, Node receiver, ArgumentPosition pos
SummarizedCallable c, SummaryComponentStack s, SummaryNode receiver, ArgumentPosition pos
) {
any(SummaryNodeState state).isOutputState(c, s) and
s.head() = TParameterSummaryComponent(pos) and
@@ -634,7 +675,7 @@ module Private {
}
/** Holds if a call targeting `receiver` should be synthesized inside `c`. */
predicate summaryCallbackRange(SummarizedCallable c, Node receiver) {
predicate summaryCallbackRange(SummarizedCallable c, SummaryNode receiver) {
callbackOutput(c, _, receiver, _)
or
callbackInput(c, _, receiver, _)
@@ -647,10 +688,10 @@ module Private {
* `getContentType()`, `getReturnType()`, `getCallbackParameterType()`, and
* `getCallbackReturnType()`.
*/
DataFlowType summaryNodeType(Node n) {
exists(Node pre |
DataFlowType summaryNodeType(SummaryNode n) {
exists(SummaryNode pre |
summaryPostUpdateNode(n, pre) and
result = getNodeType(pre)
result = summaryNodeType(pre)
)
or
exists(SummarizedCallable c, SummaryComponentStack s, SummaryComponent head | head = s.head() |
@@ -662,12 +703,12 @@ module Private {
)
or
head = TWithoutContentSummaryComponent(_) and
result = getNodeType(summaryNodeInputState(c, s.tail()))
result = summaryNodeType(summaryNodeInputState(c, s.tail()))
or
exists(ReturnKind rk |
head = TReturnSummaryComponent(rk) and
result =
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackReturnType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), rk)
)
or
@@ -675,6 +716,11 @@ module Private {
head = TSyntheticGlobalSummaryComponent(sg) and
result = getSyntheticGlobalType(sg)
)
or
exists(ParameterPosition pos |
head = TArgumentSummaryComponent(pos) and
result = getParameterType(c, pos)
)
)
or
n = summaryNodeOutputState(c, s) and
@@ -691,7 +737,7 @@ module Private {
or
exists(ArgumentPosition pos | head = TParameterSummaryComponent(pos) |
result =
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
getCallbackParameterType(summaryNodeType(summaryNodeInputState(pragma[only_bind_out](c),
s.tail())), pos)
)
or
@@ -703,9 +749,14 @@ module Private {
)
}
/** Holds if summary node `p` is a parameter with position `pos`. */
predicate summaryParameterNode(SummaryNode p, ParameterPosition pos) {
p = TSummaryParameterNode(_, pos)
}
/** Holds if summary node `out` contains output of kind `rk` from call `c`. */
predicate summaryOutNode(DataFlowCall c, Node out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryOutNode(DataFlowCall c, SummaryNode out, ReturnKind rk) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackOutput(callable, s, receiver, rk) and
out = summaryNodeInputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -713,8 +764,8 @@ module Private {
}
/** Holds if summary node `arg` is at position `pos` in the call `c`. */
predicate summaryArgumentNode(DataFlowCall c, Node arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, Node receiver |
predicate summaryArgumentNode(DataFlowCall c, SummaryNode arg, ArgumentPosition pos) {
exists(SummarizedCallable callable, SummaryComponentStack s, SummaryNode receiver |
callbackInput(callable, s, receiver, pos) and
arg = summaryNodeOutputState(callable, s) and
c = summaryDataFlowCall(receiver)
@@ -722,10 +773,10 @@ module Private {
}
/** Holds if summary node `post` is a post-update node with pre-update node `pre`. */
predicate summaryPostUpdateNode(Node post, Node pre) {
predicate summaryPostUpdateNode(SummaryNode post, SummaryNode pre) {
exists(SummarizedCallable c, ParameterPosition pos |
isParameterPostUpdate(post, c, pos) and
pre.(ParamNode).isParameterOf(inject(c), pos)
pre = TSummaryParameterNode(c, pos)
)
or
exists(SummarizedCallable callable, SummaryComponentStack s |
@@ -736,7 +787,7 @@ module Private {
}
/** Holds if summary node `ret` is a return node of kind `rk`. */
predicate summaryReturnNode(Node ret, ReturnKind rk) {
predicate summaryReturnNode(SummaryNode ret, ReturnKind rk) {
exists(SummaryComponentStack s |
ret = summaryNodeOutputState(_, s) and
s = TSingletonSummaryComponentStack(TReturnSummaryComponent(rk))
@@ -748,7 +799,9 @@ module Private {
* node, and back out to `p`.
*/
predicate summaryAllowParameterReturnInSelf(ParamNode p) {
exists(SummarizedCallable c, ParameterPosition ppos | p.isParameterOf(inject(c), ppos) |
exists(SummarizedCallable c, ParameterPosition ppos |
p.isParameterOf(inject(c), pragma[only_bind_into](ppos))
|
exists(SummaryComponentStack inputContents, SummaryComponentStack outputContents |
summary(c, inputContents, outputContents, _) and
inputContents.bottom() = pragma[only_bind_into](TArgumentSummaryComponent(ppos)) and
@@ -763,7 +816,7 @@ module Private {
* Holds if there is a local step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryLocalStep(Node pred, Node succ, boolean preservesValue) {
predicate summaryLocalStep(SummaryNode pred, SummaryNode succ, boolean preservesValue) {
exists(
SummarizedCallable c, SummaryComponentStack inputContents,
SummaryComponentStack outputContents
@@ -789,7 +842,7 @@ module Private {
* Holds if there is a read step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryReadStep(Node pred, ContentSet c, Node succ) {
predicate summaryReadStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeInputState(sc, s.tail()) and
succ = summaryNodeInputState(sc, s) and
@@ -801,7 +854,7 @@ module Private {
* Holds if there is a store step of content `c` from `pred` to `succ`, which
* is synthesized from a flow summary.
*/
predicate summaryStoreStep(Node pred, ContentSet c, Node succ) {
predicate summaryStoreStep(SummaryNode pred, ContentSet c, SummaryNode succ) {
exists(SummarizedCallable sc, SummaryComponentStack s |
pred = summaryNodeOutputState(sc, s) and
succ = summaryNodeOutputState(sc, s.tail()) and
@@ -813,7 +866,7 @@ module Private {
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
* from a flow summary.
*/
predicate summaryJumpStep(Node pred, Node succ) {
predicate summaryJumpStep(SummaryNode pred, SummaryNode succ) {
exists(SummaryComponentStack s |
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
pred = summaryNodeOutputState(_, s) and
@@ -840,9 +893,9 @@ module Private {
* `a` on line 2 to the post-update node for `a` on that line (via an intermediate
* node where field `b` is cleared).
*/
predicate summaryClearsContent(Node n, ContentSet c) {
predicate summaryClearsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withoutContent(c)
)
@@ -852,9 +905,9 @@ module Private {
* Holds if the value that is being tracked is expected to be stored inside
* content `c` at `n`.
*/
predicate summaryExpectsContent(Node n, ContentSet c) {
predicate summaryExpectsContent(SummaryNode n, ContentSet c) {
exists(SummarizedCallable sc, SummaryNodeState state, SummaryComponentStack stack |
n = summaryNode(sc, state) and
n = TSummaryInternalNode(sc, state) and
state.isInputState(sc, stack) and
stack.head() = SummaryComponent::withContent(c)
)
@@ -862,17 +915,17 @@ module Private {
pragma[noinline]
private predicate viableParam(
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, ParamNode p
DataFlowCall call, SummarizedCallable sc, ParameterPosition ppos, SummaryParamNode p
) {
exists(DataFlowCallable c |
c = inject(sc) and
p.isParameterOf(c, ppos) and
p = TSummaryParameterNode(sc, ppos) and
c = viableCallable(call)
)
}
pragma[nomagic]
private ParamNode summaryArgParam0(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
private SummaryParamNode summaryArgParam(DataFlowCall call, ArgNode arg, SummarizedCallable sc) {
exists(ParameterPosition ppos |
argumentPositionMatch(call, arg, ppos) and
viableParam(call, sc, ppos, result)
@@ -884,12 +937,12 @@ module Private {
* local steps. `clearsOrExpects` records whether any node on the path from `p` to
* `n` either clears or expects contents.
*/
private predicate paramReachesLocal(ParamNode p, Node n, boolean clearsOrExpects) {
private predicate paramReachesLocal(SummaryParamNode p, SummaryNode n, boolean clearsOrExpects) {
viableParam(_, _, _, p) and
n = p and
clearsOrExpects = false
or
exists(Node mid, boolean clearsOrExpectsMid |
exists(SummaryNode mid, boolean clearsOrExpectsMid |
paramReachesLocal(p, mid, clearsOrExpectsMid) and
summaryLocalStep(mid, n, true) and
if
@@ -909,21 +962,33 @@ module Private {
*/
pragma[nomagic]
predicate prohibitsUseUseFlow(ArgNode arg, SummarizedCallable sc) {
exists(ParamNode p, ParameterPosition ppos, Node ret |
exists(SummaryParamNode p, ParameterPosition ppos, SummaryNode ret |
paramReachesLocal(p, ret, true) and
p = summaryArgParam0(_, arg, sc) and
p.isParameterOf(_, pragma[only_bind_into](ppos)) and
p = summaryArgParam(_, arg, sc) and
p = TSummaryParameterNode(_, pragma[only_bind_into](ppos)) and
isParameterPostUpdate(ret, _, pragma[only_bind_into](ppos))
)
}
pragma[nomagic]
private predicate summaryReturnNodeExt(SummaryNode ret, ReturnKindExt rk) {
summaryReturnNode(ret, rk.(ValueReturnKind).getKind())
or
exists(SummaryParamNode p, SummaryNode pre, ParameterPosition pos |
paramReachesLocal(p, pre, _) and
summaryPostUpdateNode(ret, pre) and
p = TSummaryParameterNode(_, pos) and
rk.(ParamUpdateReturnKind).getPosition() = pos
)
}
bindingset[ret]
private ParamNode summaryArgParam(
ArgNode arg, ReturnNodeExt ret, OutNodeExt out, SummarizedCallable sc
private SummaryParamNode summaryArgParamRetOut(
ArgNode arg, SummaryNode ret, OutNodeExt out, SummarizedCallable sc
) {
exists(DataFlowCall call, ReturnKindExt rk |
result = summaryArgParam0(call, arg, sc) and
ret.getKind() = pragma[only_bind_into](rk) and
result = summaryArgParam(call, arg, sc) and
summaryReturnNodeExt(ret, pragma[only_bind_into](rk)) and
out = pragma[only_bind_into](rk).getAnOutNode(call)
)
}
@@ -936,9 +1001,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepValue(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnKind rk, ReturnNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam0(call, arg, sc), ret, true) and
ret.getKind() = pragma[only_bind_into](rk) and
exists(ReturnKind rk, SummaryNode ret, DataFlowCall call |
summaryLocalStep(summaryArgParam(call, arg, sc), ret, true) and
summaryReturnNode(ret, pragma[only_bind_into](rk)) and
out = getAnOutNode(call, pragma[only_bind_into](rk))
)
}
@@ -951,7 +1016,9 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryThroughStepTaint(ArgNode arg, Node out, SummarizedCallable sc) {
exists(ReturnNodeExt ret | summaryLocalStep(summaryArgParam(arg, ret, out, sc), ret, false))
exists(SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), ret, false)
)
}
/**
@@ -962,8 +1029,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summaryGetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryReadStep(summaryArgParam(arg, ret, out, sc), c, mid) and
exists(SummaryNode mid, SummaryNode ret |
summaryReadStep(summaryArgParamRetOut(arg, ret, out, sc), c, mid) and
summaryLocalStep(mid, ret, _)
)
}
@@ -976,8 +1043,8 @@ module Private {
* be useful to include in the exposed local data-flow/taint-tracking relations.
*/
predicate summarySetterStep(ArgNode arg, ContentSet c, Node out, SummarizedCallable sc) {
exists(Node mid, ReturnNodeExt ret |
summaryLocalStep(summaryArgParam(arg, ret, out, sc), mid, _) and
exists(SummaryNode mid, SummaryNode ret |
summaryLocalStep(summaryArgParamRetOut(arg, ret, out, sc), mid, _) and
summaryStoreStep(mid, c, ret)
)
}
@@ -1344,11 +1411,11 @@ module Private {
}
private newtype TNodeOrCall =
MkNode(Node n) {
MkNode(SummaryNode n) {
exists(RelevantSummarizedCallable c |
n = summaryNode(c, _)
n = TSummaryInternalNode(c, _)
or
n.(ParamNode).isParameterOf(inject(c), _)
n = TSummaryParameterNode(c, _)
)
} or
MkCall(DataFlowCall call) {
@@ -1357,7 +1424,7 @@ module Private {
}
private class NodeOrCall extends TNodeOrCall {
Node asNode() { this = MkNode(result) }
SummaryNode asNode() { this = MkNode(result) }
DataFlowCall asCall() { this = MkCall(result) }
@@ -1377,9 +1444,11 @@ module Private {
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
) {
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
or
this.asCall().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
filepath = "" and
startline = 0 and
startcolumn = 0 and
endline = 0 and
endcolumn = 0
}
}

View File

@@ -20,15 +20,15 @@ DataFlowCallable inject(SummarizedCallable c) { result.getUnderlyingCallable() =
/** Gets the parameter position of the instance parameter. */
ArgumentPosition callbackSelfParameterPosition() { result instanceof ThisArgumentPosition }
/** Gets the synthesized summary data-flow node for the given values. */
Node summaryNode(SummarizedCallable c, SummaryNodeState state) { result = TSummaryNode(c, state) }
/** Gets the synthesized data-flow call for `receiver`. */
SummaryCall summaryDataFlowCall(Node receiver) { receiver = result.getReceiver() }
SummaryCall summaryDataFlowCall(SummaryNode receiver) { receiver = result.getReceiver() }
/** Gets the type of content `c`. */
DataFlowType getContentType(ContentSet c) { any() }
/** Gets the type of the parameter at the given position. */
DataFlowType getParameterType(SummarizedCallable c, ParameterPosition pos) { any() }
/** Gets the return type of kind `rk` for callable `c`. */
bindingset[c]
DataFlowType getReturnType(SummarizedCallable c, ReturnKind rk) { any() }

View File

@@ -68,7 +68,8 @@ private module Cached {
)
or
// flow through a flow summary (extension of `SummaryModelCsv`)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom, nodeTo, false)
FlowSummaryImpl::Private::Steps::summaryLocalStep(nodeFrom.(FlowSummaryNode).getSummaryNode(),
nodeTo.(FlowSummaryNode).getSummaryNode(), false)
or
any(AdditionalTaintStep a).step(nodeFrom, nodeTo)
}

View File

@@ -1,7 +1,7 @@
edges
| UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:) |
| UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | UnsafeWebViewFetch.swift:10:2:10:25 | [summary] to write: return (return) in URL.init(string:) |
| UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:11:2:11:43 | [summary] to write: return (return) in URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | UnsafeWebViewFetch.swift:43:5:43:29 | [summary] to write: return (return) in Data.init(_:) |
| UnsafeWebViewFetch.swift:94:10:94:37 | try ... | UnsafeWebViewFetch.swift:117:21:117:35 | call to getRemoteData() |
| UnsafeWebViewFetch.swift:94:10:94:37 | try ... | UnsafeWebViewFetch.swift:120:25:120:39 | call to getRemoteData() |
| UnsafeWebViewFetch.swift:94:10:94:37 | try ... | UnsafeWebViewFetch.swift:164:21:164:35 | call to getRemoteData() |
@@ -63,8 +63,11 @@ edges
| UnsafeWebViewFetch.swift:206:17:206:31 | call to getRemoteData() | UnsafeWebViewFetch.swift:211:25:211:25 | htmlData |
nodes
| UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | semmle.label | [summary param] 0 in URL.init(string:) |
| UnsafeWebViewFetch.swift:10:2:10:25 | [summary] to write: return (return) in URL.init(string:) | semmle.label | [summary] to write: return (return) in URL.init(string:) |
| UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | semmle.label | [summary param] 1 in URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:11:2:11:43 | [summary] to write: return (return) in URL.init(string:relativeTo:) | semmle.label | [summary] to write: return (return) in URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| UnsafeWebViewFetch.swift:43:5:43:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| UnsafeWebViewFetch.swift:94:10:94:37 | try ... | semmle.label | try ... |
| UnsafeWebViewFetch.swift:94:14:94:37 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
| UnsafeWebViewFetch.swift:103:25:103:84 | try! ... | semmle.label | try! ... |
@@ -122,16 +125,13 @@ nodes
| UnsafeWebViewFetch.swift:206:17:206:31 | call to getRemoteData() | semmle.label | call to getRemoteData() |
| UnsafeWebViewFetch.swift:210:25:210:25 | htmlData | semmle.label | htmlData |
| UnsafeWebViewFetch.swift:211:25:211:25 | htmlData | semmle.label | htmlData |
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:) | semmle.label | [summary] to write: return (return) in URL.init(string:) |
| file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:relativeTo:) | semmle.label | [summary] to write: return (return) in URL.init(string:relativeTo:) |
subpaths
| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:) | UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) |
| UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL | UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 | UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:) | UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) |
| UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL | UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | file://:0:0:0:0 | [summary] to write: return (return) in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 | UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:131:30:131:30 | remoteString | UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | UnsafeWebViewFetch.swift:10:2:10:25 | [summary] to write: return (return) in URL.init(string:) | UnsafeWebViewFetch.swift:131:18:131:42 | call to URL.init(string:) |
| UnsafeWebViewFetch.swift:132:52:132:52 | remoteURL | UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:11:2:11:43 | [summary] to write: return (return) in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:132:19:132:61 | call to URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:150:24:150:37 | .utf8 | UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | UnsafeWebViewFetch.swift:43:5:43:29 | [summary] to write: return (return) in Data.init(_:) | UnsafeWebViewFetch.swift:150:19:150:41 | call to Data.init(_:) |
| UnsafeWebViewFetch.swift:178:30:178:30 | remoteString | UnsafeWebViewFetch.swift:10:2:10:25 | [summary param] 0 in URL.init(string:) | UnsafeWebViewFetch.swift:10:2:10:25 | [summary] to write: return (return) in URL.init(string:) | UnsafeWebViewFetch.swift:178:18:178:42 | call to URL.init(string:) |
| UnsafeWebViewFetch.swift:179:52:179:52 | remoteURL | UnsafeWebViewFetch.swift:11:2:11:43 | [summary param] 1 in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:11:2:11:43 | [summary] to write: return (return) in URL.init(string:relativeTo:) | UnsafeWebViewFetch.swift:179:19:179:61 | call to URL.init(string:relativeTo:) |
| UnsafeWebViewFetch.swift:197:24:197:37 | .utf8 | UnsafeWebViewFetch.swift:43:5:43:29 | [summary param] 0 in Data.init(_:) | UnsafeWebViewFetch.swift:43:5:43:29 | [summary] to write: return (return) in Data.init(_:) | UnsafeWebViewFetch.swift:197:19:197:41 | call to Data.init(_:) |
#select
| UnsafeWebViewFetch.swift:103:25:103:84 | try! ... | UnsafeWebViewFetch.swift:103:30:103:84 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:103:25:103:84 | try! ... | Tainted data is used in a WebView fetch without restricting the base URL. |
| UnsafeWebViewFetch.swift:106:25:106:25 | data | UnsafeWebViewFetch.swift:105:18:105:72 | call to String.init(contentsOf:) | UnsafeWebViewFetch.swift:106:25:106:25 | data | Tainted data is used in a WebView fetch without restricting the base URL. |

View File

@@ -97,8 +97,8 @@ edges
| SQLite.swift:62:25:62:79 | call to String.init(contentsOf:) | SQLite.swift:117:16:117:16 | unsafeQuery1 |
| SQLite.swift:62:25:62:79 | call to String.init(contentsOf:) | SQLite.swift:119:16:119:16 | unsafeQuery1 |
| SQLite.swift:62:25:62:79 | call to String.init(contentsOf:) | SQLite.swift:132:20:132:20 | remoteString |
| sqlite3_c_api.swift:15:2:15:71 | [summary param] this in copyBytes(to:count:) | file://:0:0:0:0 | [summary] to write: argument 0 in copyBytes(to:count:) |
| sqlite3_c_api.swift:37:2:37:103 | [summary param] this in data(using:allowLossyConversion:) | file://:0:0:0:0 | [summary] to write: return (return) in data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:15:2:15:71 | [summary param] this in copyBytes(to:count:) | sqlite3_c_api.swift:15:2:15:71 | [summary] to write: argument 0 in copyBytes(to:count:) |
| sqlite3_c_api.swift:37:2:37:103 | [summary param] this in data(using:allowLossyConversion:) | sqlite3_c_api.swift:37:2:37:103 | [summary] to write: return (return) in data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:122:26:122:80 | call to String.init(contentsOf:) | sqlite3_c_api.swift:133:33:133:33 | unsafeQuery1 |
| sqlite3_c_api.swift:122:26:122:80 | call to String.init(contentsOf:) | sqlite3_c_api.swift:134:33:134:33 | unsafeQuery2 |
| sqlite3_c_api.swift:122:26:122:80 | call to String.init(contentsOf:) | sqlite3_c_api.swift:135:33:135:33 | unsafeQuery3 |
@@ -226,10 +226,10 @@ nodes
| SQLite.swift:117:16:117:16 | unsafeQuery1 | semmle.label | unsafeQuery1 |
| SQLite.swift:119:16:119:16 | unsafeQuery1 | semmle.label | unsafeQuery1 |
| SQLite.swift:132:20:132:20 | remoteString | semmle.label | remoteString |
| file://:0:0:0:0 | [summary] to write: argument 0 in copyBytes(to:count:) | semmle.label | [summary] to write: argument 0 in copyBytes(to:count:) |
| file://:0:0:0:0 | [summary] to write: return (return) in data(using:allowLossyConversion:) | semmle.label | [summary] to write: return (return) in data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:15:2:15:71 | [summary param] this in copyBytes(to:count:) | semmle.label | [summary param] this in copyBytes(to:count:) |
| sqlite3_c_api.swift:15:2:15:71 | [summary] to write: argument 0 in copyBytes(to:count:) | semmle.label | [summary] to write: argument 0 in copyBytes(to:count:) |
| sqlite3_c_api.swift:37:2:37:103 | [summary param] this in data(using:allowLossyConversion:) | semmle.label | [summary param] this in data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:37:2:37:103 | [summary] to write: return (return) in data(using:allowLossyConversion:) | semmle.label | [summary] to write: return (return) in data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:122:26:122:80 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
| sqlite3_c_api.swift:133:33:133:33 | unsafeQuery1 | semmle.label | unsafeQuery1 |
| sqlite3_c_api.swift:134:33:134:33 | unsafeQuery2 | semmle.label | unsafeQuery2 |
@@ -245,8 +245,8 @@ nodes
| sqlite3_c_api.swift:202:31:202:31 | buffer | semmle.label | buffer |
| sqlite3_c_api.swift:210:31:210:31 | buffer | semmle.label | buffer |
subpaths
| sqlite3_c_api.swift:189:13:189:13 | unsafeQuery3 | sqlite3_c_api.swift:37:2:37:103 | [summary param] this in data(using:allowLossyConversion:) | file://:0:0:0:0 | [summary] to write: return (return) in data(using:allowLossyConversion:) | sqlite3_c_api.swift:189:13:189:58 | call to data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:190:2:190:2 | data | sqlite3_c_api.swift:15:2:15:71 | [summary param] this in copyBytes(to:count:) | file://:0:0:0:0 | [summary] to write: argument 0 in copyBytes(to:count:) | sqlite3_c_api.swift:190:21:190:21 | [post] buffer |
| sqlite3_c_api.swift:189:13:189:13 | unsafeQuery3 | sqlite3_c_api.swift:37:2:37:103 | [summary param] this in data(using:allowLossyConversion:) | sqlite3_c_api.swift:37:2:37:103 | [summary] to write: return (return) in data(using:allowLossyConversion:) | sqlite3_c_api.swift:189:13:189:58 | call to data(using:allowLossyConversion:) |
| sqlite3_c_api.swift:190:2:190:2 | data | sqlite3_c_api.swift:15:2:15:71 | [summary param] this in copyBytes(to:count:) | sqlite3_c_api.swift:15:2:15:71 | [summary] to write: argument 0 in copyBytes(to:count:) | sqlite3_c_api.swift:190:21:190:21 | [post] buffer |
#select
| GRDB.swift:106:41:106:41 | remoteString | GRDB.swift:104:25:104:79 | call to String.init(contentsOf:) | GRDB.swift:106:41:106:41 | remoteString | This query depends on a $@. | GRDB.swift:104:25:104:79 | call to String.init(contentsOf:) | user-provided value |
| GRDB.swift:108:41:108:41 | remoteString | GRDB.swift:104:25:104:79 | call to String.init(contentsOf:) | GRDB.swift:108:41:108:41 | remoteString | This query depends on a $@. | GRDB.swift:104:25:104:79 | call to String.init(contentsOf:) | user-provided value |

View File

@@ -1,8 +1,8 @@
edges
| UnsafeJsEval.swift:69:2:73:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | file://:0:0:0:0 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| UnsafeJsEval.swift:75:2:80:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | file://:0:0:0:0 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
| UnsafeJsEval.swift:69:2:73:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | UnsafeJsEval.swift:69:2:73:5 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| UnsafeJsEval.swift:75:2:80:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | UnsafeJsEval.swift:75:2:80:5 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
| UnsafeJsEval.swift:124:21:124:42 | string | UnsafeJsEval.swift:124:70:124:70 | string |
| UnsafeJsEval.swift:144:5:144:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| UnsafeJsEval.swift:144:5:144:29 | [summary param] 0 in Data.init(_:) | UnsafeJsEval.swift:144:5:144:29 | [summary] to write: return (return) in Data.init(_:) |
| UnsafeJsEval.swift:165:10:165:37 | try ... | UnsafeJsEval.swift:201:21:201:35 | call to getRemoteData() |
| UnsafeJsEval.swift:165:14:165:37 | call to String.init(contentsOf:) | UnsafeJsEval.swift:165:10:165:37 | try ... |
| UnsafeJsEval.swift:201:21:201:35 | call to getRemoteData() | UnsafeJsEval.swift:205:7:205:7 | remoteString |
@@ -66,10 +66,13 @@ edges
| file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) | file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) |
nodes
| UnsafeJsEval.swift:69:2:73:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | semmle.label | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| UnsafeJsEval.swift:69:2:73:5 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | semmle.label | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| UnsafeJsEval.swift:75:2:80:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | semmle.label | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
| UnsafeJsEval.swift:75:2:80:5 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | semmle.label | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
| UnsafeJsEval.swift:124:21:124:42 | string | semmle.label | string |
| UnsafeJsEval.swift:124:70:124:70 | string | semmle.label | string |
| UnsafeJsEval.swift:144:5:144:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| UnsafeJsEval.swift:144:5:144:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| UnsafeJsEval.swift:165:10:165:37 | try ... | semmle.label | try ... |
| UnsafeJsEval.swift:165:14:165:37 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
| UnsafeJsEval.swift:201:21:201:35 | call to getRemoteData() | semmle.label | call to getRemoteData() |
@@ -106,15 +109,12 @@ nodes
| UnsafeJsEval.swift:318:24:318:87 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
| UnsafeJsEval.swift:320:44:320:74 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) | semmle.label | [summary param] 0 in String.init(decoding:as:) |
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) | semmle.label | [summary] to write: return (return) in String.init(decoding:as:) |
| file://:0:0:0:0 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | semmle.label | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| file://:0:0:0:0 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | semmle.label | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
subpaths
| UnsafeJsEval.swift:211:24:211:37 | .utf8 | UnsafeJsEval.swift:144:5:144:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | UnsafeJsEval.swift:211:19:211:41 | call to Data.init(_:) |
| UnsafeJsEval.swift:211:24:211:37 | .utf8 | UnsafeJsEval.swift:144:5:144:29 | [summary param] 0 in Data.init(_:) | UnsafeJsEval.swift:144:5:144:29 | [summary] to write: return (return) in Data.init(_:) | UnsafeJsEval.swift:211:19:211:41 | call to Data.init(_:) |
| UnsafeJsEval.swift:214:24:214:24 | remoteData | file://:0:0:0:0 | [summary param] 0 in String.init(decoding:as:) | file://:0:0:0:0 | [summary] to write: return (return) in String.init(decoding:as:) | UnsafeJsEval.swift:214:7:214:49 | call to String.init(decoding:as:) |
| UnsafeJsEval.swift:266:43:266:43 | string | UnsafeJsEval.swift:69:2:73:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | file://:0:0:0:0 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | UnsafeJsEval.swift:266:22:266:107 | call to WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| UnsafeJsEval.swift:269:43:269:43 | string | UnsafeJsEval.swift:75:2:80:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | file://:0:0:0:0 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | UnsafeJsEval.swift:269:22:269:124 | call to WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
| UnsafeJsEval.swift:266:43:266:43 | string | UnsafeJsEval.swift:69:2:73:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | UnsafeJsEval.swift:69:2:73:5 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:) | UnsafeJsEval.swift:266:22:266:107 | call to WKUserScript.init(source:injectionTime:forMainFrameOnly:) |
| UnsafeJsEval.swift:269:43:269:43 | string | UnsafeJsEval.swift:75:2:80:5 | [summary param] 0 in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | UnsafeJsEval.swift:75:2:80:5 | [summary] to write: return (return) in WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) | UnsafeJsEval.swift:269:22:269:124 | call to WKUserScript.init(source:injectionTime:forMainFrameOnly:in:) |
| UnsafeJsEval.swift:287:31:287:97 | call to JSStringCreateWithCharacters(_:_:) | UnsafeJsEval.swift:124:21:124:42 | string | UnsafeJsEval.swift:124:70:124:70 | string | UnsafeJsEval.swift:287:16:287:98 | call to JSStringRetain(_:) |
| UnsafeJsEval.swift:301:31:301:84 | call to JSStringCreateWithUTF8CString(_:) | UnsafeJsEval.swift:124:21:124:42 | string | UnsafeJsEval.swift:124:70:124:70 | string | UnsafeJsEval.swift:301:16:301:85 | call to JSStringRetain(_:) |
#select

View File

@@ -1,5 +1,5 @@
edges
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:60:19:60:25 | call to Data.init(_:) | rncryptor.swift:68:104:68:104 | myConstIV1 |
| rncryptor.swift:60:19:60:25 | call to Data.init(_:) | rncryptor.swift:77:125:77:125 | myConstIV1 |
| rncryptor.swift:60:24:60:24 | 0 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) |
@@ -40,8 +40,8 @@ edges
| test.swift:101:17:101:35 | call to getConstantString() | test.swift:130:39:130:39 | ivString |
| test.swift:147:22:147:22 | iv | test.swift:53:19:53:34 | iv |
nodes
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:60:19:60:25 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| rncryptor.swift:60:24:60:24 | 0 | semmle.label | 0 |
| rncryptor.swift:61:19:61:27 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
@@ -84,10 +84,10 @@ nodes
| test.swift:167:22:167:22 | iv | semmle.label | iv |
| test.swift:168:22:168:22 | iv | semmle.label | iv |
subpaths
| rncryptor.swift:60:24:60:24 | 0 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:60:19:60:25 | call to Data.init(_:) |
| rncryptor.swift:61:24:61:24 | 123 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:61:19:61:27 | call to Data.init(_:) |
| rncryptor.swift:62:24:62:34 | [...] | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:62:19:62:35 | call to Data.init(_:) |
| rncryptor.swift:63:24:63:24 | iv | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:63:19:63:28 | call to Data.init(_:) |
| rncryptor.swift:60:24:60:24 | 0 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:60:19:60:25 | call to Data.init(_:) |
| rncryptor.swift:61:24:61:24 | 123 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:61:19:61:27 | call to Data.init(_:) |
| rncryptor.swift:62:24:62:34 | [...] | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:62:19:62:35 | call to Data.init(_:) |
| rncryptor.swift:63:24:63:24 | iv | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:63:19:63:28 | call to Data.init(_:) |
#select
| rncryptor.swift:68:104:68:104 | myConstIV1 | rncryptor.swift:60:24:60:24 | 0 | rncryptor.swift:68:104:68:104 | myConstIV1 | The static value '0' is used as an initialization vector for encryption. |
| rncryptor.swift:70:104:70:104 | myConstIV2 | rncryptor.swift:61:24:61:24 | 123 | rncryptor.swift:70:104:70:104 | myConstIV2 | The static value '123' is used as an initialization vector for encryption. |

View File

@@ -1,5 +1,5 @@
edges
| UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in NSString.init(string:) |
| UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | UncontrolledFormatString.swift:30:5:30:35 | [summary] to write: return (return) in NSString.init(string:) |
| UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:70:28:70:28 | tainted |
| UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:73:28:73:28 | tainted |
| UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:74:28:74:28 | tainted |
@@ -23,6 +23,7 @@ edges
| UncontrolledFormatString.swift:85:72:85:72 | tainted | UncontrolledFormatString.swift:85:55:85:79 | call to NSString.init(string:) |
nodes
| UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | semmle.label | [summary param] 0 in NSString.init(string:) |
| UncontrolledFormatString.swift:30:5:30:35 | [summary] to write: return (return) in NSString.init(string:) | semmle.label | [summary] to write: return (return) in NSString.init(string:) |
| UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | semmle.label | call to String.init(contentsOf:) |
| UncontrolledFormatString.swift:70:28:70:28 | tainted | semmle.label | tainted |
| UncontrolledFormatString.swift:73:28:73:28 | tainted | semmle.label | tainted |
@@ -41,12 +42,11 @@ nodes
| UncontrolledFormatString.swift:85:72:85:72 | tainted | semmle.label | tainted |
| UncontrolledFormatString.swift:88:11:88:11 | tainted | semmle.label | tainted |
| UncontrolledFormatString.swift:91:61:91:61 | tainted | semmle.label | tainted |
| file://:0:0:0:0 | [summary] to write: return (return) in NSString.init(string:) | semmle.label | [summary] to write: return (return) in NSString.init(string:) |
subpaths
| UncontrolledFormatString.swift:81:47:81:47 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:81:30:81:54 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:82:65:82:65 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:82:48:82:72 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:84:54:84:54 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:84:37:84:61 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:85:72:85:72 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | file://:0:0:0:0 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:85:55:85:79 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:81:47:81:47 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | UncontrolledFormatString.swift:30:5:30:35 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:81:30:81:54 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:82:65:82:65 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | UncontrolledFormatString.swift:30:5:30:35 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:82:48:82:72 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:84:54:84:54 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | UncontrolledFormatString.swift:30:5:30:35 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:84:37:84:61 | call to NSString.init(string:) |
| UncontrolledFormatString.swift:85:72:85:72 | tainted | UncontrolledFormatString.swift:30:5:30:35 | [summary param] 0 in NSString.init(string:) | UncontrolledFormatString.swift:30:5:30:35 | [summary] to write: return (return) in NSString.init(string:) | UncontrolledFormatString.swift:85:55:85:79 | call to NSString.init(string:) |
#select
| UncontrolledFormatString.swift:70:28:70:28 | tainted | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:70:28:70:28 | tainted | This format string depends on $@. | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | this user-provided value |
| UncontrolledFormatString.swift:73:28:73:28 | tainted | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | UncontrolledFormatString.swift:73:28:73:28 | tainted | This format string depends on $@. | UncontrolledFormatString.swift:64:24:64:77 | call to String.init(contentsOf:) | this user-provided value |

View File

@@ -2,7 +2,7 @@ edges
| testAlamofire.swift:150:45:150:45 | password | testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... |
| testAlamofire.swift:152:51:152:51 | password | testAlamofire.swift:152:19:152:51 | ... .+(_:_:) ... |
| testAlamofire.swift:154:38:154:38 | email | testAlamofire.swift:154:14:154:46 | ... .+(_:_:) ... |
| testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | testSend.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) |
| testSend.swift:33:14:33:32 | call to Data.init(_:) | testSend.swift:37:19:37:19 | data2 |
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) |
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:33:14:33:32 | call to Data.init(_:) |
@@ -16,7 +16,6 @@ edges
| testURL.swift:15:55:15:55 | account_no | testURL.swift:15:22:15:55 | ... .+(_:_:) ... |
| testURL.swift:16:55:16:55 | credit_card_no | testURL.swift:16:22:16:55 | ... .+(_:_:) ... |
nodes
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| testAlamofire.swift:150:45:150:45 | password | semmle.label | password |
| testAlamofire.swift:152:19:152:51 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
@@ -24,6 +23,7 @@ nodes
| testAlamofire.swift:154:14:154:46 | ... .+(_:_:) ... | semmle.label | ... .+(_:_:) ... |
| testAlamofire.swift:154:38:154:38 | email | semmle.label | email |
| testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| testSend.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| testSend.swift:29:19:29:19 | passwordPlain | semmle.label | passwordPlain |
| testSend.swift:33:14:33:32 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| testSend.swift:33:19:33:19 | passwordPlain | semmle.label | passwordPlain |
@@ -47,7 +47,7 @@ nodes
| testURL.swift:16:55:16:55 | credit_card_no | semmle.label | credit_card_no |
| testURL.swift:20:22:20:22 | passwd | semmle.label | passwd |
subpaths
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | testSend.swift:33:14:33:32 | call to Data.init(_:) |
| testSend.swift:33:19:33:19 | passwordPlain | testSend.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | testSend.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | testSend.swift:33:14:33:32 | call to Data.init(_:) |
| testSend.swift:54:17:54:17 | password | testSend.swift:41:10:41:18 | data | testSend.swift:41:45:41:45 | data | testSend.swift:54:13:54:25 | call to pad(_:) |
#select
| testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | testAlamofire.swift:150:45:150:45 | password | testAlamofire.swift:150:13:150:45 | ... .+(_:_:) ... | This operation transmits '... .+(_:_:) ...', which may contain unencrypted sensitive data from $@. | testAlamofire.swift:150:45:150:45 | password | password |

View File

@@ -22,7 +22,7 @@ edges
| file://:0:0:0:0 | [post] self [encryptionKey] | file://:0:0:0:0 | [post] self |
| file://:0:0:0:0 | [post] self [encryptionKey] | file://:0:0:0:0 | [post] self |
| file://:0:0:0:0 | value | file://:0:0:0:0 | [post] self [encryptionKey] |
| misc.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| misc.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | misc.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) |
| misc.swift:30:7:30:7 | value | file://:0:0:0:0 | value |
| misc.swift:46:19:46:38 | call to Data.init(_:) | misc.swift:49:41:49:41 | myConstKey |
| misc.swift:46:19:46:38 | call to Data.init(_:) | misc.swift:53:25:53:25 | myConstKey |
@@ -37,7 +37,7 @@ edges
| misc.swift:57:41:57:41 | myConstKey | misc.swift:30:7:30:7 | value |
| misc.swift:57:41:57:41 | myConstKey | misc.swift:57:2:57:18 | [post] getter for .config |
| misc.swift:57:41:57:41 | myConstKey | misc.swift:57:2:57:18 | [post] getter for .config [encryptionKey] |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:60:19:60:38 | call to Data.init(_:) | rncryptor.swift:65:73:65:73 | myConstKey |
| rncryptor.swift:60:19:60:38 | call to Data.init(_:) | rncryptor.swift:66:73:66:73 | myConstKey |
| rncryptor.swift:60:19:60:38 | call to Data.init(_:) | rncryptor.swift:67:73:67:73 | myConstKey |
@@ -81,10 +81,9 @@ nodes
| file://:0:0:0:0 | [post] self | semmle.label | [post] self |
| file://:0:0:0:0 | [post] self | semmle.label | [post] self |
| file://:0:0:0:0 | [post] self [encryptionKey] | semmle.label | [post] self [encryptionKey] |
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| file://:0:0:0:0 | value | semmle.label | value |
| misc.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| misc.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| misc.swift:30:7:30:7 | value | semmle.label | value |
| misc.swift:46:19:46:38 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| misc.swift:46:24:46:24 | abcdef123456 | semmle.label | abcdef123456 |
@@ -96,6 +95,7 @@ nodes
| misc.swift:57:2:57:18 | [post] getter for .config [encryptionKey] | semmle.label | [post] getter for .config [encryptionKey] |
| misc.swift:57:41:57:41 | myConstKey | semmle.label | myConstKey |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:60:19:60:38 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| rncryptor.swift:60:24:60:24 | abcdef123456 | semmle.label | abcdef123456 |
| rncryptor.swift:65:73:65:73 | myConstKey | semmle.label | myConstKey |
@@ -114,12 +114,12 @@ nodes
| rncryptor.swift:81:102:81:102 | myConstKey | semmle.label | myConstKey |
| rncryptor.swift:83:92:83:92 | myConstKey | semmle.label | myConstKey |
subpaths
| misc.swift:46:24:46:24 | abcdef123456 | misc.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | misc.swift:46:19:46:38 | call to Data.init(_:) |
| misc.swift:46:24:46:24 | abcdef123456 | misc.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | misc.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | misc.swift:46:19:46:38 | call to Data.init(_:) |
| misc.swift:53:25:53:25 | myConstKey | misc.swift:30:7:30:7 | value | file://:0:0:0:0 | [post] self | misc.swift:53:2:53:2 | [post] config |
| misc.swift:53:25:53:25 | myConstKey | misc.swift:30:7:30:7 | value | file://:0:0:0:0 | [post] self [encryptionKey] | misc.swift:53:2:53:2 | [post] config [encryptionKey] |
| misc.swift:57:41:57:41 | myConstKey | misc.swift:30:7:30:7 | value | file://:0:0:0:0 | [post] self | misc.swift:57:2:57:18 | [post] getter for .config |
| misc.swift:57:41:57:41 | myConstKey | misc.swift:30:7:30:7 | value | file://:0:0:0:0 | [post] self [encryptionKey] | misc.swift:57:2:57:18 | [post] getter for .config [encryptionKey] |
| rncryptor.swift:60:24:60:24 | abcdef123456 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:60:19:60:38 | call to Data.init(_:) |
| rncryptor.swift:60:24:60:24 | abcdef123456 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:60:19:60:38 | call to Data.init(_:) |
#select
| cryptoswift.swift:108:21:108:21 | keyString | cryptoswift.swift:76:3:76:3 | this string is constant | cryptoswift.swift:108:21:108:21 | keyString | The key 'keyString' has been initialized with hard-coded values from $@. | cryptoswift.swift:76:3:76:3 | this string is constant | this string is constant |
| cryptoswift.swift:109:21:109:21 | keyString | cryptoswift.swift:76:3:76:3 | this string is constant | cryptoswift.swift:109:21:109:21 | keyString | The key 'keyString' has been initialized with hard-coded values from $@. | cryptoswift.swift:76:3:76:3 | this string is constant | this string is constant |

View File

@@ -1,5 +1,5 @@
edges
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:59:24:59:43 | call to Data.init(_:) | rncryptor.swift:63:57:63:57 | myConstantSalt1 |
| rncryptor.swift:59:24:59:43 | call to Data.init(_:) | rncryptor.swift:68:106:68:106 | myConstantSalt1 |
| rncryptor.swift:59:24:59:43 | call to Data.init(_:) | rncryptor.swift:71:106:71:106 | myConstantSalt1 |
@@ -19,8 +19,8 @@ edges
| test.swift:43:35:43:130 | [...] | test.swift:62:59:62:59 | constantSalt |
| test.swift:43:35:43:130 | [...] | test.swift:67:53:67:53 | constantSalt |
nodes
| file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | semmle.label | [summary param] 0 in Data.init(_:) |
| rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | semmle.label | [summary] to write: return (return) in Data.init(_:) |
| rncryptor.swift:59:24:59:43 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
| rncryptor.swift:59:29:59:29 | abcdef123456 | semmle.label | abcdef123456 |
| rncryptor.swift:60:24:60:30 | call to Data.init(_:) | semmle.label | call to Data.init(_:) |
@@ -41,8 +41,8 @@ nodes
| test.swift:62:59:62:59 | constantSalt | semmle.label | constantSalt |
| test.swift:67:53:67:53 | constantSalt | semmle.label | constantSalt |
subpaths
| rncryptor.swift:59:29:59:29 | abcdef123456 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:59:24:59:43 | call to Data.init(_:) |
| rncryptor.swift:60:29:60:29 | 0 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | file://:0:0:0:0 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:60:24:60:30 | call to Data.init(_:) |
| rncryptor.swift:59:29:59:29 | abcdef123456 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:59:24:59:43 | call to Data.init(_:) |
| rncryptor.swift:60:29:60:29 | 0 | rncryptor.swift:5:5:5:29 | [summary param] 0 in Data.init(_:) | rncryptor.swift:5:5:5:29 | [summary] to write: return (return) in Data.init(_:) | rncryptor.swift:60:24:60:30 | call to Data.init(_:) |
#select
| rncryptor.swift:63:57:63:57 | myConstantSalt1 | rncryptor.swift:59:29:59:29 | abcdef123456 | rncryptor.swift:63:57:63:57 | myConstantSalt1 | The value 'abcdef123456' is used as a constant salt, which is insecure for hashing passwords. |
| rncryptor.swift:65:55:65:55 | myConstantSalt2 | rncryptor.swift:60:29:60:29 | 0 | rncryptor.swift:65:55:65:55 | myConstantSalt2 | The value '0' is used as a constant salt, which is insecure for hashing passwords. |