From b4b91e84a3fee32f090a6f5285a9ace183208d2c Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Tue, 7 Dec 2021 18:24:00 +1300
Subject: [PATCH 001/196] Ruby: Fix ConstantAccessCfgNode.getValueText
The superclass definition uses SSA, which doesn't track constants.
---
ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 455327ddb0d..5ea3038c3a4 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -390,6 +390,8 @@ module ExprNodes {
/** Gets the scope expression. */
final ExprCfgNode getScopeExpr() { e.hasCfgChild(e.getScopeExpr(), this, result) }
+
+ override string getValueText() { result = this.getExpr().getValueText() }
}
private class StmtSequenceChildMapping extends ExprChildMapping, StmtSequence {
From 3df3fb092b7d22a32a83edc1f1e8e021fd805c3e Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Mon, 13 Dec 2021 12:15:45 +1300
Subject: [PATCH 002/196] Make room for new test code
This change is split over several commits so it is easier to see.
This change adds some extra lines, which will be populated in the next
commit.
---
ruby/ql/test/library-tests/ast/Ast.expected | 618 +++++-----
.../library-tests/ast/AstDesugar.expected | 208 ++--
.../test/library-tests/ast/ValueText.expected | 237 ++--
.../ast/literals/literals.expected | 1072 ++++++++---------
.../library-tests/ast/literals/literals.rb | 4 +
5 files changed, 1074 insertions(+), 1065 deletions(-)
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index 1fa6cf4a4c3..e3630cf4ac2 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -1515,346 +1515,346 @@ literals/literals.rb:
# 66| getStmt: [AddExpr] ... + ...
# 66| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 66| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 9
-# 69| getStmt: [CharacterLiteral] ?x
-# 70| getStmt: [CharacterLiteral] ?\n
-# 71| getStmt: [CharacterLiteral] ?\s
-# 72| getStmt: [CharacterLiteral] ?\\
-# 73| getStmt: [CharacterLiteral] ?\u{58}
-# 74| getStmt: [CharacterLiteral] ?\C-a
-# 75| getStmt: [CharacterLiteral] ?\M-a
-# 76| getStmt: [CharacterLiteral] ?\M-\C-a
-# 77| getStmt: [CharacterLiteral] ?\C-\M-a
-# 80| getStmt: [SymbolLiteral] :""
-# 81| getStmt: [SymbolLiteral] :hello
-# 82| getStmt: [SymbolLiteral] :"foo bar"
-# 82| getComponent: [StringTextComponent] foo bar
-# 83| getStmt: [SymbolLiteral] :"bar baz"
-# 83| getComponent: [StringTextComponent] bar baz
-# 84| getStmt: [HashLiteral] {...}
-# 84| getElement: [Pair] Pair
-# 84| getKey: [SymbolLiteral] :foo
-# 84| getValue: [StringLiteral] "bar"
-# 84| getComponent: [StringTextComponent] bar
-# 85| getStmt: [SymbolLiteral] :"wibble"
-# 85| getComponent: [StringTextComponent] wibble
-# 86| getStmt: [SymbolLiteral] :"wibble wobble"
-# 86| getComponent: [StringTextComponent] wibble wobble
-# 87| getStmt: [SymbolLiteral] :"foo_#{...}"
-# 87| getComponent: [StringTextComponent] foo_
-# 87| getComponent: [StringInterpolationComponent] #{...}
-# 87| getStmt: [AddExpr] ... + ...
-# 87| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
-# 87| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
-# 88| getStmt: [SymbolLiteral] :"foo_#{ 1 + 1 }"
-# 88| getComponent: [StringTextComponent] foo_#{ 1 + 1 }
-# 89| getStmt: [SymbolLiteral] :"foo_#{ 3 - 2 }"
-# 89| getComponent: [StringTextComponent] foo_#{ 3 - 2 }
-# 92| getStmt: [ArrayLiteral] [...]
-# 93| getStmt: [ArrayLiteral] [...]
-# 93| getElement: [IntegerLiteral] 1
-# 93| getElement: [IntegerLiteral] 2
-# 93| getElement: [IntegerLiteral] 3
-# 94| getStmt: [ArrayLiteral] [...]
-# 94| getElement: [IntegerLiteral] 4
-# 94| getElement: [IntegerLiteral] 5
-# 94| getElement: [DivExpr] ... / ...
-# 94| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 12
-# 94| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
-# 95| getStmt: [ArrayLiteral] [...]
-# 95| getElement: [IntegerLiteral] 7
-# 95| getElement: [ArrayLiteral] [...]
-# 95| getElement: [IntegerLiteral] 8
-# 95| getElement: [IntegerLiteral] 9
-# 98| getStmt: [ArrayLiteral] %w(...)
-# 99| getStmt: [ArrayLiteral] %w(...)
-# 99| getElement: [StringLiteral] "foo"
-# 99| getComponent: [StringTextComponent] foo
-# 99| getElement: [StringLiteral] "bar"
-# 99| getComponent: [StringTextComponent] bar
-# 99| getElement: [StringLiteral] "baz"
-# 99| getComponent: [StringTextComponent] baz
-# 100| getStmt: [ArrayLiteral] %w(...)
-# 100| getElement: [StringLiteral] "foo"
-# 100| getComponent: [StringTextComponent] foo
-# 100| getElement: [StringLiteral] "bar"
-# 100| getComponent: [StringTextComponent] bar
-# 100| getElement: [StringLiteral] "baz"
-# 100| getComponent: [StringTextComponent] baz
-# 101| getStmt: [ArrayLiteral] %w(...)
-# 101| getElement: [StringLiteral] "foo"
-# 101| getComponent: [StringTextComponent] foo
-# 101| getElement: [StringLiteral] "bar#{...}"
-# 101| getComponent: [StringTextComponent] bar
-# 101| getComponent: [StringInterpolationComponent] #{...}
-# 101| getStmt: [AddExpr] ... + ...
-# 101| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 101| getElement: [StringLiteral] "baz"
-# 101| getComponent: [StringTextComponent] baz
+# 73| getStmt: [CharacterLiteral] ?x
+# 74| getStmt: [CharacterLiteral] ?\n
+# 75| getStmt: [CharacterLiteral] ?\s
+# 76| getStmt: [CharacterLiteral] ?\\
+# 77| getStmt: [CharacterLiteral] ?\u{58}
+# 78| getStmt: [CharacterLiteral] ?\C-a
+# 79| getStmt: [CharacterLiteral] ?\M-a
+# 80| getStmt: [CharacterLiteral] ?\M-\C-a
+# 81| getStmt: [CharacterLiteral] ?\C-\M-a
+# 84| getStmt: [SymbolLiteral] :""
+# 85| getStmt: [SymbolLiteral] :hello
+# 86| getStmt: [SymbolLiteral] :"foo bar"
+# 86| getComponent: [StringTextComponent] foo bar
+# 87| getStmt: [SymbolLiteral] :"bar baz"
+# 87| getComponent: [StringTextComponent] bar baz
+# 88| getStmt: [HashLiteral] {...}
+# 88| getElement: [Pair] Pair
+# 88| getKey: [SymbolLiteral] :foo
+# 88| getValue: [StringLiteral] "bar"
+# 88| getComponent: [StringTextComponent] bar
+# 89| getStmt: [SymbolLiteral] :"wibble"
+# 89| getComponent: [StringTextComponent] wibble
+# 90| getStmt: [SymbolLiteral] :"wibble wobble"
+# 90| getComponent: [StringTextComponent] wibble wobble
+# 91| getStmt: [SymbolLiteral] :"foo_#{...}"
+# 91| getComponent: [StringTextComponent] foo_
+# 91| getComponent: [StringInterpolationComponent] #{...}
+# 91| getStmt: [AddExpr] ... + ...
+# 91| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
+# 91| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
+# 92| getStmt: [SymbolLiteral] :"foo_#{ 1 + 1 }"
+# 92| getComponent: [StringTextComponent] foo_#{ 1 + 1 }
+# 93| getStmt: [SymbolLiteral] :"foo_#{ 3 - 2 }"
+# 93| getComponent: [StringTextComponent] foo_#{ 3 - 2 }
+# 96| getStmt: [ArrayLiteral] [...]
+# 97| getStmt: [ArrayLiteral] [...]
+# 97| getElement: [IntegerLiteral] 1
+# 97| getElement: [IntegerLiteral] 2
+# 97| getElement: [IntegerLiteral] 3
+# 98| getStmt: [ArrayLiteral] [...]
+# 98| getElement: [IntegerLiteral] 4
+# 98| getElement: [IntegerLiteral] 5
+# 98| getElement: [DivExpr] ... / ...
+# 98| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 12
+# 98| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
+# 99| getStmt: [ArrayLiteral] [...]
+# 99| getElement: [IntegerLiteral] 7
+# 99| getElement: [ArrayLiteral] [...]
+# 99| getElement: [IntegerLiteral] 8
+# 99| getElement: [IntegerLiteral] 9
# 102| getStmt: [ArrayLiteral] %w(...)
-# 102| getElement: [StringLiteral] "foo"
-# 102| getComponent: [StringTextComponent] foo
-# 102| getElement: [StringLiteral] "bar#{1+1}"
-# 102| getComponent: [StringTextComponent] bar#{1+1}
-# 102| getElement: [StringLiteral] "baz"
-# 102| getComponent: [StringTextComponent] baz
-# 105| getStmt: [ArrayLiteral] %i(...)
-# 106| getStmt: [ArrayLiteral] %i(...)
-# 106| getElement: [SymbolLiteral] :"foo"
+# 103| getStmt: [ArrayLiteral] %w(...)
+# 103| getElement: [StringLiteral] "foo"
+# 103| getComponent: [StringTextComponent] foo
+# 103| getElement: [StringLiteral] "bar"
+# 103| getComponent: [StringTextComponent] bar
+# 103| getElement: [StringLiteral] "baz"
+# 103| getComponent: [StringTextComponent] baz
+# 104| getStmt: [ArrayLiteral] %w(...)
+# 104| getElement: [StringLiteral] "foo"
+# 104| getComponent: [StringTextComponent] foo
+# 104| getElement: [StringLiteral] "bar"
+# 104| getComponent: [StringTextComponent] bar
+# 104| getElement: [StringLiteral] "baz"
+# 104| getComponent: [StringTextComponent] baz
+# 105| getStmt: [ArrayLiteral] %w(...)
+# 105| getElement: [StringLiteral] "foo"
+# 105| getComponent: [StringTextComponent] foo
+# 105| getElement: [StringLiteral] "bar#{...}"
+# 105| getComponent: [StringTextComponent] bar
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [AddExpr] ... + ...
+# 105| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
+# 105| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 105| getElement: [StringLiteral] "baz"
+# 105| getComponent: [StringTextComponent] baz
+# 106| getStmt: [ArrayLiteral] %w(...)
+# 106| getElement: [StringLiteral] "foo"
# 106| getComponent: [StringTextComponent] foo
-# 106| getElement: [SymbolLiteral] :"bar"
-# 106| getComponent: [StringTextComponent] bar
-# 106| getElement: [SymbolLiteral] :"baz"
+# 106| getElement: [StringLiteral] "bar#{1+1}"
+# 106| getComponent: [StringTextComponent] bar#{1+1}
+# 106| getElement: [StringLiteral] "baz"
# 106| getComponent: [StringTextComponent] baz
-# 107| getStmt: [ArrayLiteral] %i(...)
-# 107| getElement: [SymbolLiteral] :"foo"
-# 107| getComponent: [StringTextComponent] foo
-# 107| getElement: [SymbolLiteral] :"bar"
-# 107| getComponent: [StringTextComponent] bar
-# 107| getElement: [SymbolLiteral] :"baz"
-# 107| getComponent: [StringTextComponent] baz
-# 108| getStmt: [ArrayLiteral] %i(...)
-# 108| getElement: [SymbolLiteral] :"foo"
-# 108| getComponent: [StringTextComponent] foo
-# 108| getElement: [SymbolLiteral] :"bar#{...}"
-# 108| getComponent: [StringTextComponent] bar
-# 108| getComponent: [StringInterpolationComponent] #{...}
-# 108| getStmt: [AddExpr] ... + ...
-# 108| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
-# 108| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
-# 108| getElement: [SymbolLiteral] :"baz"
-# 108| getComponent: [StringTextComponent] baz
# 109| getStmt: [ArrayLiteral] %i(...)
-# 109| getElement: [SymbolLiteral] :"foo"
-# 109| getComponent: [StringTextComponent] foo
-# 109| getElement: [SymbolLiteral] :"bar#{"
-# 109| getComponent: [StringTextComponent] bar#{
-# 109| getElement: [SymbolLiteral] :"2"
-# 109| getComponent: [StringTextComponent] 2
-# 109| getElement: [SymbolLiteral] :"+"
-# 109| getComponent: [StringTextComponent] +
-# 109| getElement: [SymbolLiteral] :"4"
-# 109| getComponent: [StringTextComponent] 4
-# 109| getElement: [SymbolLiteral] :"}"
-# 109| getComponent: [StringTextComponent] }
-# 109| getElement: [SymbolLiteral] :"baz"
-# 109| getComponent: [StringTextComponent] baz
-# 112| getStmt: [HashLiteral] {...}
-# 113| getStmt: [HashLiteral] {...}
-# 113| getElement: [Pair] Pair
-# 113| getKey: [SymbolLiteral] :foo
-# 113| getValue: [IntegerLiteral] 1
-# 113| getElement: [Pair] Pair
-# 113| getKey: [SymbolLiteral] :bar
-# 113| getValue: [IntegerLiteral] 2
-# 113| getElement: [Pair] Pair
-# 113| getKey: [StringLiteral] "baz"
-# 113| getComponent: [StringTextComponent] baz
-# 113| getValue: [IntegerLiteral] 3
-# 114| getStmt: [HashLiteral] {...}
-# 114| getElement: [Pair] Pair
-# 114| getKey: [SymbolLiteral] :foo
-# 114| getValue: [IntegerLiteral] 7
-# 114| getElement: [HashSplatExpr] ** ...
-# 114| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
-# 114| getReceiver: [Self, SelfVariableAccess] self
-# 117| getStmt: [ParenthesizedExpr] ( ... )
-# 117| getStmt: [RangeLiteral] _ .. _
-# 117| getBegin: [IntegerLiteral] 1
-# 117| getEnd: [IntegerLiteral] 10
-# 118| getStmt: [ParenthesizedExpr] ( ... )
-# 118| getStmt: [RangeLiteral] _ ... _
-# 118| getBegin: [IntegerLiteral] 1
-# 118| getEnd: [IntegerLiteral] 10
-# 119| getStmt: [ParenthesizedExpr] ( ... )
-# 119| getStmt: [RangeLiteral] _ .. _
-# 119| getBegin: [IntegerLiteral] 1
-# 119| getEnd: [IntegerLiteral] 0
-# 120| getStmt: [ParenthesizedExpr] ( ... )
-# 120| getStmt: [RangeLiteral] _ .. _
-# 120| getBegin: [MethodCall] call to start
-# 120| getReceiver: [Self, SelfVariableAccess] self
-# 120| getEnd: [AddExpr] ... + ...
-# 120| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
-# 120| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 3
+# 110| getStmt: [ArrayLiteral] %i(...)
+# 110| getElement: [SymbolLiteral] :"foo"
+# 110| getComponent: [StringTextComponent] foo
+# 110| getElement: [SymbolLiteral] :"bar"
+# 110| getComponent: [StringTextComponent] bar
+# 110| getElement: [SymbolLiteral] :"baz"
+# 110| getComponent: [StringTextComponent] baz
+# 111| getStmt: [ArrayLiteral] %i(...)
+# 111| getElement: [SymbolLiteral] :"foo"
+# 111| getComponent: [StringTextComponent] foo
+# 111| getElement: [SymbolLiteral] :"bar"
+# 111| getComponent: [StringTextComponent] bar
+# 111| getElement: [SymbolLiteral] :"baz"
+# 111| getComponent: [StringTextComponent] baz
+# 112| getStmt: [ArrayLiteral] %i(...)
+# 112| getElement: [SymbolLiteral] :"foo"
+# 112| getComponent: [StringTextComponent] foo
+# 112| getElement: [SymbolLiteral] :"bar#{...}"
+# 112| getComponent: [StringTextComponent] bar
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [AddExpr] ... + ...
+# 112| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
+# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 112| getElement: [SymbolLiteral] :"baz"
+# 112| getComponent: [StringTextComponent] baz
+# 113| getStmt: [ArrayLiteral] %i(...)
+# 113| getElement: [SymbolLiteral] :"foo"
+# 113| getComponent: [StringTextComponent] foo
+# 113| getElement: [SymbolLiteral] :"bar#{"
+# 113| getComponent: [StringTextComponent] bar#{
+# 113| getElement: [SymbolLiteral] :"2"
+# 113| getComponent: [StringTextComponent] 2
+# 113| getElement: [SymbolLiteral] :"+"
+# 113| getComponent: [StringTextComponent] +
+# 113| getElement: [SymbolLiteral] :"4"
+# 113| getComponent: [StringTextComponent] 4
+# 113| getElement: [SymbolLiteral] :"}"
+# 113| getComponent: [StringTextComponent] }
+# 113| getElement: [SymbolLiteral] :"baz"
+# 113| getComponent: [StringTextComponent] baz
+# 116| getStmt: [HashLiteral] {...}
+# 117| getStmt: [HashLiteral] {...}
+# 117| getElement: [Pair] Pair
+# 117| getKey: [SymbolLiteral] :foo
+# 117| getValue: [IntegerLiteral] 1
+# 117| getElement: [Pair] Pair
+# 117| getKey: [SymbolLiteral] :bar
+# 117| getValue: [IntegerLiteral] 2
+# 117| getElement: [Pair] Pair
+# 117| getKey: [StringLiteral] "baz"
+# 117| getComponent: [StringTextComponent] baz
+# 117| getValue: [IntegerLiteral] 3
+# 118| getStmt: [HashLiteral] {...}
+# 118| getElement: [Pair] Pair
+# 118| getKey: [SymbolLiteral] :foo
+# 118| getValue: [IntegerLiteral] 7
+# 118| getElement: [HashSplatExpr] ** ...
+# 118| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
+# 118| getReceiver: [Self, SelfVariableAccess] self
# 121| getStmt: [ParenthesizedExpr] ( ... )
# 121| getStmt: [RangeLiteral] _ .. _
# 121| getBegin: [IntegerLiteral] 1
+# 121| getEnd: [IntegerLiteral] 10
# 122| getStmt: [ParenthesizedExpr] ( ... )
-# 122| getStmt: [RangeLiteral] _ .. _
-# 122| getEnd: [IntegerLiteral] 1
+# 122| getStmt: [RangeLiteral] _ ... _
+# 122| getBegin: [IntegerLiteral] 1
+# 122| getEnd: [IntegerLiteral] 10
# 123| getStmt: [ParenthesizedExpr] ( ... )
-# 123| getStmt: [SubExpr] ... - ...
-# 123| getAnOperand/getLeftOperand/getReceiver: [RangeLiteral] _ .. _
-# 123| getBegin: [IntegerLiteral] 0
-# 123| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 126| getStmt: [SubshellLiteral] `ls -l`
-# 126| getComponent: [StringTextComponent] ls -l
-# 127| getStmt: [SubshellLiteral] `ls -l`
-# 127| getComponent: [StringTextComponent] ls -l
-# 128| getStmt: [SubshellLiteral] `du -d #{...}`
-# 128| getComponent: [StringTextComponent] du -d
-# 128| getComponent: [StringInterpolationComponent] #{...}
-# 128| getStmt: [AddExpr] ... + ...
-# 128| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 128| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 129| getStmt: [SubshellLiteral] `du -d #{...}`
-# 129| getComponent: [StringTextComponent] du -d
-# 129| getComponent: [StringInterpolationComponent] #{...}
-# 129| getStmt: [SubExpr] ... - ...
-# 129| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 5
-# 129| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
-# 132| getStmt: [RegExpLiteral] //
-# 133| getStmt: [RegExpLiteral] /foo/
-# 133| getParsed: [RegExpSequence] foo
-# 133| 0: [RegExpConstant, RegExpNormalChar] f
-# 133| 1: [RegExpConstant, RegExpNormalChar] o
-# 133| 2: [RegExpConstant, RegExpNormalChar] o
-# 133| getComponent: [StringTextComponent] foo
-# 134| getStmt: [RegExpLiteral] /foo/
-# 134| getParsed: [RegExpSequence] foo
-# 134| 0: [RegExpConstant, RegExpNormalChar] f
-# 134| 1: [RegExpConstant, RegExpNormalChar] o
-# 134| 2: [RegExpConstant, RegExpNormalChar] o
-# 134| getComponent: [StringTextComponent] foo
-# 135| getStmt: [RegExpLiteral] /foo+\sbar\S/
-# 135| getParsed: [RegExpSequence] foo+\sbar\S
-# 135| 0: [RegExpConstant, RegExpNormalChar] f
-# 135| 1: [RegExpConstant, RegExpNormalChar] o
-# 135| 2: [RegExpPlus] o+
-# 135| 0: [RegExpConstant, RegExpNormalChar] o
-# 135| 3: [RegExpCharacterClassEscape] \s
-# 135| 4: [RegExpConstant, RegExpNormalChar] b
-# 135| 5: [RegExpConstant, RegExpNormalChar] a
-# 135| 6: [RegExpConstant, RegExpNormalChar] r
-# 135| 7: [RegExpCharacterClassEscape] \S
-# 135| getComponent: [StringTextComponent] foo+
-# 135| getComponent: [StringEscapeSequenceComponent] \s
-# 135| getComponent: [StringTextComponent] bar
-# 135| getComponent: [StringEscapeSequenceComponent] \S
-# 136| getStmt: [RegExpLiteral] /foo#{...}bar/
-# 136| getComponent: [StringTextComponent] foo
-# 136| getComponent: [StringInterpolationComponent] #{...}
-# 136| getStmt: [AddExpr] ... + ...
-# 136| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 136| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 136| getComponent: [StringTextComponent] bar
+# 123| getStmt: [RangeLiteral] _ .. _
+# 123| getBegin: [IntegerLiteral] 1
+# 123| getEnd: [IntegerLiteral] 0
+# 124| getStmt: [ParenthesizedExpr] ( ... )
+# 124| getStmt: [RangeLiteral] _ .. _
+# 124| getBegin: [MethodCall] call to start
+# 124| getReceiver: [Self, SelfVariableAccess] self
+# 124| getEnd: [AddExpr] ... + ...
+# 124| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
+# 124| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 3
+# 125| getStmt: [ParenthesizedExpr] ( ... )
+# 125| getStmt: [RangeLiteral] _ .. _
+# 125| getBegin: [IntegerLiteral] 1
+# 126| getStmt: [ParenthesizedExpr] ( ... )
+# 126| getStmt: [RangeLiteral] _ .. _
+# 126| getEnd: [IntegerLiteral] 1
+# 127| getStmt: [ParenthesizedExpr] ( ... )
+# 127| getStmt: [SubExpr] ... - ...
+# 127| getAnOperand/getLeftOperand/getReceiver: [RangeLiteral] _ .. _
+# 127| getBegin: [IntegerLiteral] 0
+# 127| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 130| getStmt: [SubshellLiteral] `ls -l`
+# 130| getComponent: [StringTextComponent] ls -l
+# 131| getStmt: [SubshellLiteral] `ls -l`
+# 131| getComponent: [StringTextComponent] ls -l
+# 132| getStmt: [SubshellLiteral] `du -d #{...}`
+# 132| getComponent: [StringTextComponent] du -d
+# 132| getComponent: [StringInterpolationComponent] #{...}
+# 132| getStmt: [AddExpr] ... + ...
+# 132| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
+# 132| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 133| getStmt: [SubshellLiteral] `du -d #{...}`
+# 133| getComponent: [StringTextComponent] du -d
+# 133| getComponent: [StringInterpolationComponent] #{...}
+# 133| getStmt: [SubExpr] ... - ...
+# 133| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 5
+# 133| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 136| getStmt: [RegExpLiteral] //
# 137| getStmt: [RegExpLiteral] /foo/
# 137| getParsed: [RegExpSequence] foo
# 137| 0: [RegExpConstant, RegExpNormalChar] f
# 137| 1: [RegExpConstant, RegExpNormalChar] o
# 137| 2: [RegExpConstant, RegExpNormalChar] o
# 137| getComponent: [StringTextComponent] foo
-# 138| getStmt: [RegExpLiteral] //
-# 139| getStmt: [RegExpLiteral] /foo/
-# 139| getParsed: [RegExpSequence] foo
+# 138| getStmt: [RegExpLiteral] /foo/
+# 138| getParsed: [RegExpSequence] foo
+# 138| 0: [RegExpConstant, RegExpNormalChar] f
+# 138| 1: [RegExpConstant, RegExpNormalChar] o
+# 138| 2: [RegExpConstant, RegExpNormalChar] o
+# 138| getComponent: [StringTextComponent] foo
+# 139| getStmt: [RegExpLiteral] /foo+\sbar\S/
+# 139| getParsed: [RegExpSequence] foo+\sbar\S
# 139| 0: [RegExpConstant, RegExpNormalChar] f
# 139| 1: [RegExpConstant, RegExpNormalChar] o
-# 139| 2: [RegExpConstant, RegExpNormalChar] o
-# 139| getComponent: [StringTextComponent] foo
-# 140| getStmt: [RegExpLiteral] /foo/
-# 140| getParsed: [RegExpSequence] foo
-# 140| 0: [RegExpConstant, RegExpNormalChar] f
-# 140| 1: [RegExpConstant, RegExpNormalChar] o
-# 140| 2: [RegExpConstant, RegExpNormalChar] o
+# 139| 2: [RegExpPlus] o+
+# 139| 0: [RegExpConstant, RegExpNormalChar] o
+# 139| 3: [RegExpCharacterClassEscape] \s
+# 139| 4: [RegExpConstant, RegExpNormalChar] b
+# 139| 5: [RegExpConstant, RegExpNormalChar] a
+# 139| 6: [RegExpConstant, RegExpNormalChar] r
+# 139| 7: [RegExpCharacterClassEscape] \S
+# 139| getComponent: [StringTextComponent] foo+
+# 139| getComponent: [StringEscapeSequenceComponent] \s
+# 139| getComponent: [StringTextComponent] bar
+# 139| getComponent: [StringEscapeSequenceComponent] \S
+# 140| getStmt: [RegExpLiteral] /foo#{...}bar/
# 140| getComponent: [StringTextComponent] foo
-# 141| getStmt: [RegExpLiteral] /foo+\sbar\S/
-# 141| getParsed: [RegExpSequence] foo+\sbar\S
+# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getStmt: [AddExpr] ... + ...
+# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
+# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 140| getComponent: [StringTextComponent] bar
+# 141| getStmt: [RegExpLiteral] /foo/
+# 141| getParsed: [RegExpSequence] foo
# 141| 0: [RegExpConstant, RegExpNormalChar] f
# 141| 1: [RegExpConstant, RegExpNormalChar] o
-# 141| 2: [RegExpPlus] o+
-# 141| 0: [RegExpConstant, RegExpNormalChar] o
-# 141| 3: [RegExpCharacterClassEscape] \s
-# 141| 4: [RegExpConstant, RegExpNormalChar] b
-# 141| 5: [RegExpConstant, RegExpNormalChar] a
-# 141| 6: [RegExpConstant, RegExpNormalChar] r
-# 141| 7: [RegExpCharacterClassEscape] \S
-# 141| getComponent: [StringTextComponent] foo+
-# 141| getComponent: [StringEscapeSequenceComponent] \s
-# 141| getComponent: [StringTextComponent] bar
-# 141| getComponent: [StringEscapeSequenceComponent] \S
-# 142| getStmt: [RegExpLiteral] /foo#{...}bar/
-# 142| getComponent: [StringTextComponent] foo
-# 142| getComponent: [StringInterpolationComponent] #{...}
-# 142| getStmt: [AddExpr] ... + ...
-# 142| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
-# 142| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 142| getComponent: [StringTextComponent] bar
+# 141| 2: [RegExpConstant, RegExpNormalChar] o
+# 141| getComponent: [StringTextComponent] foo
+# 142| getStmt: [RegExpLiteral] //
# 143| getStmt: [RegExpLiteral] /foo/
# 143| getParsed: [RegExpSequence] foo
# 143| 0: [RegExpConstant, RegExpNormalChar] f
# 143| 1: [RegExpConstant, RegExpNormalChar] o
# 143| 2: [RegExpConstant, RegExpNormalChar] o
# 143| getComponent: [StringTextComponent] foo
-# 146| getStmt: [StringLiteral] "abcdefghijklmnopqrstuvwxyzabcdef"
-# 146| getComponent: [StringTextComponent] abcdefghijklmnopqrstuvwxyzabcdef
-# 147| getStmt: [StringLiteral] "foobarfoobarfoobarfoobarfooba..."
-# 147| getComponent: [StringTextComponent] foobarfoobarfoobarfoobarfoobarfoo
-# 148| getStmt: [StringLiteral] "foobar\\foobar\\foobar\\fooba..."
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 148| getComponent: [StringEscapeSequenceComponent] \\
-# 148| getComponent: [StringTextComponent] foobar
-# 151| getStmt: [MethodCall] call to run_sql
-# 151| getReceiver: [Self, SelfVariableAccess] self
-# 151| getArgument: [HereDoc] < |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
-| literals.rb:69:1:69:2 | ?x | CharacterLiteral | ?x |
-| literals.rb:70:1:70:3 | ?\\n | CharacterLiteral | ?\\n |
-| literals.rb:71:1:71:3 | ?\\s | CharacterLiteral | ?\\s |
-| literals.rb:72:1:72:3 | ?\\\\ | CharacterLiteral | ?\\\\ |
-| literals.rb:73:1:73:7 | ?\\u{58} | CharacterLiteral | ?\\u{58} |
-| literals.rb:74:1:74:5 | ?\\C-a | CharacterLiteral | ?\\C-a |
-| literals.rb:75:1:75:5 | ?\\M-a | CharacterLiteral | ?\\M-a |
-| literals.rb:76:1:76:8 | ?\\M-\\C-a | CharacterLiteral | ?\\M-\\C-a |
-| literals.rb:77:1:77:8 | ?\\C-\\M-a | CharacterLiteral | ?\\C-\\M-a |
-| literals.rb:80:1:80:3 | :"" | SymbolLiteral | |
-| literals.rb:81:1:81:6 | :hello | SymbolLiteral | hello |
-| literals.rb:82:1:82:10 | :"foo bar" | SymbolLiteral | foo bar |
-| literals.rb:83:1:83:10 | :"bar baz" | SymbolLiteral | bar baz |
-| literals.rb:84:1:84:14 | {...} | HashLiteral | |
-| literals.rb:84:3:84:5 | :foo | SymbolLiteral | foo |
-| literals.rb:84:8:84:12 | "bar" | StringLiteral | bar |
-| literals.rb:85:1:85:10 | :"wibble" | SymbolLiteral | wibble |
-| literals.rb:86:1:86:17 | :"wibble wobble" | SymbolLiteral | wibble wobble |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | SymbolLiteral | |
-| literals.rb:87:10:87:10 | 2 | IntegerLiteral | 2 |
-| literals.rb:87:14:87:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | foo_#{ 1 + 1 } |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | foo_#{ 3 - 2 } |
-| literals.rb:92:1:92:2 | [...] | ArrayLiteral | |
-| literals.rb:93:1:93:9 | [...] | ArrayLiteral | |
-| literals.rb:93:2:93:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:93:5:93:5 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:8:93:8 | 3 | IntegerLiteral | 3 |
-| literals.rb:94:1:94:14 | [...] | ArrayLiteral | |
-| literals.rb:94:2:94:2 | 4 | IntegerLiteral | 4 |
-| literals.rb:94:5:94:5 | 5 | IntegerLiteral | 5 |
-| literals.rb:94:8:94:9 | 12 | IntegerLiteral | 12 |
-| literals.rb:94:13:94:13 | 2 | IntegerLiteral | 2 |
-| literals.rb:95:1:95:11 | [...] | ArrayLiteral | |
-| literals.rb:95:2:95:2 | 7 | IntegerLiteral | 7 |
-| literals.rb:95:5:95:10 | [...] | ArrayLiteral | |
-| literals.rb:95:6:95:6 | 8 | IntegerLiteral | 8 |
-| literals.rb:95:9:95:9 | 9 | IntegerLiteral | 9 |
-| literals.rb:98:1:98:4 | %w(...) | ArrayLiteral | |
-| literals.rb:99:1:99:15 | %w(...) | ArrayLiteral | |
-| literals.rb:99:4:99:6 | "foo" | StringLiteral | foo |
-| literals.rb:99:8:99:10 | "bar" | StringLiteral | bar |
-| literals.rb:99:12:99:14 | "baz" | StringLiteral | baz |
-| literals.rb:100:1:100:15 | %w(...) | ArrayLiteral | |
-| literals.rb:100:4:100:6 | "foo" | StringLiteral | foo |
-| literals.rb:100:8:100:10 | "bar" | StringLiteral | bar |
-| literals.rb:100:12:100:14 | "baz" | StringLiteral | baz |
-| literals.rb:101:1:101:21 | %w(...) | ArrayLiteral | |
-| literals.rb:101:4:101:6 | "foo" | StringLiteral | foo |
-| literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral | |
-| literals.rb:101:13:101:13 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:15:101:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:18:101:20 | "baz" | StringLiteral | baz |
-| literals.rb:102:1:102:21 | %w(...) | ArrayLiteral | |
-| literals.rb:102:4:102:6 | "foo" | StringLiteral | foo |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | StringLiteral | bar#{1+1} |
-| literals.rb:102:18:102:20 | "baz" | StringLiteral | baz |
-| literals.rb:105:1:105:4 | %i(...) | ArrayLiteral | |
-| literals.rb:106:1:106:15 | %i(...) | ArrayLiteral | |
-| literals.rb:106:4:106:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:106:8:106:10 | :"bar" | SymbolLiteral | bar |
-| literals.rb:106:12:106:14 | :"baz" | SymbolLiteral | baz |
-| literals.rb:107:1:107:15 | %i(...) | ArrayLiteral | |
-| literals.rb:107:4:107:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:107:8:107:10 | :"bar" | SymbolLiteral | bar |
-| literals.rb:107:12:107:14 | :"baz" | SymbolLiteral | baz |
-| literals.rb:108:1:108:25 | %i(...) | ArrayLiteral | |
-| literals.rb:108:4:108:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral | |
-| literals.rb:108:14:108:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:108:18:108:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:108:22:108:24 | :"baz" | SymbolLiteral | baz |
-| literals.rb:109:1:109:25 | %i(...) | ArrayLiteral | |
-| literals.rb:109:4:109:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:109:8:109:12 | :"bar#{" | SymbolLiteral | bar#{ |
-| literals.rb:109:14:109:14 | :"2" | SymbolLiteral | 2 |
-| literals.rb:109:16:109:16 | :"+" | SymbolLiteral | + |
-| literals.rb:109:18:109:18 | :"4" | SymbolLiteral | 4 |
-| literals.rb:109:20:109:20 | :"}" | SymbolLiteral | } |
-| literals.rb:109:22:109:24 | :"baz" | SymbolLiteral | baz |
-| literals.rb:112:1:112:2 | {...} | HashLiteral | |
-| literals.rb:113:1:113:33 | {...} | HashLiteral | |
-| literals.rb:113:3:113:5 | :foo | SymbolLiteral | foo |
-| literals.rb:113:8:113:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:113:11:113:14 | :bar | SymbolLiteral | bar |
-| literals.rb:113:19:113:19 | 2 | IntegerLiteral | 2 |
-| literals.rb:113:22:113:26 | "baz" | StringLiteral | baz |
-| literals.rb:113:31:113:31 | 3 | IntegerLiteral | 3 |
-| literals.rb:114:1:114:17 | {...} | HashLiteral | |
-| literals.rb:114:3:114:5 | :foo | SymbolLiteral | foo |
-| literals.rb:114:8:114:8 | 7 | IntegerLiteral | 7 |
-| literals.rb:117:2:117:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:117:2:117:6 | _ .. _ | RangeLiteral | |
-| literals.rb:117:5:117:6 | 10 | IntegerLiteral | 10 |
-| literals.rb:118:2:118:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:118:2:118:7 | _ ... _ | RangeLiteral | |
-| literals.rb:118:6:118:7 | 10 | IntegerLiteral | 10 |
-| literals.rb:119:2:119:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:119:2:119:7 | _ .. _ | RangeLiteral | |
-| literals.rb:119:7:119:7 | 0 | IntegerLiteral | 0 |
-| literals.rb:120:2:120:11 | _ .. _ | RangeLiteral | |
-| literals.rb:120:9:120:9 | 2 | IntegerLiteral | 2 |
-| literals.rb:120:11:120:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:73:1:73:2 | ?x | CharacterLiteral | ?x |
+| literals.rb:74:1:74:3 | ?\\n | CharacterLiteral | ?\\n |
+| literals.rb:75:1:75:3 | ?\\s | CharacterLiteral | ?\\s |
+| literals.rb:76:1:76:3 | ?\\\\ | CharacterLiteral | ?\\\\ |
+| literals.rb:77:1:77:7 | ?\\u{58} | CharacterLiteral | ?\\u{58} |
+| literals.rb:78:1:78:5 | ?\\C-a | CharacterLiteral | ?\\C-a |
+| literals.rb:79:1:79:5 | ?\\M-a | CharacterLiteral | ?\\M-a |
+| literals.rb:80:1:80:8 | ?\\M-\\C-a | CharacterLiteral | ?\\M-\\C-a |
+| literals.rb:81:1:81:8 | ?\\C-\\M-a | CharacterLiteral | ?\\C-\\M-a |
+| literals.rb:84:1:84:3 | :"" | SymbolLiteral | |
+| literals.rb:85:1:85:6 | :hello | SymbolLiteral | hello |
+| literals.rb:86:1:86:10 | :"foo bar" | SymbolLiteral | foo bar |
+| literals.rb:87:1:87:10 | :"bar baz" | SymbolLiteral | bar baz |
+| literals.rb:88:1:88:14 | {...} | HashLiteral | |
+| literals.rb:88:3:88:5 | :foo | SymbolLiteral | foo |
+| literals.rb:88:8:88:12 | "bar" | StringLiteral | bar |
+| literals.rb:89:1:89:10 | :"wibble" | SymbolLiteral | wibble |
+| literals.rb:90:1:90:17 | :"wibble wobble" | SymbolLiteral | wibble wobble |
+| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | |
+| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
+| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | foo_#{ 1 + 1 } |
+| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | foo_#{ 3 - 2 } |
+| literals.rb:96:1:96:2 | [...] | ArrayLiteral | |
+| literals.rb:97:1:97:9 | [...] | ArrayLiteral | |
+| literals.rb:97:2:97:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:97:5:97:5 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:8:97:8 | 3 | IntegerLiteral | 3 |
+| literals.rb:98:1:98:14 | [...] | ArrayLiteral | |
+| literals.rb:98:2:98:2 | 4 | IntegerLiteral | 4 |
+| literals.rb:98:5:98:5 | 5 | IntegerLiteral | 5 |
+| literals.rb:98:8:98:9 | 12 | IntegerLiteral | 12 |
+| literals.rb:98:13:98:13 | 2 | IntegerLiteral | 2 |
+| literals.rb:99:1:99:11 | [...] | ArrayLiteral | |
+| literals.rb:99:2:99:2 | 7 | IntegerLiteral | 7 |
+| literals.rb:99:5:99:10 | [...] | ArrayLiteral | |
+| literals.rb:99:6:99:6 | 8 | IntegerLiteral | 8 |
+| literals.rb:99:9:99:9 | 9 | IntegerLiteral | 9 |
+| literals.rb:102:1:102:4 | %w(...) | ArrayLiteral | |
+| literals.rb:103:1:103:15 | %w(...) | ArrayLiteral | |
+| literals.rb:103:4:103:6 | "foo" | StringLiteral | foo |
+| literals.rb:103:8:103:10 | "bar" | StringLiteral | bar |
+| literals.rb:103:12:103:14 | "baz" | StringLiteral | baz |
+| literals.rb:104:1:104:15 | %w(...) | ArrayLiteral | |
+| literals.rb:104:4:104:6 | "foo" | StringLiteral | foo |
+| literals.rb:104:8:104:10 | "bar" | StringLiteral | bar |
+| literals.rb:104:12:104:14 | "baz" | StringLiteral | baz |
+| literals.rb:105:1:105:21 | %w(...) | ArrayLiteral | |
+| literals.rb:105:4:105:6 | "foo" | StringLiteral | foo |
+| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | |
+| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:18:105:20 | "baz" | StringLiteral | baz |
+| literals.rb:106:1:106:21 | %w(...) | ArrayLiteral | |
+| literals.rb:106:4:106:6 | "foo" | StringLiteral | foo |
+| literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral | bar#{1+1} |
+| literals.rb:106:18:106:20 | "baz" | StringLiteral | baz |
+| literals.rb:109:1:109:4 | %i(...) | ArrayLiteral | |
+| literals.rb:110:1:110:15 | %i(...) | ArrayLiteral | |
+| literals.rb:110:4:110:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:110:8:110:10 | :"bar" | SymbolLiteral | bar |
+| literals.rb:110:12:110:14 | :"baz" | SymbolLiteral | baz |
+| literals.rb:111:1:111:15 | %i(...) | ArrayLiteral | |
+| literals.rb:111:4:111:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:111:8:111:10 | :"bar" | SymbolLiteral | bar |
+| literals.rb:111:12:111:14 | :"baz" | SymbolLiteral | baz |
+| literals.rb:112:1:112:25 | %i(...) | ArrayLiteral | |
+| literals.rb:112:4:112:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | |
+| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
+| literals.rb:112:22:112:24 | :"baz" | SymbolLiteral | baz |
+| literals.rb:113:1:113:25 | %i(...) | ArrayLiteral | |
+| literals.rb:113:4:113:6 | :"foo" | SymbolLiteral | foo |
+| literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral | bar#{ |
+| literals.rb:113:14:113:14 | :"2" | SymbolLiteral | 2 |
+| literals.rb:113:16:113:16 | :"+" | SymbolLiteral | + |
+| literals.rb:113:18:113:18 | :"4" | SymbolLiteral | 4 |
+| literals.rb:113:20:113:20 | :"}" | SymbolLiteral | } |
+| literals.rb:113:22:113:24 | :"baz" | SymbolLiteral | baz |
+| literals.rb:116:1:116:2 | {...} | HashLiteral | |
+| literals.rb:117:1:117:33 | {...} | HashLiteral | |
+| literals.rb:117:3:117:5 | :foo | SymbolLiteral | foo |
+| literals.rb:117:8:117:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:117:11:117:14 | :bar | SymbolLiteral | bar |
+| literals.rb:117:19:117:19 | 2 | IntegerLiteral | 2 |
+| literals.rb:117:22:117:26 | "baz" | StringLiteral | baz |
+| literals.rb:117:31:117:31 | 3 | IntegerLiteral | 3 |
+| literals.rb:118:1:118:17 | {...} | HashLiteral | |
+| literals.rb:118:3:118:5 | :foo | SymbolLiteral | foo |
+| literals.rb:118:8:118:8 | 7 | IntegerLiteral | 7 |
| literals.rb:121:2:121:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:121:2:121:4 | _ .. _ | RangeLiteral | |
-| literals.rb:122:2:122:4 | _ .. _ | RangeLiteral | |
-| literals.rb:122:4:122:4 | 1 | IntegerLiteral | 1 |
-| literals.rb:123:2:123:2 | 0 | IntegerLiteral | 0 |
-| literals.rb:123:2:123:4 | _ .. _ | RangeLiteral | |
-| literals.rb:123:6:123:6 | 1 | IntegerLiteral | 1 |
-| literals.rb:126:1:126:7 | `ls -l` | SubshellLiteral | ls -l |
-| literals.rb:127:1:127:9 | `ls -l` | SubshellLiteral | ls -l |
-| literals.rb:128:1:128:18 | `du -d #{...}` | SubshellLiteral | |
-| literals.rb:128:11:128:11 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:15:128:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:129:1:129:20 | `du -d #{...}` | SubshellLiteral | |
-| literals.rb:129:13:129:13 | 5 | IntegerLiteral | 5 |
-| literals.rb:129:17:129:17 | 4 | IntegerLiteral | 4 |
-| literals.rb:132:1:132:2 | // | RegExpLiteral | |
-| literals.rb:133:1:133:5 | /foo/ | RegExpLiteral | foo |
-| literals.rb:134:1:134:6 | /foo/ | RegExpLiteral | foo |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | |
-| literals.rb:136:8:136:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:136:12:136:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:137:1:137:8 | /foo/ | RegExpLiteral | foo |
-| literals.rb:138:1:138:4 | // | RegExpLiteral | |
-| literals.rb:139:1:139:7 | /foo/ | RegExpLiteral | foo |
-| literals.rb:140:1:140:8 | /foo/ | RegExpLiteral | foo |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | |
-| literals.rb:142:10:142:10 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:14:142:14 | 1 | IntegerLiteral | 1 |
-| literals.rb:143:1:143:10 | /foo/ | RegExpLiteral | foo |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
-| literals.rb:151:9:151:13 | < |
-| literals.rb:158:11:158:16 | <<-BLA | HereDoc | \nsome text\\nand some more\n |
-| literals.rb:163:9:163:19 | <<~SQUIGGLY | HereDoc | \n indented stuff\n |
-| literals.rb:167:9:167:15 | <<"DOC" | HereDoc | |
-| literals.rb:172:9:172:15 | <<'DOC' | HereDoc | |
-| literals.rb:176:10:176:19 | <<`SCRIPT` | HereDoc | \n cat file.txt\n |
+| literals.rb:121:2:121:6 | _ .. _ | RangeLiteral | |
+| literals.rb:121:5:121:6 | 10 | IntegerLiteral | 10 |
+| literals.rb:122:2:122:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:122:2:122:7 | _ ... _ | RangeLiteral | |
+| literals.rb:122:6:122:7 | 10 | IntegerLiteral | 10 |
+| literals.rb:123:2:123:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:123:2:123:7 | _ .. _ | RangeLiteral | |
+| literals.rb:123:7:123:7 | 0 | IntegerLiteral | 0 |
+| literals.rb:124:2:124:11 | _ .. _ | RangeLiteral | |
+| literals.rb:124:9:124:9 | 2 | IntegerLiteral | 2 |
+| literals.rb:124:11:124:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:125:2:125:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:125:2:125:4 | _ .. _ | RangeLiteral | |
+| literals.rb:126:2:126:4 | _ .. _ | RangeLiteral | |
+| literals.rb:126:4:126:4 | 1 | IntegerLiteral | 1 |
+| literals.rb:127:2:127:2 | 0 | IntegerLiteral | 0 |
+| literals.rb:127:2:127:4 | _ .. _ | RangeLiteral | |
+| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
+| literals.rb:130:1:130:7 | `ls -l` | SubshellLiteral | ls -l |
+| literals.rb:131:1:131:9 | `ls -l` | SubshellLiteral | ls -l |
+| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
+| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
+| literals.rb:136:1:136:2 | // | RegExpLiteral | |
+| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | foo |
+| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | foo |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
+| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
+| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
+| literals.rb:142:1:142:4 | // | RegExpLiteral | |
+| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
+| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
+| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
+| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
+| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
+| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
+| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
+| literals.rb:155:9:155:13 | < |
+| literals.rb:162:11:162:16 | <<-BLA | HereDoc | \nsome text\\nand some more\n |
+| literals.rb:167:9:167:19 | <<~SQUIGGLY | HereDoc | \n indented stuff\n |
+| literals.rb:171:9:171:15 | <<"DOC" | HereDoc | |
+| literals.rb:176:9:176:15 | <<'DOC' | HereDoc | |
+| literals.rb:180:10:180:19 | <<`SCRIPT` | HereDoc | \n cat file.txt\n |
stringlikeLiterals
| literals.rb:46:1:46:2 | "" | |
| literals.rb:47:1:47:2 | "" | |
@@ -234,75 +234,75 @@ stringlikeLiterals
| literals.rb:65:1:65:35 | "foo #{...} qux" | |
| literals.rb:65:9:65:28 | "bar #{...} baz" | |
| literals.rb:66:1:66:22 | "foo #{...}" | |
-| literals.rb:80:1:80:3 | :"" | |
-| literals.rb:81:1:81:6 | :hello | hello |
-| literals.rb:82:1:82:10 | :"foo bar" | foo bar |
-| literals.rb:83:1:83:10 | :"bar baz" | bar baz |
-| literals.rb:84:3:84:5 | :foo | foo |
-| literals.rb:84:8:84:12 | "bar" | bar |
-| literals.rb:85:1:85:10 | :"wibble" | wibble |
-| literals.rb:86:1:86:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
-| literals.rb:99:4:99:6 | "foo" | foo |
-| literals.rb:99:8:99:10 | "bar" | bar |
-| literals.rb:99:12:99:14 | "baz" | baz |
-| literals.rb:100:4:100:6 | "foo" | foo |
-| literals.rb:100:8:100:10 | "bar" | bar |
-| literals.rb:100:12:100:14 | "baz" | baz |
-| literals.rb:101:4:101:6 | "foo" | foo |
-| literals.rb:101:8:101:16 | "bar#{...}" | |
-| literals.rb:101:18:101:20 | "baz" | baz |
-| literals.rb:102:4:102:6 | "foo" | foo |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:102:18:102:20 | "baz" | baz |
-| literals.rb:106:4:106:6 | :"foo" | foo |
-| literals.rb:106:8:106:10 | :"bar" | bar |
-| literals.rb:106:12:106:14 | :"baz" | baz |
-| literals.rb:107:4:107:6 | :"foo" | foo |
-| literals.rb:107:8:107:10 | :"bar" | bar |
-| literals.rb:107:12:107:14 | :"baz" | baz |
-| literals.rb:108:4:108:6 | :"foo" | foo |
-| literals.rb:108:8:108:20 | :"bar#{...}" | |
-| literals.rb:108:22:108:24 | :"baz" | baz |
-| literals.rb:109:4:109:6 | :"foo" | foo |
-| literals.rb:109:8:109:12 | :"bar#{" | bar#{ |
-| literals.rb:109:14:109:14 | :"2" | 2 |
-| literals.rb:109:16:109:16 | :"+" | + |
-| literals.rb:109:18:109:18 | :"4" | 4 |
-| literals.rb:109:20:109:20 | :"}" | } |
-| literals.rb:109:22:109:24 | :"baz" | baz |
-| literals.rb:113:3:113:5 | :foo | foo |
-| literals.rb:113:11:113:14 | :bar | bar |
-| literals.rb:113:22:113:26 | "baz" | baz |
-| literals.rb:114:3:114:5 | :foo | foo |
-| literals.rb:126:1:126:7 | `ls -l` | ls -l |
-| literals.rb:127:1:127:9 | `ls -l` | ls -l |
-| literals.rb:128:1:128:18 | `du -d #{...}` | |
-| literals.rb:129:1:129:20 | `du -d #{...}` | |
-| literals.rb:132:1:132:2 | // | |
-| literals.rb:133:1:133:5 | /foo/ | foo |
-| literals.rb:134:1:134:6 | /foo/ | foo |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | |
-| literals.rb:137:1:137:8 | /foo/ | foo |
-| literals.rb:138:1:138:4 | // | |
-| literals.rb:139:1:139:7 | /foo/ | foo |
-| literals.rb:140:1:140:8 | /foo/ | foo |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | |
-| literals.rb:143:1:143:10 | /foo/ | foo |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
-| literals.rb:151:9:151:13 | < |
-| literals.rb:158:11:158:16 | <<-BLA | \nsome text\\nand some more\n |
-| literals.rb:163:9:163:19 | <<~SQUIGGLY | \n indented stuff\n |
-| literals.rb:167:9:167:15 | <<"DOC" | |
-| literals.rb:172:9:172:15 | <<'DOC' | |
-| literals.rb:176:10:176:19 | <<`SCRIPT` | \n cat file.txt\n |
+| literals.rb:84:1:84:3 | :"" | |
+| literals.rb:85:1:85:6 | :hello | hello |
+| literals.rb:86:1:86:10 | :"foo bar" | foo bar |
+| literals.rb:87:1:87:10 | :"bar baz" | bar baz |
+| literals.rb:88:3:88:5 | :foo | foo |
+| literals.rb:88:8:88:12 | "bar" | bar |
+| literals.rb:89:1:89:10 | :"wibble" | wibble |
+| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
+| literals.rb:91:1:91:16 | :"foo_#{...}" | |
+| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
+| literals.rb:103:4:103:6 | "foo" | foo |
+| literals.rb:103:8:103:10 | "bar" | bar |
+| literals.rb:103:12:103:14 | "baz" | baz |
+| literals.rb:104:4:104:6 | "foo" | foo |
+| literals.rb:104:8:104:10 | "bar" | bar |
+| literals.rb:104:12:104:14 | "baz" | baz |
+| literals.rb:105:4:105:6 | "foo" | foo |
+| literals.rb:105:8:105:16 | "bar#{...}" | |
+| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:106:4:106:6 | "foo" | foo |
+| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
+| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:110:4:110:6 | :"foo" | foo |
+| literals.rb:110:8:110:10 | :"bar" | bar |
+| literals.rb:110:12:110:14 | :"baz" | baz |
+| literals.rb:111:4:111:6 | :"foo" | foo |
+| literals.rb:111:8:111:10 | :"bar" | bar |
+| literals.rb:111:12:111:14 | :"baz" | baz |
+| literals.rb:112:4:112:6 | :"foo" | foo |
+| literals.rb:112:8:112:20 | :"bar#{...}" | |
+| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:113:4:113:6 | :"foo" | foo |
+| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
+| literals.rb:113:14:113:14 | :"2" | 2 |
+| literals.rb:113:16:113:16 | :"+" | + |
+| literals.rb:113:18:113:18 | :"4" | 4 |
+| literals.rb:113:20:113:20 | :"}" | } |
+| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:117:3:117:5 | :foo | foo |
+| literals.rb:117:11:117:14 | :bar | bar |
+| literals.rb:117:22:117:26 | "baz" | baz |
+| literals.rb:118:3:118:5 | :foo | foo |
+| literals.rb:130:1:130:7 | `ls -l` | ls -l |
+| literals.rb:131:1:131:9 | `ls -l` | ls -l |
+| literals.rb:132:1:132:18 | `du -d #{...}` | |
+| literals.rb:133:1:133:20 | `du -d #{...}` | |
+| literals.rb:136:1:136:2 | // | |
+| literals.rb:137:1:137:5 | /foo/ | foo |
+| literals.rb:138:1:138:6 | /foo/ | foo |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals.rb:140:1:140:18 | /foo#{...}bar/ | |
+| literals.rb:141:1:141:8 | /foo/ | foo |
+| literals.rb:142:1:142:4 | // | |
+| literals.rb:143:1:143:7 | /foo/ | foo |
+| literals.rb:144:1:144:8 | /foo/ | foo |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals.rb:146:1:146:20 | /foo#{...}bar/ | |
+| literals.rb:147:1:147:10 | /foo/ | foo |
+| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
+| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
+| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
+| literals.rb:155:9:155:13 | < |
+| literals.rb:162:11:162:16 | <<-BLA | \nsome text\\nand some more\n |
+| literals.rb:167:9:167:19 | <<~SQUIGGLY | \n indented stuff\n |
+| literals.rb:171:9:171:15 | <<"DOC" | |
+| literals.rb:176:9:176:15 | <<'DOC' | |
+| literals.rb:180:10:180:19 | <<`SCRIPT` | \n cat file.txt\n |
stringLiterals
| literals.rb:46:1:46:2 | "" | |
| literals.rb:47:1:47:2 | "" | |
@@ -332,71 +332,71 @@ stringLiterals
| literals.rb:65:1:65:35 | "foo #{...} qux" | |
| literals.rb:65:9:65:28 | "bar #{...} baz" | |
| literals.rb:66:1:66:22 | "foo #{...}" | |
-| literals.rb:84:8:84:12 | "bar" | bar |
-| literals.rb:99:4:99:6 | "foo" | foo |
-| literals.rb:99:8:99:10 | "bar" | bar |
-| literals.rb:99:12:99:14 | "baz" | baz |
-| literals.rb:100:4:100:6 | "foo" | foo |
-| literals.rb:100:8:100:10 | "bar" | bar |
-| literals.rb:100:12:100:14 | "baz" | baz |
-| literals.rb:101:4:101:6 | "foo" | foo |
-| literals.rb:101:8:101:16 | "bar#{...}" | |
-| literals.rb:101:18:101:20 | "baz" | baz |
-| literals.rb:102:4:102:6 | "foo" | foo |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:102:18:102:20 | "baz" | baz |
-| literals.rb:113:22:113:26 | "baz" | baz |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
+| literals.rb:88:8:88:12 | "bar" | bar |
+| literals.rb:103:4:103:6 | "foo" | foo |
+| literals.rb:103:8:103:10 | "bar" | bar |
+| literals.rb:103:12:103:14 | "baz" | baz |
+| literals.rb:104:4:104:6 | "foo" | foo |
+| literals.rb:104:8:104:10 | "bar" | bar |
+| literals.rb:104:12:104:14 | "baz" | baz |
+| literals.rb:105:4:105:6 | "foo" | foo |
+| literals.rb:105:8:105:16 | "bar#{...}" | |
+| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:106:4:106:6 | "foo" | foo |
+| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
+| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:117:22:117:26 | "baz" | baz |
+| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
+| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
+| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
regExpLiterals
-| literals.rb:132:1:132:2 | // | | |
-| literals.rb:133:1:133:5 | /foo/ | foo | |
-| literals.rb:134:1:134:6 | /foo/ | foo | i |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | | |
-| literals.rb:137:1:137:8 | /foo/ | foo | oxm |
-| literals.rb:138:1:138:4 | // | | |
-| literals.rb:139:1:139:7 | /foo/ | foo | |
-| literals.rb:140:1:140:8 | /foo/ | foo | i |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | | |
-| literals.rb:143:1:143:10 | /foo/ | foo | mxo |
+| literals.rb:136:1:136:2 | // | | |
+| literals.rb:137:1:137:5 | /foo/ | foo | |
+| literals.rb:138:1:138:6 | /foo/ | foo | i |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
+| literals.rb:140:1:140:18 | /foo#{...}bar/ | | |
+| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
+| literals.rb:142:1:142:4 | // | | |
+| literals.rb:143:1:143:7 | /foo/ | foo | |
+| literals.rb:144:1:144:8 | /foo/ | foo | i |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
+| literals.rb:146:1:146:20 | /foo#{...}bar/ | | |
+| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
symbolLiterals
-| literals.rb:80:1:80:3 | :"" | |
-| literals.rb:81:1:81:6 | :hello | hello |
-| literals.rb:82:1:82:10 | :"foo bar" | foo bar |
-| literals.rb:83:1:83:10 | :"bar baz" | bar baz |
-| literals.rb:84:3:84:5 | :foo | foo |
-| literals.rb:85:1:85:10 | :"wibble" | wibble |
-| literals.rb:86:1:86:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
-| literals.rb:106:4:106:6 | :"foo" | foo |
-| literals.rb:106:8:106:10 | :"bar" | bar |
-| literals.rb:106:12:106:14 | :"baz" | baz |
-| literals.rb:107:4:107:6 | :"foo" | foo |
-| literals.rb:107:8:107:10 | :"bar" | bar |
-| literals.rb:107:12:107:14 | :"baz" | baz |
-| literals.rb:108:4:108:6 | :"foo" | foo |
-| literals.rb:108:8:108:20 | :"bar#{...}" | |
-| literals.rb:108:22:108:24 | :"baz" | baz |
-| literals.rb:109:4:109:6 | :"foo" | foo |
-| literals.rb:109:8:109:12 | :"bar#{" | bar#{ |
-| literals.rb:109:14:109:14 | :"2" | 2 |
-| literals.rb:109:16:109:16 | :"+" | + |
-| literals.rb:109:18:109:18 | :"4" | 4 |
-| literals.rb:109:20:109:20 | :"}" | } |
-| literals.rb:109:22:109:24 | :"baz" | baz |
-| literals.rb:113:3:113:5 | :foo | foo |
-| literals.rb:113:11:113:14 | :bar | bar |
-| literals.rb:114:3:114:5 | :foo | foo |
+| literals.rb:84:1:84:3 | :"" | |
+| literals.rb:85:1:85:6 | :hello | hello |
+| literals.rb:86:1:86:10 | :"foo bar" | foo bar |
+| literals.rb:87:1:87:10 | :"bar baz" | bar baz |
+| literals.rb:88:3:88:5 | :foo | foo |
+| literals.rb:89:1:89:10 | :"wibble" | wibble |
+| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
+| literals.rb:91:1:91:16 | :"foo_#{...}" | |
+| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
+| literals.rb:110:4:110:6 | :"foo" | foo |
+| literals.rb:110:8:110:10 | :"bar" | bar |
+| literals.rb:110:12:110:14 | :"baz" | baz |
+| literals.rb:111:4:111:6 | :"foo" | foo |
+| literals.rb:111:8:111:10 | :"bar" | bar |
+| literals.rb:111:12:111:14 | :"baz" | baz |
+| literals.rb:112:4:112:6 | :"foo" | foo |
+| literals.rb:112:8:112:20 | :"bar#{...}" | |
+| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:113:4:113:6 | :"foo" | foo |
+| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
+| literals.rb:113:14:113:14 | :"2" | 2 |
+| literals.rb:113:16:113:16 | :"+" | + |
+| literals.rb:113:18:113:18 | :"4" | 4 |
+| literals.rb:113:20:113:20 | :"}" | } |
+| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:117:3:117:5 | :foo | foo |
+| literals.rb:117:11:117:14 | :bar | bar |
+| literals.rb:118:3:118:5 | :foo | foo |
subshellLiterals
-| literals.rb:126:1:126:7 | `ls -l` | ls -l |
-| literals.rb:127:1:127:9 | `ls -l` | ls -l |
-| literals.rb:128:1:128:18 | `du -d #{...}` | |
-| literals.rb:129:1:129:20 | `du -d #{...}` | |
+| literals.rb:130:1:130:7 | `ls -l` | ls -l |
+| literals.rb:131:1:131:9 | `ls -l` | ls -l |
+| literals.rb:132:1:132:18 | `du -d #{...}` | |
+| literals.rb:133:1:133:20 | `du -d #{...}` | |
stringComponents
| literals.rb:48:1:48:7 | "hello" | StringLiteral | 0 | literals.rb:48:2:48:6 | hello | StringTextComponent |
| literals.rb:49:1:49:9 | "goodbye" | StringLiteral | 0 | literals.rb:49:2:49:8 | goodbye | StringTextComponent |
@@ -436,98 +436,98 @@ stringComponents
| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | 2 | literals.rb:65:24:65:27 | baz | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 0 | literals.rb:66:2:66:5 | foo | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 1 | literals.rb:66:6:66:21 | #{...} | StringInterpolationComponent |
-| literals.rb:82:1:82:10 | :"foo bar" | SymbolLiteral | 0 | literals.rb:82:3:82:9 | foo bar | StringTextComponent |
-| literals.rb:83:1:83:10 | :"bar baz" | SymbolLiteral | 0 | literals.rb:83:3:83:9 | bar baz | StringTextComponent |
-| literals.rb:84:8:84:12 | "bar" | StringLiteral | 0 | literals.rb:84:9:84:11 | bar | StringTextComponent |
-| literals.rb:85:1:85:10 | :"wibble" | SymbolLiteral | 0 | literals.rb:85:4:85:9 | wibble | StringTextComponent |
-| literals.rb:86:1:86:17 | :"wibble wobble" | SymbolLiteral | 0 | literals.rb:86:4:86:16 | wibble wobble | StringTextComponent |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | SymbolLiteral | 0 | literals.rb:87:3:87:6 | foo_ | StringTextComponent |
-| literals.rb:87:1:87:16 | :"foo_#{...}" | SymbolLiteral | 1 | literals.rb:87:7:87:15 | #{...} | StringInterpolationComponent |
-| literals.rb:88:1:88:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | 0 | literals.rb:88:3:88:16 | foo_#{ 1 + 1 } | StringTextComponent |
-| literals.rb:89:1:89:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | 0 | literals.rb:89:4:89:17 | foo_#{ 3 - 2 } | StringTextComponent |
-| literals.rb:99:4:99:6 | "foo" | StringLiteral | 0 | literals.rb:99:4:99:6 | foo | StringTextComponent |
-| literals.rb:99:8:99:10 | "bar" | StringLiteral | 0 | literals.rb:99:8:99:10 | bar | StringTextComponent |
-| literals.rb:99:12:99:14 | "baz" | StringLiteral | 0 | literals.rb:99:12:99:14 | baz | StringTextComponent |
-| literals.rb:100:4:100:6 | "foo" | StringLiteral | 0 | literals.rb:100:4:100:6 | foo | StringTextComponent |
-| literals.rb:100:8:100:10 | "bar" | StringLiteral | 0 | literals.rb:100:8:100:10 | bar | StringTextComponent |
-| literals.rb:100:12:100:14 | "baz" | StringLiteral | 0 | literals.rb:100:12:100:14 | baz | StringTextComponent |
-| literals.rb:101:4:101:6 | "foo" | StringLiteral | 0 | literals.rb:101:4:101:6 | foo | StringTextComponent |
-| literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral | 0 | literals.rb:101:8:101:10 | bar | StringTextComponent |
-| literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral | 1 | literals.rb:101:11:101:16 | #{...} | StringInterpolationComponent |
-| literals.rb:101:18:101:20 | "baz" | StringLiteral | 0 | literals.rb:101:18:101:20 | baz | StringTextComponent |
-| literals.rb:102:4:102:6 | "foo" | StringLiteral | 0 | literals.rb:102:4:102:6 | foo | StringTextComponent |
-| literals.rb:102:8:102:16 | "bar#{1+1}" | StringLiteral | 0 | literals.rb:102:8:102:16 | bar#{1+1} | StringTextComponent |
-| literals.rb:102:18:102:20 | "baz" | StringLiteral | 0 | literals.rb:102:18:102:20 | baz | StringTextComponent |
-| literals.rb:106:4:106:6 | :"foo" | SymbolLiteral | 0 | literals.rb:106:4:106:6 | foo | StringTextComponent |
-| literals.rb:106:8:106:10 | :"bar" | SymbolLiteral | 0 | literals.rb:106:8:106:10 | bar | StringTextComponent |
-| literals.rb:106:12:106:14 | :"baz" | SymbolLiteral | 0 | literals.rb:106:12:106:14 | baz | StringTextComponent |
-| literals.rb:107:4:107:6 | :"foo" | SymbolLiteral | 0 | literals.rb:107:4:107:6 | foo | StringTextComponent |
-| literals.rb:107:8:107:10 | :"bar" | SymbolLiteral | 0 | literals.rb:107:8:107:10 | bar | StringTextComponent |
-| literals.rb:107:12:107:14 | :"baz" | SymbolLiteral | 0 | literals.rb:107:12:107:14 | baz | StringTextComponent |
-| literals.rb:108:4:108:6 | :"foo" | SymbolLiteral | 0 | literals.rb:108:4:108:6 | foo | StringTextComponent |
-| literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral | 0 | literals.rb:108:8:108:10 | bar | StringTextComponent |
-| literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral | 1 | literals.rb:108:11:108:20 | #{...} | StringInterpolationComponent |
-| literals.rb:108:22:108:24 | :"baz" | SymbolLiteral | 0 | literals.rb:108:22:108:24 | baz | StringTextComponent |
-| literals.rb:109:4:109:6 | :"foo" | SymbolLiteral | 0 | literals.rb:109:4:109:6 | foo | StringTextComponent |
-| literals.rb:109:8:109:12 | :"bar#{" | SymbolLiteral | 0 | literals.rb:109:8:109:12 | bar#{ | StringTextComponent |
-| literals.rb:109:14:109:14 | :"2" | SymbolLiteral | 0 | literals.rb:109:14:109:14 | 2 | StringTextComponent |
-| literals.rb:109:16:109:16 | :"+" | SymbolLiteral | 0 | literals.rb:109:16:109:16 | + | StringTextComponent |
-| literals.rb:109:18:109:18 | :"4" | SymbolLiteral | 0 | literals.rb:109:18:109:18 | 4 | StringTextComponent |
-| literals.rb:109:20:109:20 | :"}" | SymbolLiteral | 0 | literals.rb:109:20:109:20 | } | StringTextComponent |
-| literals.rb:109:22:109:24 | :"baz" | SymbolLiteral | 0 | literals.rb:109:22:109:24 | baz | StringTextComponent |
-| literals.rb:113:22:113:26 | "baz" | StringLiteral | 0 | literals.rb:113:23:113:25 | baz | StringTextComponent |
-| literals.rb:126:1:126:7 | `ls -l` | SubshellLiteral | 0 | literals.rb:126:2:126:6 | ls -l | StringTextComponent |
-| literals.rb:127:1:127:9 | `ls -l` | SubshellLiteral | 0 | literals.rb:127:4:127:8 | ls -l | StringTextComponent |
-| literals.rb:128:1:128:18 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:128:2:128:7 | du -d | StringTextComponent |
-| literals.rb:128:1:128:18 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:128:8:128:17 | #{...} | StringInterpolationComponent |
-| literals.rb:129:1:129:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:129:4:129:9 | du -d | StringTextComponent |
-| literals.rb:129:1:129:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:129:10:129:19 | #{...} | StringInterpolationComponent |
-| literals.rb:133:1:133:5 | /foo/ | RegExpLiteral | 0 | literals.rb:133:2:133:4 | foo | StringTextComponent |
-| literals.rb:134:1:134:6 | /foo/ | RegExpLiteral | 0 | literals.rb:134:2:134:4 | foo | StringTextComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:135:2:135:5 | foo+ | StringTextComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:135:6:135:7 | \\s | StringEscapeSequenceComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:135:8:135:10 | bar | StringTextComponent |
-| literals.rb:135:1:135:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:135:11:135:12 | \\S | StringEscapeSequenceComponent |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:136:2:136:4 | foo | StringTextComponent |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:136:5:136:14 | #{...} | StringInterpolationComponent |
-| literals.rb:136:1:136:18 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:136:15:136:17 | bar | StringTextComponent |
-| literals.rb:137:1:137:8 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
-| literals.rb:139:1:139:7 | /foo/ | RegExpLiteral | 0 | literals.rb:139:4:139:6 | foo | StringTextComponent |
-| literals.rb:140:1:140:8 | /foo/ | RegExpLiteral | 0 | literals.rb:140:4:140:6 | foo | StringTextComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:141:4:141:7 | foo+ | StringTextComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:141:8:141:9 | \\s | StringEscapeSequenceComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:141:10:141:12 | bar | StringTextComponent |
-| literals.rb:141:1:141:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:141:13:141:14 | \\S | StringEscapeSequenceComponent |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:142:4:142:6 | foo | StringTextComponent |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:142:7:142:16 | #{...} | StringInterpolationComponent |
-| literals.rb:142:1:142:20 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:142:17:142:19 | bar | StringTextComponent |
-| literals.rb:143:1:143:10 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
-| literals.rb:146:1:146:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:146:2:146:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
-| literals.rb:147:1:147:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:147:2:147:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 0 | literals.rb:148:2:148:7 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 1 | literals.rb:148:8:148:9 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 2 | literals.rb:148:10:148:15 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 3 | literals.rb:148:16:148:17 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 4 | literals.rb:148:18:148:23 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 5 | literals.rb:148:24:148:25 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 6 | literals.rb:148:26:148:31 | foobar | StringTextComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 7 | literals.rb:148:32:148:33 | \\\\ | StringEscapeSequenceComponent |
-| literals.rb:148:1:148:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 8 | literals.rb:148:34:148:39 | foobar | StringTextComponent |
-| literals.rb:151:9:151:13 | < | 1 | literals.rb:64:7:64:21 | "bar#{...}" |
| literals.rb:64:1:64:27 | "..." "..." | | 2 | literals.rb:64:23:64:27 | "baz" |
arrayLiterals
-| literals.rb:92:1:92:2 | [...] | 0 |
-| literals.rb:93:1:93:9 | [...] | 3 |
-| literals.rb:94:1:94:14 | [...] | 3 |
-| literals.rb:95:1:95:11 | [...] | 2 |
-| literals.rb:95:5:95:10 | [...] | 2 |
-| literals.rb:98:1:98:4 | %w(...) | 0 |
-| literals.rb:99:1:99:15 | %w(...) | 3 |
-| literals.rb:100:1:100:15 | %w(...) | 3 |
-| literals.rb:101:1:101:21 | %w(...) | 3 |
-| literals.rb:102:1:102:21 | %w(...) | 3 |
-| literals.rb:105:1:105:4 | %i(...) | 0 |
-| literals.rb:106:1:106:15 | %i(...) | 3 |
-| literals.rb:107:1:107:15 | %i(...) | 3 |
-| literals.rb:108:1:108:25 | %i(...) | 3 |
-| literals.rb:109:1:109:25 | %i(...) | 7 |
+| literals.rb:96:1:96:2 | [...] | 0 |
+| literals.rb:97:1:97:9 | [...] | 3 |
+| literals.rb:98:1:98:14 | [...] | 3 |
+| literals.rb:99:1:99:11 | [...] | 2 |
+| literals.rb:99:5:99:10 | [...] | 2 |
+| literals.rb:102:1:102:4 | %w(...) | 0 |
+| literals.rb:103:1:103:15 | %w(...) | 3 |
+| literals.rb:104:1:104:15 | %w(...) | 3 |
+| literals.rb:105:1:105:21 | %w(...) | 3 |
+| literals.rb:106:1:106:21 | %w(...) | 3 |
+| literals.rb:109:1:109:4 | %i(...) | 0 |
+| literals.rb:110:1:110:15 | %i(...) | 3 |
+| literals.rb:111:1:111:15 | %i(...) | 3 |
+| literals.rb:112:1:112:25 | %i(...) | 3 |
+| literals.rb:113:1:113:25 | %i(...) | 7 |
arrayLiteralElements
-| literals.rb:93:1:93:9 | [...] | 0 | literals.rb:93:2:93:2 | 1 | IntegerLiteral |
-| literals.rb:93:1:93:9 | [...] | 1 | literals.rb:93:5:93:5 | 2 | IntegerLiteral |
-| literals.rb:93:1:93:9 | [...] | 2 | literals.rb:93:8:93:8 | 3 | IntegerLiteral |
-| literals.rb:94:1:94:14 | [...] | 0 | literals.rb:94:2:94:2 | 4 | IntegerLiteral |
-| literals.rb:94:1:94:14 | [...] | 1 | literals.rb:94:5:94:5 | 5 | IntegerLiteral |
-| literals.rb:94:1:94:14 | [...] | 2 | literals.rb:94:8:94:13 | ... / ... | DivExpr |
-| literals.rb:95:1:95:11 | [...] | 0 | literals.rb:95:2:95:2 | 7 | IntegerLiteral |
-| literals.rb:95:1:95:11 | [...] | 1 | literals.rb:95:5:95:10 | [...] | ArrayLiteral |
-| literals.rb:95:5:95:10 | [...] | 0 | literals.rb:95:6:95:6 | 8 | IntegerLiteral |
-| literals.rb:95:5:95:10 | [...] | 1 | literals.rb:95:9:95:9 | 9 | IntegerLiteral |
-| literals.rb:99:1:99:15 | %w(...) | 0 | literals.rb:99:4:99:6 | "foo" | StringLiteral |
-| literals.rb:99:1:99:15 | %w(...) | 1 | literals.rb:99:8:99:10 | "bar" | StringLiteral |
-| literals.rb:99:1:99:15 | %w(...) | 2 | literals.rb:99:12:99:14 | "baz" | StringLiteral |
-| literals.rb:100:1:100:15 | %w(...) | 0 | literals.rb:100:4:100:6 | "foo" | StringLiteral |
-| literals.rb:100:1:100:15 | %w(...) | 1 | literals.rb:100:8:100:10 | "bar" | StringLiteral |
-| literals.rb:100:1:100:15 | %w(...) | 2 | literals.rb:100:12:100:14 | "baz" | StringLiteral |
-| literals.rb:101:1:101:21 | %w(...) | 0 | literals.rb:101:4:101:6 | "foo" | StringLiteral |
-| literals.rb:101:1:101:21 | %w(...) | 1 | literals.rb:101:8:101:16 | "bar#{...}" | StringLiteral |
-| literals.rb:101:1:101:21 | %w(...) | 2 | literals.rb:101:18:101:20 | "baz" | StringLiteral |
-| literals.rb:102:1:102:21 | %w(...) | 0 | literals.rb:102:4:102:6 | "foo" | StringLiteral |
-| literals.rb:102:1:102:21 | %w(...) | 1 | literals.rb:102:8:102:16 | "bar#{1+1}" | StringLiteral |
-| literals.rb:102:1:102:21 | %w(...) | 2 | literals.rb:102:18:102:20 | "baz" | StringLiteral |
-| literals.rb:106:1:106:15 | %i(...) | 0 | literals.rb:106:4:106:6 | :"foo" | SymbolLiteral |
-| literals.rb:106:1:106:15 | %i(...) | 1 | literals.rb:106:8:106:10 | :"bar" | SymbolLiteral |
-| literals.rb:106:1:106:15 | %i(...) | 2 | literals.rb:106:12:106:14 | :"baz" | SymbolLiteral |
-| literals.rb:107:1:107:15 | %i(...) | 0 | literals.rb:107:4:107:6 | :"foo" | SymbolLiteral |
-| literals.rb:107:1:107:15 | %i(...) | 1 | literals.rb:107:8:107:10 | :"bar" | SymbolLiteral |
-| literals.rb:107:1:107:15 | %i(...) | 2 | literals.rb:107:12:107:14 | :"baz" | SymbolLiteral |
-| literals.rb:108:1:108:25 | %i(...) | 0 | literals.rb:108:4:108:6 | :"foo" | SymbolLiteral |
-| literals.rb:108:1:108:25 | %i(...) | 1 | literals.rb:108:8:108:20 | :"bar#{...}" | SymbolLiteral |
-| literals.rb:108:1:108:25 | %i(...) | 2 | literals.rb:108:22:108:24 | :"baz" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 0 | literals.rb:109:4:109:6 | :"foo" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 1 | literals.rb:109:8:109:12 | :"bar#{" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 2 | literals.rb:109:14:109:14 | :"2" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 3 | literals.rb:109:16:109:16 | :"+" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 4 | literals.rb:109:18:109:18 | :"4" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 5 | literals.rb:109:20:109:20 | :"}" | SymbolLiteral |
-| literals.rb:109:1:109:25 | %i(...) | 6 | literals.rb:109:22:109:24 | :"baz" | SymbolLiteral |
+| literals.rb:97:1:97:9 | [...] | 0 | literals.rb:97:2:97:2 | 1 | IntegerLiteral |
+| literals.rb:97:1:97:9 | [...] | 1 | literals.rb:97:5:97:5 | 2 | IntegerLiteral |
+| literals.rb:97:1:97:9 | [...] | 2 | literals.rb:97:8:97:8 | 3 | IntegerLiteral |
+| literals.rb:98:1:98:14 | [...] | 0 | literals.rb:98:2:98:2 | 4 | IntegerLiteral |
+| literals.rb:98:1:98:14 | [...] | 1 | literals.rb:98:5:98:5 | 5 | IntegerLiteral |
+| literals.rb:98:1:98:14 | [...] | 2 | literals.rb:98:8:98:13 | ... / ... | DivExpr |
+| literals.rb:99:1:99:11 | [...] | 0 | literals.rb:99:2:99:2 | 7 | IntegerLiteral |
+| literals.rb:99:1:99:11 | [...] | 1 | literals.rb:99:5:99:10 | [...] | ArrayLiteral |
+| literals.rb:99:5:99:10 | [...] | 0 | literals.rb:99:6:99:6 | 8 | IntegerLiteral |
+| literals.rb:99:5:99:10 | [...] | 1 | literals.rb:99:9:99:9 | 9 | IntegerLiteral |
+| literals.rb:103:1:103:15 | %w(...) | 0 | literals.rb:103:4:103:6 | "foo" | StringLiteral |
+| literals.rb:103:1:103:15 | %w(...) | 1 | literals.rb:103:8:103:10 | "bar" | StringLiteral |
+| literals.rb:103:1:103:15 | %w(...) | 2 | literals.rb:103:12:103:14 | "baz" | StringLiteral |
+| literals.rb:104:1:104:15 | %w(...) | 0 | literals.rb:104:4:104:6 | "foo" | StringLiteral |
+| literals.rb:104:1:104:15 | %w(...) | 1 | literals.rb:104:8:104:10 | "bar" | StringLiteral |
+| literals.rb:104:1:104:15 | %w(...) | 2 | literals.rb:104:12:104:14 | "baz" | StringLiteral |
+| literals.rb:105:1:105:21 | %w(...) | 0 | literals.rb:105:4:105:6 | "foo" | StringLiteral |
+| literals.rb:105:1:105:21 | %w(...) | 1 | literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral |
+| literals.rb:105:1:105:21 | %w(...) | 2 | literals.rb:105:18:105:20 | "baz" | StringLiteral |
+| literals.rb:106:1:106:21 | %w(...) | 0 | literals.rb:106:4:106:6 | "foo" | StringLiteral |
+| literals.rb:106:1:106:21 | %w(...) | 1 | literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral |
+| literals.rb:106:1:106:21 | %w(...) | 2 | literals.rb:106:18:106:20 | "baz" | StringLiteral |
+| literals.rb:110:1:110:15 | %i(...) | 0 | literals.rb:110:4:110:6 | :"foo" | SymbolLiteral |
+| literals.rb:110:1:110:15 | %i(...) | 1 | literals.rb:110:8:110:10 | :"bar" | SymbolLiteral |
+| literals.rb:110:1:110:15 | %i(...) | 2 | literals.rb:110:12:110:14 | :"baz" | SymbolLiteral |
+| literals.rb:111:1:111:15 | %i(...) | 0 | literals.rb:111:4:111:6 | :"foo" | SymbolLiteral |
+| literals.rb:111:1:111:15 | %i(...) | 1 | literals.rb:111:8:111:10 | :"bar" | SymbolLiteral |
+| literals.rb:111:1:111:15 | %i(...) | 2 | literals.rb:111:12:111:14 | :"baz" | SymbolLiteral |
+| literals.rb:112:1:112:25 | %i(...) | 0 | literals.rb:112:4:112:6 | :"foo" | SymbolLiteral |
+| literals.rb:112:1:112:25 | %i(...) | 1 | literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:25 | %i(...) | 2 | literals.rb:112:22:112:24 | :"baz" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 0 | literals.rb:113:4:113:6 | :"foo" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 1 | literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 2 | literals.rb:113:14:113:14 | :"2" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 3 | literals.rb:113:16:113:16 | :"+" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 4 | literals.rb:113:18:113:18 | :"4" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 5 | literals.rb:113:20:113:20 | :"}" | SymbolLiteral |
+| literals.rb:113:1:113:25 | %i(...) | 6 | literals.rb:113:22:113:24 | :"baz" | SymbolLiteral |
hashLiterals
-| literals.rb:84:1:84:14 | {...} | 1 |
-| literals.rb:112:1:112:2 | {...} | 0 |
-| literals.rb:113:1:113:33 | {...} | 3 |
-| literals.rb:114:1:114:17 | {...} | 2 |
+| literals.rb:88:1:88:14 | {...} | 1 |
+| literals.rb:116:1:116:2 | {...} | 0 |
+| literals.rb:117:1:117:33 | {...} | 3 |
+| literals.rb:118:1:118:17 | {...} | 2 |
hashLiteralElements
-| literals.rb:84:1:84:14 | {...} | 0 | literals.rb:84:3:84:12 | Pair | Pair |
-| literals.rb:113:1:113:33 | {...} | 0 | literals.rb:113:3:113:8 | Pair | Pair |
-| literals.rb:113:1:113:33 | {...} | 1 | literals.rb:113:11:113:19 | Pair | Pair |
-| literals.rb:113:1:113:33 | {...} | 2 | literals.rb:113:22:113:31 | Pair | Pair |
-| literals.rb:114:1:114:17 | {...} | 0 | literals.rb:114:3:114:8 | Pair | Pair |
-| literals.rb:114:1:114:17 | {...} | 1 | literals.rb:114:11:114:15 | ** ... | HashSplatExpr |
+| literals.rb:88:1:88:14 | {...} | 0 | literals.rb:88:3:88:12 | Pair | Pair |
+| literals.rb:117:1:117:33 | {...} | 0 | literals.rb:117:3:117:8 | Pair | Pair |
+| literals.rb:117:1:117:33 | {...} | 1 | literals.rb:117:11:117:19 | Pair | Pair |
+| literals.rb:117:1:117:33 | {...} | 2 | literals.rb:117:22:117:31 | Pair | Pair |
+| literals.rb:118:1:118:17 | {...} | 0 | literals.rb:118:3:118:8 | Pair | Pair |
+| literals.rb:118:1:118:17 | {...} | 1 | literals.rb:118:11:118:15 | ** ... | HashSplatExpr |
hashLiteralKeyValuePairs
-| literals.rb:84:1:84:14 | {...} | literals.rb:84:3:84:12 | Pair | literals.rb:84:3:84:5 | :foo | literals.rb:84:8:84:12 | "bar" |
-| literals.rb:113:1:113:33 | {...} | literals.rb:113:3:113:8 | Pair | literals.rb:113:3:113:5 | :foo | literals.rb:113:8:113:8 | 1 |
-| literals.rb:113:1:113:33 | {...} | literals.rb:113:11:113:19 | Pair | literals.rb:113:11:113:14 | :bar | literals.rb:113:19:113:19 | 2 |
-| literals.rb:113:1:113:33 | {...} | literals.rb:113:22:113:31 | Pair | literals.rb:113:22:113:26 | "baz" | literals.rb:113:31:113:31 | 3 |
-| literals.rb:114:1:114:17 | {...} | literals.rb:114:3:114:8 | Pair | literals.rb:114:3:114:5 | :foo | literals.rb:114:8:114:8 | 7 |
+| literals.rb:88:1:88:14 | {...} | literals.rb:88:3:88:12 | Pair | literals.rb:88:3:88:5 | :foo | literals.rb:88:8:88:12 | "bar" |
+| literals.rb:117:1:117:33 | {...} | literals.rb:117:3:117:8 | Pair | literals.rb:117:3:117:5 | :foo | literals.rb:117:8:117:8 | 1 |
+| literals.rb:117:1:117:33 | {...} | literals.rb:117:11:117:19 | Pair | literals.rb:117:11:117:14 | :bar | literals.rb:117:19:117:19 | 2 |
+| literals.rb:117:1:117:33 | {...} | literals.rb:117:22:117:31 | Pair | literals.rb:117:22:117:26 | "baz" | literals.rb:117:31:117:31 | 3 |
+| literals.rb:118:1:118:17 | {...} | literals.rb:118:3:118:8 | Pair | literals.rb:118:3:118:5 | :foo | literals.rb:118:8:118:8 | 7 |
finiteRangeLiterals
-| literals.rb:117:2:117:6 | _ .. _ | literals.rb:117:2:117:2 | 1 | literals.rb:117:5:117:6 | 10 |
-| literals.rb:118:2:118:7 | _ ... _ | literals.rb:118:2:118:2 | 1 | literals.rb:118:6:118:7 | 10 |
-| literals.rb:119:2:119:7 | _ .. _ | literals.rb:119:2:119:2 | 1 | literals.rb:119:7:119:7 | 0 |
-| literals.rb:120:2:120:11 | _ .. _ | literals.rb:120:2:120:6 | call to start | literals.rb:120:9:120:11 | ... + ... |
+| literals.rb:121:2:121:6 | _ .. _ | literals.rb:121:2:121:2 | 1 | literals.rb:121:5:121:6 | 10 |
+| literals.rb:122:2:122:7 | _ ... _ | literals.rb:122:2:122:2 | 1 | literals.rb:122:6:122:7 | 10 |
+| literals.rb:123:2:123:7 | _ .. _ | literals.rb:123:2:123:2 | 1 | literals.rb:123:7:123:7 | 0 |
+| literals.rb:124:2:124:11 | _ .. _ | literals.rb:124:2:124:6 | call to start | literals.rb:124:9:124:11 | ... + ... |
beginlessRangeLiterals
-| literals.rb:122:2:122:4 | _ .. _ | literals.rb:122:4:122:4 | 1 |
+| literals.rb:126:2:126:4 | _ .. _ | literals.rb:126:4:126:4 | 1 |
endlessRangeLiterals
-| literals.rb:121:2:121:4 | _ .. _ | literals.rb:121:2:121:2 | 1 |
-| literals.rb:123:2:123:4 | _ .. _ | literals.rb:123:2:123:2 | 0 |
+| literals.rb:125:2:125:4 | _ .. _ | literals.rb:125:2:125:2 | 1 |
+| literals.rb:127:2:127:4 | _ .. _ | literals.rb:127:2:127:2 | 0 |
inclusiveRangeLiterals
-| literals.rb:117:2:117:6 | _ .. _ |
-| literals.rb:119:2:119:7 | _ .. _ |
-| literals.rb:120:2:120:11 | _ .. _ |
-| literals.rb:121:2:121:4 | _ .. _ |
-| literals.rb:122:2:122:4 | _ .. _ |
-| literals.rb:123:2:123:4 | _ .. _ |
+| literals.rb:121:2:121:6 | _ .. _ |
+| literals.rb:123:2:123:7 | _ .. _ |
+| literals.rb:124:2:124:11 | _ .. _ |
+| literals.rb:125:2:125:4 | _ .. _ |
+| literals.rb:126:2:126:4 | _ .. _ |
+| literals.rb:127:2:127:4 | _ .. _ |
exclusiveRangeLiterals
-| literals.rb:118:2:118:7 | _ ... _ |
+| literals.rb:122:2:122:7 | _ ... _ |
numericLiterals
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
@@ -677,46 +677,46 @@ numericLiterals
| literals.rb:65:21:65:21 | 3 | IntegerLiteral | 3 |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
-| literals.rb:87:10:87:10 | 2 | IntegerLiteral | 2 |
-| literals.rb:87:14:87:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:2:93:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:93:5:93:5 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:8:93:8 | 3 | IntegerLiteral | 3 |
-| literals.rb:94:2:94:2 | 4 | IntegerLiteral | 4 |
-| literals.rb:94:5:94:5 | 5 | IntegerLiteral | 5 |
-| literals.rb:94:8:94:9 | 12 | IntegerLiteral | 12 |
-| literals.rb:94:13:94:13 | 2 | IntegerLiteral | 2 |
-| literals.rb:95:2:95:2 | 7 | IntegerLiteral | 7 |
-| literals.rb:95:6:95:6 | 8 | IntegerLiteral | 8 |
-| literals.rb:95:9:95:9 | 9 | IntegerLiteral | 9 |
-| literals.rb:101:13:101:13 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:15:101:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:108:14:108:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:108:18:108:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:113:8:113:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:113:19:113:19 | 2 | IntegerLiteral | 2 |
-| literals.rb:113:31:113:31 | 3 | IntegerLiteral | 3 |
-| literals.rb:114:8:114:8 | 7 | IntegerLiteral | 7 |
-| literals.rb:117:2:117:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:117:5:117:6 | 10 | IntegerLiteral | 10 |
-| literals.rb:118:2:118:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:118:6:118:7 | 10 | IntegerLiteral | 10 |
-| literals.rb:119:2:119:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:119:7:119:7 | 0 | IntegerLiteral | 0 |
-| literals.rb:120:9:120:9 | 2 | IntegerLiteral | 2 |
-| literals.rb:120:11:120:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
+| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:2:97:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:97:5:97:5 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:8:97:8 | 3 | IntegerLiteral | 3 |
+| literals.rb:98:2:98:2 | 4 | IntegerLiteral | 4 |
+| literals.rb:98:5:98:5 | 5 | IntegerLiteral | 5 |
+| literals.rb:98:8:98:9 | 12 | IntegerLiteral | 12 |
+| literals.rb:98:13:98:13 | 2 | IntegerLiteral | 2 |
+| literals.rb:99:2:99:2 | 7 | IntegerLiteral | 7 |
+| literals.rb:99:6:99:6 | 8 | IntegerLiteral | 8 |
+| literals.rb:99:9:99:9 | 9 | IntegerLiteral | 9 |
+| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
+| literals.rb:117:8:117:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:117:19:117:19 | 2 | IntegerLiteral | 2 |
+| literals.rb:117:31:117:31 | 3 | IntegerLiteral | 3 |
+| literals.rb:118:8:118:8 | 7 | IntegerLiteral | 7 |
| literals.rb:121:2:121:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:122:4:122:4 | 1 | IntegerLiteral | 1 |
-| literals.rb:123:2:123:2 | 0 | IntegerLiteral | 0 |
-| literals.rb:123:6:123:6 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:11:128:11 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:15:128:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:129:13:129:13 | 5 | IntegerLiteral | 5 |
-| literals.rb:129:17:129:17 | 4 | IntegerLiteral | 4 |
-| literals.rb:136:8:136:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:136:12:136:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:10:142:10 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:14:142:14 | 1 | IntegerLiteral | 1 |
+| literals.rb:121:5:121:6 | 10 | IntegerLiteral | 10 |
+| literals.rb:122:2:122:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:122:6:122:7 | 10 | IntegerLiteral | 10 |
+| literals.rb:123:2:123:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:123:7:123:7 | 0 | IntegerLiteral | 0 |
+| literals.rb:124:9:124:9 | 2 | IntegerLiteral | 2 |
+| literals.rb:124:11:124:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:125:2:125:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:126:4:126:4 | 1 | IntegerLiteral | 1 |
+| literals.rb:127:2:127:2 | 0 | IntegerLiteral | 0 |
+| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
+| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
+| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
integerLiterals
| literals.rb:10:1:10:4 | 1234 | IntegerLiteral | 1234 |
| literals.rb:11:1:11:5 | 5_678 | IntegerLiteral | 5_678 |
@@ -740,46 +740,46 @@ integerLiterals
| literals.rb:65:21:65:21 | 3 | IntegerLiteral | 3 |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
-| literals.rb:87:10:87:10 | 2 | IntegerLiteral | 2 |
-| literals.rb:87:14:87:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:2:93:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:93:5:93:5 | 2 | IntegerLiteral | 2 |
-| literals.rb:93:8:93:8 | 3 | IntegerLiteral | 3 |
-| literals.rb:94:2:94:2 | 4 | IntegerLiteral | 4 |
-| literals.rb:94:5:94:5 | 5 | IntegerLiteral | 5 |
-| literals.rb:94:8:94:9 | 12 | IntegerLiteral | 12 |
-| literals.rb:94:13:94:13 | 2 | IntegerLiteral | 2 |
-| literals.rb:95:2:95:2 | 7 | IntegerLiteral | 7 |
-| literals.rb:95:6:95:6 | 8 | IntegerLiteral | 8 |
-| literals.rb:95:9:95:9 | 9 | IntegerLiteral | 9 |
-| literals.rb:101:13:101:13 | 1 | IntegerLiteral | 1 |
-| literals.rb:101:15:101:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:108:14:108:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:108:18:108:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:113:8:113:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:113:19:113:19 | 2 | IntegerLiteral | 2 |
-| literals.rb:113:31:113:31 | 3 | IntegerLiteral | 3 |
-| literals.rb:114:8:114:8 | 7 | IntegerLiteral | 7 |
-| literals.rb:117:2:117:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:117:5:117:6 | 10 | IntegerLiteral | 10 |
-| literals.rb:118:2:118:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:118:6:118:7 | 10 | IntegerLiteral | 10 |
-| literals.rb:119:2:119:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:119:7:119:7 | 0 | IntegerLiteral | 0 |
-| literals.rb:120:9:120:9 | 2 | IntegerLiteral | 2 |
-| literals.rb:120:11:120:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
+| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:2:97:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:97:5:97:5 | 2 | IntegerLiteral | 2 |
+| literals.rb:97:8:97:8 | 3 | IntegerLiteral | 3 |
+| literals.rb:98:2:98:2 | 4 | IntegerLiteral | 4 |
+| literals.rb:98:5:98:5 | 5 | IntegerLiteral | 5 |
+| literals.rb:98:8:98:9 | 12 | IntegerLiteral | 12 |
+| literals.rb:98:13:98:13 | 2 | IntegerLiteral | 2 |
+| literals.rb:99:2:99:2 | 7 | IntegerLiteral | 7 |
+| literals.rb:99:6:99:6 | 8 | IntegerLiteral | 8 |
+| literals.rb:99:9:99:9 | 9 | IntegerLiteral | 9 |
+| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
+| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
+| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
+| literals.rb:117:8:117:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:117:19:117:19 | 2 | IntegerLiteral | 2 |
+| literals.rb:117:31:117:31 | 3 | IntegerLiteral | 3 |
+| literals.rb:118:8:118:8 | 7 | IntegerLiteral | 7 |
| literals.rb:121:2:121:2 | 1 | IntegerLiteral | 1 |
-| literals.rb:122:4:122:4 | 1 | IntegerLiteral | 1 |
-| literals.rb:123:2:123:2 | 0 | IntegerLiteral | 0 |
-| literals.rb:123:6:123:6 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:11:128:11 | 1 | IntegerLiteral | 1 |
-| literals.rb:128:15:128:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:129:13:129:13 | 5 | IntegerLiteral | 5 |
-| literals.rb:129:17:129:17 | 4 | IntegerLiteral | 4 |
-| literals.rb:136:8:136:8 | 1 | IntegerLiteral | 1 |
-| literals.rb:136:12:136:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:10:142:10 | 1 | IntegerLiteral | 1 |
-| literals.rb:142:14:142:14 | 1 | IntegerLiteral | 1 |
+| literals.rb:121:5:121:6 | 10 | IntegerLiteral | 10 |
+| literals.rb:122:2:122:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:122:6:122:7 | 10 | IntegerLiteral | 10 |
+| literals.rb:123:2:123:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:123:7:123:7 | 0 | IntegerLiteral | 0 |
+| literals.rb:124:9:124:9 | 2 | IntegerLiteral | 2 |
+| literals.rb:124:11:124:11 | 3 | IntegerLiteral | 3 |
+| literals.rb:125:2:125:2 | 1 | IntegerLiteral | 1 |
+| literals.rb:126:4:126:4 | 1 | IntegerLiteral | 1 |
+| literals.rb:127:2:127:2 | 0 | IntegerLiteral | 0 |
+| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
+| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
+| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
+| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
+| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
+| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
+| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
floatLiterals
| literals.rb:30:1:30:5 | 12.34 | FloatLiteral | 12.34 |
| literals.rb:31:1:31:7 | 1234e-2 | FloatLiteral | 1234e-2 |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.rb b/ruby/ql/test/library-tests/ast/literals/literals.rb
index a264a6d0003..1c1304d9eef 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.rb
+++ b/ruby/ql/test/library-tests/ast/literals/literals.rb
@@ -65,6 +65,10 @@ TRUE
"foo #{ "bar #{ 2 + 3 } baz" } qux" # interpolation containing string containing interpolation
"foo #{ blah(); 1+9 }" # multiple statements in interpolation
+
+
+
+
# characters
?x
?\n
From 32c93e70e2612bfbc76b11f17b59d58709342985 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Tue, 7 Dec 2021 17:55:46 +1300
Subject: [PATCH 003/196] Include simple interpolations in getValueText
When calculating `StringlikeLiteral.getValueText`, include results from
interpolations where we can determine their string value. For example:
b = "b" # local variable
D = "d" # constant
"a#{b}c" # getValueText() = "abc"
"a#{b}c{D}" # getValueText() = "abcd"
/#a#{b}c{D}/ # getValueText() = "abcd"
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 7 +-
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 39 ++-
ruby/ql/test/library-tests/ast/Ast.expected | 98 ++++++-
.../library-tests/ast/AstDesugar.expected | 20 ++
.../test/library-tests/ast/ValueText.expected | 51 +++-
.../ast/literals/literals.expected | 276 ++++++++++++------
.../library-tests/ast/literals/literals.rb | 30 +-
.../test/library-tests/ast/misc/misc.expected | 4 +-
.../test/library-tests/regexp/parse.expected | 11 +
ruby/ql/test/library-tests/regexp/regexp.rb | 6 +-
10 files changed, 411 insertions(+), 131 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 1be956c9a33..181c23fbf6e 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -3,6 +3,7 @@ private import codeql.ruby.security.performance.RegExpTreeView as RETV
private import internal.AST
private import internal.Scope
private import internal.TreeSitter
+private import codeql.ruby.controlflow.CfgNodes
/**
* A literal.
@@ -411,14 +412,14 @@ class StringlikeLiteral extends Literal, TStringlikeLiteral {
}
override string getValueText() {
- // 0 components should result in the empty string
- // if there are any interpolations, there should be no result
- // otherwise, concatenate all the components
forall(StringComponent c | c = this.getComponent(_) |
not c instanceof StringInterpolationComponent
) and
result =
concat(StringComponent c, int i | c = this.getComponent(i) | c.getValueText() order by i)
+ or
+ exists(this.getComponent(_)) and
+ result = this.getAControlFlowNode().(ExprNodes::StringlikeLiteralCfgNode).getValueText()
}
override string toString() {
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 5ea3038c3a4..369a79209ab 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -128,6 +128,8 @@ class ReturningCfgNode extends AstCfgNode {
/** A control-flow node that wraps a `StringComponent` AST expression. */
class StringComponentCfgNode extends AstCfgNode {
StringComponentCfgNode() { this.getNode() instanceof StringComponent }
+
+ string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
private Expr desugar(Expr n) {
@@ -463,8 +465,13 @@ module ExprNodes {
}
/** A control-flow node that wraps a `StringInterpolationComponent` AST expression. */
- class StringInterpolationComponentCfgNode extends StmtSequenceCfgNode {
+ class StringInterpolationComponentCfgNode extends StringComponentCfgNode, StmtSequenceCfgNode {
StringInterpolationComponentCfgNode() { this.getNode() instanceof StringInterpolationComponent }
+
+ // If last statement in the interpolation is a constant or local variable read,
+ // we attempt to look up its string value.
+ // If there's a result, we return that as the string value of the interpolation.
+ final override string getValueText() { result = this.getLastStmt().getValueText() }
}
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
@@ -477,8 +484,36 @@ module ExprNodes {
final override StringlikeLiteral getExpr() { result = super.getExpr() }
+ /** Gets the `n`th component of this `StringlikeLiteral` */
+ StringComponentCfgNode getComponent(int n) { result.getNode() = e.getComponent(n) }
+
/** Gets a component of this `StringlikeLiteral` */
- StringComponentCfgNode getAComponent() { e.hasCfgChild(e.getComponent(_), this, result) }
+ StringComponentCfgNode getAComponent() { result = this.getComponent(_) }
+
+ // 0 components results in the empty string
+ // if all interpolations have a known string value, we will get a result
+ language[monotonicAggregates]
+ override string getValueText() {
+ result = e.getValueText()
+ or
+ result =
+ concat(StringComponent c, int i |
+ c = e.getComponent(i)
+ |
+ getComponentValueText(c) order by i
+ )
+ }
+
+ /**
+ * Get the `ValueText()` of a `StringComponent`.
+ * If the component has a CFG node, defer to that (in order to resolve variables in interpolations).
+ * Otherwise, defer to the AST node.
+ */
+ private string getComponentValueText(StringComponent c) {
+ exists(StringComponentCfgNode n | n.getNode() = c | result = n.getValueText())
+ or
+ not exists(StringComponentCfgNode n | n.getNode() = c) and result = c.getValueText()
+ }
}
/** A control-flow node that wraps a `StringLiteral` AST expression. */
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index e3630cf4ac2..57c9704bc40 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -1515,6 +1515,22 @@ literals/literals.rb:
# 66| getStmt: [AddExpr] ... + ...
# 66| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 66| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 9
+# 67| getStmt: [AssignExpr] ... = ...
+# 67| getAnOperand/getLeftOperand: [LocalVariableAccess] bar
+# 67| getAnOperand/getRightOperand: [StringLiteral] "bar"
+# 67| getComponent: [StringTextComponent] bar
+# 68| getStmt: [AssignExpr] ... = ...
+# 68| getAnOperand/getLeftOperand: [ConstantAssignment] BAR
+# 68| getAnOperand/getRightOperand: [StringLiteral] "bar"
+# 68| getComponent: [StringTextComponent] bar
+# 69| getStmt: [StringLiteral] "foo #{...}"
+# 69| getComponent: [StringTextComponent] foo
+# 69| getComponent: [StringInterpolationComponent] #{...}
+# 69| getStmt: [LocalVariableAccess] bar
+# 70| getStmt: [StringLiteral] "foo #{...}"
+# 70| getComponent: [StringTextComponent] foo
+# 70| getComponent: [StringInterpolationComponent] #{...}
+# 70| getStmt: [ConstantReadAccess] BAR
# 73| getStmt: [CharacterLiteral] ?x
# 74| getStmt: [CharacterLiteral] ?\n
# 75| getStmt: [CharacterLiteral] ?\s
@@ -1539,14 +1555,20 @@ literals/literals.rb:
# 89| getComponent: [StringTextComponent] wibble
# 90| getStmt: [SymbolLiteral] :"wibble wobble"
# 90| getComponent: [StringTextComponent] wibble wobble
-# 91| getStmt: [SymbolLiteral] :"foo_#{...}"
+# 91| getStmt: [SymbolLiteral] :"foo_#{...}_#{...}_#{...}"
# 91| getComponent: [StringTextComponent] foo_
# 91| getComponent: [StringInterpolationComponent] #{...}
# 91| getStmt: [AddExpr] ... + ...
# 91| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
# 91| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 2
-# 92| getStmt: [SymbolLiteral] :"foo_#{ 1 + 1 }"
-# 92| getComponent: [StringTextComponent] foo_#{ 1 + 1 }
+# 91| getComponent: [StringTextComponent] _
+# 91| getComponent: [StringInterpolationComponent] #{...}
+# 91| getStmt: [LocalVariableAccess] bar
+# 91| getComponent: [StringTextComponent] _
+# 91| getComponent: [StringInterpolationComponent] #{...}
+# 91| getStmt: [ConstantReadAccess] BAR
+# 92| getStmt: [SymbolLiteral] :"foo_#{ 2 + 2}_#{bar}_#{BAR}"
+# 92| getComponent: [StringTextComponent] foo_#{ 2 + 2}_#{bar}_#{BAR}
# 93| getStmt: [SymbolLiteral] :"foo_#{ 3 - 2 }"
# 93| getComponent: [StringTextComponent] foo_#{ 3 - 2 }
# 96| getStmt: [ArrayLiteral] [...]
@@ -1589,6 +1611,12 @@ literals/literals.rb:
# 105| getStmt: [AddExpr] ... + ...
# 105| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 105| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 105| getElement: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [LocalVariableAccess] bar
+# 105| getElement: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [ConstantReadAccess] BAR
# 105| getElement: [StringLiteral] "baz"
# 105| getComponent: [StringTextComponent] baz
# 106| getStmt: [ArrayLiteral] %w(...)
@@ -1596,6 +1624,10 @@ literals/literals.rb:
# 106| getComponent: [StringTextComponent] foo
# 106| getElement: [StringLiteral] "bar#{1+1}"
# 106| getComponent: [StringTextComponent] bar#{1+1}
+# 106| getElement: [StringLiteral] "#{bar}"
+# 106| getComponent: [StringTextComponent] #{bar}
+# 106| getElement: [StringLiteral] "#{BAR}"
+# 106| getComponent: [StringTextComponent] #{BAR}
# 106| getElement: [StringLiteral] "baz"
# 106| getComponent: [StringTextComponent] baz
# 109| getStmt: [ArrayLiteral] %i(...)
@@ -1622,6 +1654,12 @@ literals/literals.rb:
# 112| getStmt: [AddExpr] ... + ...
# 112| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 112| getElement: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [LocalVariableAccess] bar
+# 112| getElement: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [ConstantReadAccess] BAR
# 112| getElement: [SymbolLiteral] :"baz"
# 112| getComponent: [StringTextComponent] baz
# 113| getStmt: [ArrayLiteral] %i(...)
@@ -1637,6 +1675,10 @@ literals/literals.rb:
# 113| getComponent: [StringTextComponent] 4
# 113| getElement: [SymbolLiteral] :"}"
# 113| getComponent: [StringTextComponent] }
+# 113| getElement: [SymbolLiteral] :"#{bar}"
+# 113| getComponent: [StringTextComponent] #{bar}
+# 113| getElement: [SymbolLiteral] :"#{BAR}"
+# 113| getComponent: [StringTextComponent] #{BAR}
# 113| getElement: [SymbolLiteral] :"baz"
# 113| getComponent: [StringTextComponent] baz
# 116| getStmt: [HashLiteral] {...}
@@ -1656,7 +1698,7 @@ literals/literals.rb:
# 118| getKey: [SymbolLiteral] :foo
# 118| getValue: [IntegerLiteral] 7
# 118| getElement: [HashSplatExpr] ** ...
-# 118| getAnOperand/getOperand/getReceiver: [MethodCall] call to bar
+# 118| getAnOperand/getOperand/getReceiver: [MethodCall] call to baz
# 118| getReceiver: [Self, SelfVariableAccess] self
# 121| getStmt: [ParenthesizedExpr] ( ... )
# 121| getStmt: [RangeLiteral] _ .. _
@@ -1692,12 +1734,18 @@ literals/literals.rb:
# 130| getComponent: [StringTextComponent] ls -l
# 131| getStmt: [SubshellLiteral] `ls -l`
# 131| getComponent: [StringTextComponent] ls -l
-# 132| getStmt: [SubshellLiteral] `du -d #{...}`
+# 132| getStmt: [SubshellLiteral] `du -d #{...} #{...} #{...}`
# 132| getComponent: [StringTextComponent] du -d
# 132| getComponent: [StringInterpolationComponent] #{...}
# 132| getStmt: [AddExpr] ... + ...
# 132| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 132| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 132| getComponent: [StringTextComponent]
+# 132| getComponent: [StringInterpolationComponent] #{...}
+# 132| getStmt: [LocalVariableAccess] bar
+# 132| getComponent: [StringTextComponent]
+# 132| getComponent: [StringInterpolationComponent] #{...}
+# 132| getStmt: [ConstantReadAccess] BAR
# 133| getStmt: [SubshellLiteral] `du -d #{...}`
# 133| getComponent: [StringTextComponent] du -d
# 133| getComponent: [StringInterpolationComponent] #{...}
@@ -1732,13 +1780,31 @@ literals/literals.rb:
# 139| getComponent: [StringEscapeSequenceComponent] \s
# 139| getComponent: [StringTextComponent] bar
# 139| getComponent: [StringEscapeSequenceComponent] \S
-# 140| getStmt: [RegExpLiteral] /foo#{...}bar/
+# 140| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
+# 140| getParsed: [RegExpSequence] foo2barbarbar
+# 140| 0: [RegExpConstant, RegExpNormalChar] f
+# 140| 1: [RegExpConstant, RegExpNormalChar] o
+# 140| 2: [RegExpConstant, RegExpNormalChar] o
+# 140| 3: [RegExpConstant, RegExpNormalChar] 2
+# 140| 4: [RegExpConstant, RegExpNormalChar] b
+# 140| 5: [RegExpConstant, RegExpNormalChar] a
+# 140| 6: [RegExpConstant, RegExpNormalChar] r
+# 140| 7: [RegExpConstant, RegExpNormalChar] b
+# 140| 8: [RegExpConstant, RegExpNormalChar] a
+# 140| 9: [RegExpConstant, RegExpNormalChar] r
+# 140| 10: [RegExpConstant, RegExpNormalChar] b
+# 140| 11: [RegExpConstant, RegExpNormalChar] a
+# 140| 12: [RegExpConstant, RegExpNormalChar] r
# 140| getComponent: [StringTextComponent] foo
# 140| getComponent: [StringInterpolationComponent] #{...}
# 140| getStmt: [AddExpr] ... + ...
# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 140| getComponent: [StringTextComponent] bar
+# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getStmt: [LocalVariableAccess] bar
+# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getStmt: [ConstantReadAccess] BAR
# 141| getStmt: [RegExpLiteral] /foo/
# 141| getParsed: [RegExpSequence] foo
# 141| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1773,13 +1839,31 @@ literals/literals.rb:
# 145| getComponent: [StringEscapeSequenceComponent] \s
# 145| getComponent: [StringTextComponent] bar
# 145| getComponent: [StringEscapeSequenceComponent] \S
-# 146| getStmt: [RegExpLiteral] /foo#{...}bar/
+# 146| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
+# 146| getParsed: [RegExpSequence] foo2barbarbar
+# 146| 0: [RegExpConstant, RegExpNormalChar] f
+# 146| 1: [RegExpConstant, RegExpNormalChar] o
+# 146| 2: [RegExpConstant, RegExpNormalChar] o
+# 146| 3: [RegExpConstant, RegExpNormalChar] 2
+# 146| 4: [RegExpConstant, RegExpNormalChar] b
+# 146| 5: [RegExpConstant, RegExpNormalChar] a
+# 146| 6: [RegExpConstant, RegExpNormalChar] r
+# 146| 7: [RegExpConstant, RegExpNormalChar] b
+# 146| 8: [RegExpConstant, RegExpNormalChar] a
+# 146| 9: [RegExpConstant, RegExpNormalChar] r
+# 146| 10: [RegExpConstant, RegExpNormalChar] b
+# 146| 11: [RegExpConstant, RegExpNormalChar] a
+# 146| 12: [RegExpConstant, RegExpNormalChar] r
# 146| getComponent: [StringTextComponent] foo
# 146| getComponent: [StringInterpolationComponent] #{...}
# 146| getStmt: [AddExpr] ... + ...
# 146| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 146| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
# 146| getComponent: [StringTextComponent] bar
+# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getStmt: [LocalVariableAccess] bar
+# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getStmt: [ConstantReadAccess] BAR
# 147| getStmt: [RegExpLiteral] /foo/
# 147| getParsed: [RegExpSequence] foo
# 147| 0: [RegExpConstant, RegExpNormalChar] f
diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected
index 40548cba53c..6acafd116c5 100644
--- a/ruby/ql/test/library-tests/ast/AstDesugar.expected
+++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected
@@ -350,6 +350,12 @@ literals/literals.rb:
# 105| getStmt: [AddExpr] ... + ...
# 105| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 105| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
+# 105| getArgument: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [LocalVariableAccess] bar
+# 105| getArgument: [StringLiteral] "#{...}"
+# 105| getComponent: [StringInterpolationComponent] #{...}
+# 105| getStmt: [ConstantReadAccess] BAR
# 105| getArgument: [StringLiteral] "baz"
# 105| getComponent: [StringTextComponent] baz
# 106| [ArrayLiteral] %w(...)
@@ -359,6 +365,10 @@ literals/literals.rb:
# 106| getComponent: [StringTextComponent] foo
# 106| getArgument: [StringLiteral] "bar#{1+1}"
# 106| getComponent: [StringTextComponent] bar#{1+1}
+# 106| getArgument: [StringLiteral] "#{bar}"
+# 106| getComponent: [StringTextComponent] #{bar}
+# 106| getArgument: [StringLiteral] "#{BAR}"
+# 106| getComponent: [StringTextComponent] #{BAR}
# 106| getArgument: [StringLiteral] "baz"
# 106| getComponent: [StringTextComponent] baz
# 109| [ArrayLiteral] %i(...)
@@ -393,6 +403,12 @@ literals/literals.rb:
# 112| getStmt: [AddExpr] ... + ...
# 112| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 2
# 112| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 4
+# 112| getArgument: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [LocalVariableAccess] bar
+# 112| getArgument: [SymbolLiteral] :"#{...}"
+# 112| getComponent: [StringInterpolationComponent] #{...}
+# 112| getStmt: [ConstantReadAccess] BAR
# 112| getArgument: [SymbolLiteral] :"baz"
# 112| getComponent: [StringTextComponent] baz
# 113| [ArrayLiteral] %i(...)
@@ -410,6 +426,10 @@ literals/literals.rb:
# 113| getComponent: [StringTextComponent] 4
# 113| getArgument: [SymbolLiteral] :"}"
# 113| getComponent: [StringTextComponent] }
+# 113| getArgument: [SymbolLiteral] :"#{bar}"
+# 113| getComponent: [StringTextComponent] #{bar}
+# 113| getArgument: [SymbolLiteral] :"#{BAR}"
+# 113| getComponent: [StringTextComponent] #{BAR}
# 113| getArgument: [SymbolLiteral] :"baz"
# 113| getComponent: [StringTextComponent] baz
control/loops.rb:
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index aae39cebac9..e2a318c333c 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -389,9 +389,11 @@
| literals/literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals/literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals/literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
+| literals/literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
| literals/literals.rb:58:13:58:13 | 2 | 2 |
| literals/literals.rb:58:13:58:17 | ... + ... | 4 |
| literals/literals.rb:58:17:58:17 | 2 | 2 |
+| literals/literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals/literals.rb:59:15:59:15 | 3 | 3 |
| literals/literals.rb:59:15:59:19 | ... + ... | 7 |
| literals/literals.rb:59:19:59:19 | 4 | 4 |
@@ -404,16 +406,26 @@
| literals/literals.rb:63:9:63:13 | "bar" | bar |
| literals/literals.rb:63:15:63:19 | "baz" | baz |
| literals/literals.rb:64:1:64:5 | "foo" | foo |
+| literals/literals.rb:64:7:64:21 | "bar#{...}" | bar1 |
| literals/literals.rb:64:14:64:14 | 1 | 1 |
| literals/literals.rb:64:14:64:18 | ... * ... | 1 |
| literals/literals.rb:64:18:64:18 | 1 | 1 |
| literals/literals.rb:64:23:64:27 | "baz" | baz |
+| literals/literals.rb:65:1:65:35 | "foo #{...} qux" | foo bar 5 baz qux |
+| literals/literals.rb:65:9:65:28 | "bar #{...} baz" | bar 5 baz |
| literals/literals.rb:65:17:65:17 | 2 | 2 |
| literals/literals.rb:65:17:65:21 | ... + ... | 5 |
| literals/literals.rb:65:21:65:21 | 3 | 3 |
+| literals/literals.rb:66:1:66:22 | "foo #{...}" | foo 10 |
| literals/literals.rb:66:17:66:17 | 1 | 1 |
| literals/literals.rb:66:17:66:19 | ... + ... | 10 |
| literals/literals.rb:66:19:66:19 | 9 | 9 |
+| literals/literals.rb:67:7:67:11 | "bar" | bar |
+| literals/literals.rb:68:7:68:11 | "bar" | bar |
+| literals/literals.rb:69:1:69:14 | "foo #{...}" | foo bar |
+| literals/literals.rb:69:9:69:11 | bar | bar |
+| literals/literals.rb:70:1:70:14 | "foo #{...}" | foo bar |
+| literals/literals.rb:70:9:70:11 | BAR | bar |
| literals/literals.rb:73:1:73:2 | ?x | ?x |
| literals/literals.rb:74:1:74:3 | ?\\n | ?\\n |
| literals/literals.rb:75:1:75:3 | ?\\s | ?\\s |
@@ -431,10 +443,13 @@
| literals/literals.rb:88:8:88:12 | "bar" | bar |
| literals/literals.rb:89:1:89:10 | :"wibble" | wibble |
| literals/literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
+| literals/literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | foo_4_bar_bar |
| literals/literals.rb:91:10:91:10 | 2 | 2 |
| literals/literals.rb:91:10:91:14 | ... + ... | 4 |
| literals/literals.rb:91:14:91:14 | 2 | 2 |
-| literals/literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals/literals.rb:91:19:91:21 | bar | bar |
+| literals/literals.rb:91:26:91:28 | BAR | bar |
+| literals/literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals/literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
| literals/literals.rb:97:2:97:2 | 1 | 1 |
| literals/literals.rb:97:5:97:5 | 2 | 2 |
@@ -454,13 +469,20 @@
| literals/literals.rb:104:8:104:10 | "bar" | bar |
| literals/literals.rb:104:12:104:14 | "baz" | baz |
| literals/literals.rb:105:4:105:6 | "foo" | foo |
+| literals/literals.rb:105:8:105:16 | "bar#{...}" | bar2 |
| literals/literals.rb:105:13:105:13 | 1 | 1 |
| literals/literals.rb:105:13:105:15 | ... + ... | 2 |
| literals/literals.rb:105:15:105:15 | 1 | 1 |
-| literals/literals.rb:105:18:105:20 | "baz" | baz |
+| literals/literals.rb:105:18:105:23 | "#{...}" | bar |
+| literals/literals.rb:105:20:105:22 | bar | bar |
+| literals/literals.rb:105:25:105:30 | "#{...}" | bar |
+| literals/literals.rb:105:27:105:29 | BAR | bar |
+| literals/literals.rb:105:32:105:34 | "baz" | baz |
| literals/literals.rb:106:4:106:6 | "foo" | foo |
| literals/literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
-| literals/literals.rb:106:18:106:20 | "baz" | baz |
+| literals/literals.rb:106:18:106:23 | "#{bar}" | #{bar} |
+| literals/literals.rb:106:25:106:30 | "#{BAR}" | #{BAR} |
+| literals/literals.rb:106:32:106:34 | "baz" | baz |
| literals/literals.rb:110:4:110:6 | :"foo" | foo |
| literals/literals.rb:110:8:110:10 | :"bar" | bar |
| literals/literals.rb:110:12:110:14 | :"baz" | baz |
@@ -468,17 +490,24 @@
| literals/literals.rb:111:8:111:10 | :"bar" | bar |
| literals/literals.rb:111:12:111:14 | :"baz" | baz |
| literals/literals.rb:112:4:112:6 | :"foo" | foo |
+| literals/literals.rb:112:8:112:20 | :"bar#{...}" | bar6 |
| literals/literals.rb:112:14:112:14 | 2 | 2 |
| literals/literals.rb:112:14:112:18 | ... + ... | 6 |
| literals/literals.rb:112:18:112:18 | 4 | 4 |
-| literals/literals.rb:112:22:112:24 | :"baz" | baz |
+| literals/literals.rb:112:22:112:27 | :"#{...}" | bar |
+| literals/literals.rb:112:24:112:26 | bar | bar |
+| literals/literals.rb:112:29:112:34 | :"#{...}" | bar |
+| literals/literals.rb:112:31:112:33 | BAR | bar |
+| literals/literals.rb:112:36:112:38 | :"baz" | baz |
| literals/literals.rb:113:4:113:6 | :"foo" | foo |
| literals/literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
| literals/literals.rb:113:14:113:14 | :"2" | 2 |
| literals/literals.rb:113:16:113:16 | :"+" | + |
| literals/literals.rb:113:18:113:18 | :"4" | 4 |
| literals/literals.rb:113:20:113:20 | :"}" | } |
-| literals/literals.rb:113:22:113:24 | :"baz" | baz |
+| literals/literals.rb:113:22:113:27 | :"#{bar}" | #{bar} |
+| literals/literals.rb:113:29:113:34 | :"#{BAR}" | #{BAR} |
+| literals/literals.rb:113:36:113:38 | :"baz" | baz |
| literals/literals.rb:117:3:117:5 | :foo | foo |
| literals/literals.rb:117:8:117:8 | 1 | 1 |
| literals/literals.rb:117:11:117:14 | :bar | bar |
@@ -502,9 +531,13 @@
| literals/literals.rb:127:6:127:6 | 1 | 1 |
| literals/literals.rb:130:1:130:7 | `ls -l` | ls -l |
| literals/literals.rb:131:1:131:9 | `ls -l` | ls -l |
+| literals/literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | du -d 2 bar bar |
| literals/literals.rb:132:11:132:11 | 1 | 1 |
| literals/literals.rb:132:11:132:15 | ... + ... | 2 |
| literals/literals.rb:132:15:132:15 | 1 | 1 |
+| literals/literals.rb:132:21:132:23 | bar | bar |
+| literals/literals.rb:132:28:132:30 | BAR | bar |
+| literals/literals.rb:133:1:133:20 | `du -d #{...}` | du -d 1 |
| literals/literals.rb:133:13:133:13 | 5 | 5 |
| literals/literals.rb:133:13:133:17 | ... - ... | 1 |
| literals/literals.rb:133:17:133:17 | 4 | 4 |
@@ -512,17 +545,23 @@
| literals/literals.rb:137:1:137:5 | /foo/ | foo |
| literals/literals.rb:138:1:138:6 | /foo/ | foo |
| literals/literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals/literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals/literals.rb:140:8:140:8 | 1 | 1 |
| literals/literals.rb:140:8:140:12 | ... + ... | 2 |
| literals/literals.rb:140:12:140:12 | 1 | 1 |
+| literals/literals.rb:140:20:140:22 | bar | bar |
+| literals/literals.rb:140:26:140:28 | BAR | bar |
| literals/literals.rb:141:1:141:8 | /foo/ | foo |
| literals/literals.rb:142:1:142:4 | // | |
| literals/literals.rb:143:1:143:7 | /foo/ | foo |
| literals/literals.rb:144:1:144:8 | /foo/ | foo |
| literals/literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
+| literals/literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals/literals.rb:146:10:146:10 | 1 | 1 |
| literals/literals.rb:146:10:146:14 | ... + ... | 2 |
| literals/literals.rb:146:14:146:14 | 1 | 1 |
+| literals/literals.rb:146:22:146:24 | bar | bar |
+| literals/literals.rb:146:28:146:30 | BAR | bar |
| literals/literals.rb:147:1:147:10 | /foo/ | foo |
| literals/literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals/literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
@@ -538,6 +577,7 @@
| misc/misc.rb:3:18:3:21 | foo= | foo= |
| misc/misc.rb:3:24:3:25 | [] | [] |
| misc/misc.rb:3:28:3:30 | []= | []= |
+| misc/misc.rb:4:7:4:19 | :"foo_#{...}" | foo_bar |
| misc/misc.rb:4:15:4:17 | bar | bar |
| misc/misc.rb:5:7:5:9 | nil | nil |
| misc/misc.rb:5:12:5:15 | true | true |
@@ -550,6 +590,7 @@
| misc/misc.rb:8:12:8:14 | []= | []= |
| misc/misc.rb:9:7:9:11 | super | super |
| misc/misc.rb:9:13:9:16 | self | self |
+| misc/misc.rb:10:7:10:17 | :"\\n#{...}" | \\nbar |
| misc/misc.rb:10:13:10:15 | bar | bar |
| misc/misc.rb:10:19:10:24 | :"foo" | foo |
| modules/classes.rb:11:28:11:31 | :baz | baz |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.expected b/ruby/ql/test/library-tests/ast/literals/literals.expected
index cfcfb81abb1..a84d52fe2b0 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.expected
+++ b/ruby/ql/test/library-tests/ast/literals/literals.expected
@@ -35,10 +35,10 @@ allLiterals
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | StringLiteral | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | StringLiteral | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | StringLiteral | foo\\ bar |
-| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | StringLiteral | |
+| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | StringLiteral | 2 + 2 = 4 |
| literals.rb:58:13:58:13 | 2 | IntegerLiteral | 2 |
| literals.rb:58:17:58:17 | 2 | IntegerLiteral | 2 |
-| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | StringLiteral | |
+| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | StringLiteral | 3 + 4 = 7 |
| literals.rb:59:15:59:15 | 3 | IntegerLiteral | 3 |
| literals.rb:59:19:59:19 | 4 | IntegerLiteral | 4 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | StringLiteral | 2 + 2 = #{ 2 + 2 } |
@@ -50,17 +50,21 @@ allLiterals
| literals.rb:63:9:63:13 | "bar" | StringLiteral | bar |
| literals.rb:63:15:63:19 | "baz" | StringLiteral | baz |
| literals.rb:64:1:64:5 | "foo" | StringLiteral | foo |
-| literals.rb:64:7:64:21 | "bar#{...}" | StringLiteral | |
+| literals.rb:64:7:64:21 | "bar#{...}" | StringLiteral | bar1 |
| literals.rb:64:14:64:14 | 1 | IntegerLiteral | 1 |
| literals.rb:64:18:64:18 | 1 | IntegerLiteral | 1 |
| literals.rb:64:23:64:27 | "baz" | StringLiteral | baz |
-| literals.rb:65:1:65:35 | "foo #{...} qux" | StringLiteral | |
-| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | |
+| literals.rb:65:1:65:35 | "foo #{...} qux" | StringLiteral | foo bar 5 baz qux |
+| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | bar 5 baz |
| literals.rb:65:17:65:17 | 2 | IntegerLiteral | 2 |
| literals.rb:65:21:65:21 | 3 | IntegerLiteral | 3 |
-| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | |
+| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | foo 10 |
| literals.rb:66:17:66:17 | 1 | IntegerLiteral | 1 |
| literals.rb:66:19:66:19 | 9 | IntegerLiteral | 9 |
+| literals.rb:67:7:67:11 | "bar" | StringLiteral | bar |
+| literals.rb:68:7:68:11 | "bar" | StringLiteral | bar |
+| literals.rb:69:1:69:14 | "foo #{...}" | StringLiteral | foo bar |
+| literals.rb:70:1:70:14 | "foo #{...}" | StringLiteral | foo bar |
| literals.rb:73:1:73:2 | ?x | CharacterLiteral | ?x |
| literals.rb:74:1:74:3 | ?\\n | CharacterLiteral | ?\\n |
| literals.rb:75:1:75:3 | ?\\s | CharacterLiteral | ?\\s |
@@ -79,10 +83,10 @@ allLiterals
| literals.rb:88:8:88:12 | "bar" | StringLiteral | bar |
| literals.rb:89:1:89:10 | :"wibble" | SymbolLiteral | wibble |
| literals.rb:90:1:90:17 | :"wibble wobble" | SymbolLiteral | wibble wobble |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | foo_4_bar_bar |
| literals.rb:91:10:91:10 | 2 | IntegerLiteral | 2 |
| literals.rb:91:14:91:14 | 2 | IntegerLiteral | 2 |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | foo_#{ 1 + 1 } |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | SymbolLiteral | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | foo_#{ 3 - 2 } |
| literals.rb:96:1:96:2 | [...] | ArrayLiteral | |
| literals.rb:97:1:97:9 | [...] | ArrayLiteral | |
@@ -108,16 +112,20 @@ allLiterals
| literals.rb:104:4:104:6 | "foo" | StringLiteral | foo |
| literals.rb:104:8:104:10 | "bar" | StringLiteral | bar |
| literals.rb:104:12:104:14 | "baz" | StringLiteral | baz |
-| literals.rb:105:1:105:21 | %w(...) | ArrayLiteral | |
+| literals.rb:105:1:105:35 | %w(...) | ArrayLiteral | |
| literals.rb:105:4:105:6 | "foo" | StringLiteral | foo |
-| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | |
+| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | bar2 |
| literals.rb:105:13:105:13 | 1 | IntegerLiteral | 1 |
| literals.rb:105:15:105:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:105:18:105:20 | "baz" | StringLiteral | baz |
-| literals.rb:106:1:106:21 | %w(...) | ArrayLiteral | |
+| literals.rb:105:18:105:23 | "#{...}" | StringLiteral | bar |
+| literals.rb:105:25:105:30 | "#{...}" | StringLiteral | bar |
+| literals.rb:105:32:105:34 | "baz" | StringLiteral | baz |
+| literals.rb:106:1:106:35 | %w(...) | ArrayLiteral | |
| literals.rb:106:4:106:6 | "foo" | StringLiteral | foo |
| literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral | bar#{1+1} |
-| literals.rb:106:18:106:20 | "baz" | StringLiteral | baz |
+| literals.rb:106:18:106:23 | "#{bar}" | StringLiteral | #{bar} |
+| literals.rb:106:25:106:30 | "#{BAR}" | StringLiteral | #{BAR} |
+| literals.rb:106:32:106:34 | "baz" | StringLiteral | baz |
| literals.rb:109:1:109:4 | %i(...) | ArrayLiteral | |
| literals.rb:110:1:110:15 | %i(...) | ArrayLiteral | |
| literals.rb:110:4:110:6 | :"foo" | SymbolLiteral | foo |
@@ -127,20 +135,24 @@ allLiterals
| literals.rb:111:4:111:6 | :"foo" | SymbolLiteral | foo |
| literals.rb:111:8:111:10 | :"bar" | SymbolLiteral | bar |
| literals.rb:111:12:111:14 | :"baz" | SymbolLiteral | baz |
-| literals.rb:112:1:112:25 | %i(...) | ArrayLiteral | |
+| literals.rb:112:1:112:39 | %i(...) | ArrayLiteral | |
| literals.rb:112:4:112:6 | :"foo" | SymbolLiteral | foo |
-| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | |
+| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | bar6 |
| literals.rb:112:14:112:14 | 2 | IntegerLiteral | 2 |
| literals.rb:112:18:112:18 | 4 | IntegerLiteral | 4 |
-| literals.rb:112:22:112:24 | :"baz" | SymbolLiteral | baz |
-| literals.rb:113:1:113:25 | %i(...) | ArrayLiteral | |
+| literals.rb:112:22:112:27 | :"#{...}" | SymbolLiteral | bar |
+| literals.rb:112:29:112:34 | :"#{...}" | SymbolLiteral | bar |
+| literals.rb:112:36:112:38 | :"baz" | SymbolLiteral | baz |
+| literals.rb:113:1:113:39 | %i(...) | ArrayLiteral | |
| literals.rb:113:4:113:6 | :"foo" | SymbolLiteral | foo |
| literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral | bar#{ |
| literals.rb:113:14:113:14 | :"2" | SymbolLiteral | 2 |
| literals.rb:113:16:113:16 | :"+" | SymbolLiteral | + |
| literals.rb:113:18:113:18 | :"4" | SymbolLiteral | 4 |
| literals.rb:113:20:113:20 | :"}" | SymbolLiteral | } |
-| literals.rb:113:22:113:24 | :"baz" | SymbolLiteral | baz |
+| literals.rb:113:22:113:27 | :"#{bar}" | SymbolLiteral | #{bar} |
+| literals.rb:113:29:113:34 | :"#{BAR}" | SymbolLiteral | #{BAR} |
+| literals.rb:113:36:113:38 | :"baz" | SymbolLiteral | baz |
| literals.rb:116:1:116:2 | {...} | HashLiteral | |
| literals.rb:117:1:117:33 | {...} | HashLiteral | |
| literals.rb:117:3:117:5 | :foo | SymbolLiteral | foo |
@@ -173,17 +185,17 @@ allLiterals
| literals.rb:127:6:127:6 | 1 | IntegerLiteral | 1 |
| literals.rb:130:1:130:7 | `ls -l` | SubshellLiteral | ls -l |
| literals.rb:131:1:131:9 | `ls -l` | SubshellLiteral | ls -l |
-| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | du -d 2 bar bar |
| literals.rb:132:11:132:11 | 1 | IntegerLiteral | 1 |
| literals.rb:132:15:132:15 | 1 | IntegerLiteral | 1 |
-| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | |
+| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | du -d 1 |
| literals.rb:133:13:133:13 | 5 | IntegerLiteral | 5 |
| literals.rb:133:17:133:17 | 4 | IntegerLiteral | 4 |
| literals.rb:136:1:136:2 | // | RegExpLiteral | |
| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | foo |
| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
@@ -191,7 +203,7 @@ allLiterals
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | foo+\\sbar\\S |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
@@ -218,8 +230,8 @@ stringlikeLiterals
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
-| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | |
-| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | |
+| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
+| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | 2 + 2 = #{ 2 + 2 } |
| literals.rb:61:1:61:22 | "3 + 4 = #{ 3 + 4 }" | 3 + 4 = #{ 3 + 4 } |
| literals.rb:62:1:62:5 | "foo" | foo |
@@ -229,11 +241,15 @@ stringlikeLiterals
| literals.rb:63:9:63:13 | "bar" | bar |
| literals.rb:63:15:63:19 | "baz" | baz |
| literals.rb:64:1:64:5 | "foo" | foo |
-| literals.rb:64:7:64:21 | "bar#{...}" | |
+| literals.rb:64:7:64:21 | "bar#{...}" | bar1 |
| literals.rb:64:23:64:27 | "baz" | baz |
-| literals.rb:65:1:65:35 | "foo #{...} qux" | |
-| literals.rb:65:9:65:28 | "bar #{...} baz" | |
-| literals.rb:66:1:66:22 | "foo #{...}" | |
+| literals.rb:65:1:65:35 | "foo #{...} qux" | foo bar 5 baz qux |
+| literals.rb:65:9:65:28 | "bar #{...} baz" | bar 5 baz |
+| literals.rb:66:1:66:22 | "foo #{...}" | foo 10 |
+| literals.rb:67:7:67:11 | "bar" | bar |
+| literals.rb:68:7:68:11 | "bar" | bar |
+| literals.rb:69:1:69:14 | "foo #{...}" | foo bar |
+| literals.rb:70:1:70:14 | "foo #{...}" | foo bar |
| literals.rb:84:1:84:3 | :"" | |
| literals.rb:85:1:85:6 | :hello | hello |
| literals.rb:86:1:86:10 | :"foo bar" | foo bar |
@@ -242,8 +258,8 @@ stringlikeLiterals
| literals.rb:88:8:88:12 | "bar" | bar |
| literals.rb:89:1:89:10 | :"wibble" | wibble |
| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | foo_4_bar_bar |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
| literals.rb:103:4:103:6 | "foo" | foo |
| literals.rb:103:8:103:10 | "bar" | bar |
@@ -252,11 +268,15 @@ stringlikeLiterals
| literals.rb:104:8:104:10 | "bar" | bar |
| literals.rb:104:12:104:14 | "baz" | baz |
| literals.rb:105:4:105:6 | "foo" | foo |
-| literals.rb:105:8:105:16 | "bar#{...}" | |
-| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:105:8:105:16 | "bar#{...}" | bar2 |
+| literals.rb:105:18:105:23 | "#{...}" | bar |
+| literals.rb:105:25:105:30 | "#{...}" | bar |
+| literals.rb:105:32:105:34 | "baz" | baz |
| literals.rb:106:4:106:6 | "foo" | foo |
| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:106:18:106:23 | "#{bar}" | #{bar} |
+| literals.rb:106:25:106:30 | "#{BAR}" | #{BAR} |
+| literals.rb:106:32:106:34 | "baz" | baz |
| literals.rb:110:4:110:6 | :"foo" | foo |
| literals.rb:110:8:110:10 | :"bar" | bar |
| literals.rb:110:12:110:14 | :"baz" | baz |
@@ -264,34 +284,38 @@ stringlikeLiterals
| literals.rb:111:8:111:10 | :"bar" | bar |
| literals.rb:111:12:111:14 | :"baz" | baz |
| literals.rb:112:4:112:6 | :"foo" | foo |
-| literals.rb:112:8:112:20 | :"bar#{...}" | |
-| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:112:8:112:20 | :"bar#{...}" | bar6 |
+| literals.rb:112:22:112:27 | :"#{...}" | bar |
+| literals.rb:112:29:112:34 | :"#{...}" | bar |
+| literals.rb:112:36:112:38 | :"baz" | baz |
| literals.rb:113:4:113:6 | :"foo" | foo |
| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
| literals.rb:113:14:113:14 | :"2" | 2 |
| literals.rb:113:16:113:16 | :"+" | + |
| literals.rb:113:18:113:18 | :"4" | 4 |
| literals.rb:113:20:113:20 | :"}" | } |
-| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:113:22:113:27 | :"#{bar}" | #{bar} |
+| literals.rb:113:29:113:34 | :"#{BAR}" | #{BAR} |
+| literals.rb:113:36:113:38 | :"baz" | baz |
| literals.rb:117:3:117:5 | :foo | foo |
| literals.rb:117:11:117:14 | :bar | bar |
| literals.rb:117:22:117:26 | "baz" | baz |
| literals.rb:118:3:118:5 | :foo | foo |
| literals.rb:130:1:130:7 | `ls -l` | ls -l |
| literals.rb:131:1:131:9 | `ls -l` | ls -l |
-| literals.rb:132:1:132:18 | `du -d #{...}` | |
-| literals.rb:133:1:133:20 | `du -d #{...}` | |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | du -d 2 bar bar |
+| literals.rb:133:1:133:20 | `du -d #{...}` | du -d 1 |
| literals.rb:136:1:136:2 | // | |
| literals.rb:137:1:137:5 | /foo/ | foo |
| literals.rb:138:1:138:6 | /foo/ | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals.rb:141:1:141:8 | /foo/ | foo |
| literals.rb:142:1:142:4 | // | |
| literals.rb:143:1:143:7 | /foo/ | foo |
| literals.rb:144:1:144:8 | /foo/ | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
| literals.rb:147:1:147:10 | /foo/ | foo |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
@@ -316,8 +340,8 @@ stringLiterals
| literals.rb:55:1:55:20 | "FOO ' BAR " BAZ'" | FOO ' BAR " BAZ' |
| literals.rb:56:1:56:12 | "foo\\ bar" | foo\\ bar |
| literals.rb:57:1:57:12 | "foo\\ bar" | foo\\ bar |
-| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | |
-| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | |
+| literals.rb:58:1:58:20 | "2 + 2 = #{...}" | 2 + 2 = 4 |
+| literals.rb:59:1:59:22 | "3 + 4 = #{...}" | 3 + 4 = 7 |
| literals.rb:60:1:60:20 | "2 + 2 = #{ 2 + 2 }" | 2 + 2 = #{ 2 + 2 } |
| literals.rb:61:1:61:22 | "3 + 4 = #{ 3 + 4 }" | 3 + 4 = #{ 3 + 4 } |
| literals.rb:62:1:62:5 | "foo" | foo |
@@ -327,11 +351,15 @@ stringLiterals
| literals.rb:63:9:63:13 | "bar" | bar |
| literals.rb:63:15:63:19 | "baz" | baz |
| literals.rb:64:1:64:5 | "foo" | foo |
-| literals.rb:64:7:64:21 | "bar#{...}" | |
+| literals.rb:64:7:64:21 | "bar#{...}" | bar1 |
| literals.rb:64:23:64:27 | "baz" | baz |
-| literals.rb:65:1:65:35 | "foo #{...} qux" | |
-| literals.rb:65:9:65:28 | "bar #{...} baz" | |
-| literals.rb:66:1:66:22 | "foo #{...}" | |
+| literals.rb:65:1:65:35 | "foo #{...} qux" | foo bar 5 baz qux |
+| literals.rb:65:9:65:28 | "bar #{...} baz" | bar 5 baz |
+| literals.rb:66:1:66:22 | "foo #{...}" | foo 10 |
+| literals.rb:67:7:67:11 | "bar" | bar |
+| literals.rb:68:7:68:11 | "bar" | bar |
+| literals.rb:69:1:69:14 | "foo #{...}" | foo bar |
+| literals.rb:70:1:70:14 | "foo #{...}" | foo bar |
| literals.rb:88:8:88:12 | "bar" | bar |
| literals.rb:103:4:103:6 | "foo" | foo |
| literals.rb:103:8:103:10 | "bar" | bar |
@@ -340,11 +368,15 @@ stringLiterals
| literals.rb:104:8:104:10 | "bar" | bar |
| literals.rb:104:12:104:14 | "baz" | baz |
| literals.rb:105:4:105:6 | "foo" | foo |
-| literals.rb:105:8:105:16 | "bar#{...}" | |
-| literals.rb:105:18:105:20 | "baz" | baz |
+| literals.rb:105:8:105:16 | "bar#{...}" | bar2 |
+| literals.rb:105:18:105:23 | "#{...}" | bar |
+| literals.rb:105:25:105:30 | "#{...}" | bar |
+| literals.rb:105:32:105:34 | "baz" | baz |
| literals.rb:106:4:106:6 | "foo" | foo |
| literals.rb:106:8:106:16 | "bar#{1+1}" | bar#{1+1} |
-| literals.rb:106:18:106:20 | "baz" | baz |
+| literals.rb:106:18:106:23 | "#{bar}" | #{bar} |
+| literals.rb:106:25:106:30 | "#{BAR}" | #{BAR} |
+| literals.rb:106:32:106:34 | "baz" | baz |
| literals.rb:117:22:117:26 | "baz" | baz |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
@@ -354,13 +386,13 @@ regExpLiterals
| literals.rb:137:1:137:5 | /foo/ | foo | |
| literals.rb:138:1:138:6 | /foo/ | foo | i |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | | |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
| literals.rb:142:1:142:4 | // | | |
| literals.rb:143:1:143:7 | /foo/ | foo | |
| literals.rb:144:1:144:8 | /foo/ | foo | i |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | | |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
symbolLiterals
| literals.rb:84:1:84:3 | :"" | |
@@ -370,8 +402,8 @@ symbolLiterals
| literals.rb:88:3:88:5 | :foo | foo |
| literals.rb:89:1:89:10 | :"wibble" | wibble |
| literals.rb:90:1:90:17 | :"wibble wobble" | wibble wobble |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | foo_#{ 1 + 1 } |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | foo_4_bar_bar |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | foo_#{ 2 + 2}_#{bar}_#{BAR} |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | foo_#{ 3 - 2 } |
| literals.rb:110:4:110:6 | :"foo" | foo |
| literals.rb:110:8:110:10 | :"bar" | bar |
@@ -380,23 +412,27 @@ symbolLiterals
| literals.rb:111:8:111:10 | :"bar" | bar |
| literals.rb:111:12:111:14 | :"baz" | baz |
| literals.rb:112:4:112:6 | :"foo" | foo |
-| literals.rb:112:8:112:20 | :"bar#{...}" | |
-| literals.rb:112:22:112:24 | :"baz" | baz |
+| literals.rb:112:8:112:20 | :"bar#{...}" | bar6 |
+| literals.rb:112:22:112:27 | :"#{...}" | bar |
+| literals.rb:112:29:112:34 | :"#{...}" | bar |
+| literals.rb:112:36:112:38 | :"baz" | baz |
| literals.rb:113:4:113:6 | :"foo" | foo |
| literals.rb:113:8:113:12 | :"bar#{" | bar#{ |
| literals.rb:113:14:113:14 | :"2" | 2 |
| literals.rb:113:16:113:16 | :"+" | + |
| literals.rb:113:18:113:18 | :"4" | 4 |
| literals.rb:113:20:113:20 | :"}" | } |
-| literals.rb:113:22:113:24 | :"baz" | baz |
+| literals.rb:113:22:113:27 | :"#{bar}" | #{bar} |
+| literals.rb:113:29:113:34 | :"#{BAR}" | #{BAR} |
+| literals.rb:113:36:113:38 | :"baz" | baz |
| literals.rb:117:3:117:5 | :foo | foo |
| literals.rb:117:11:117:14 | :bar | bar |
| literals.rb:118:3:118:5 | :foo | foo |
subshellLiterals
| literals.rb:130:1:130:7 | `ls -l` | ls -l |
| literals.rb:131:1:131:9 | `ls -l` | ls -l |
-| literals.rb:132:1:132:18 | `du -d #{...}` | |
-| literals.rb:133:1:133:20 | `du -d #{...}` | |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | du -d 2 bar bar |
+| literals.rb:133:1:133:20 | `du -d #{...}` | du -d 1 |
stringComponents
| literals.rb:48:1:48:7 | "hello" | StringLiteral | 0 | literals.rb:48:2:48:6 | hello | StringTextComponent |
| literals.rb:49:1:49:9 | "goodbye" | StringLiteral | 0 | literals.rb:49:2:49:8 | goodbye | StringTextComponent |
@@ -436,14 +472,24 @@ stringComponents
| literals.rb:65:9:65:28 | "bar #{...} baz" | StringLiteral | 2 | literals.rb:65:24:65:27 | baz | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 0 | literals.rb:66:2:66:5 | foo | StringTextComponent |
| literals.rb:66:1:66:22 | "foo #{...}" | StringLiteral | 1 | literals.rb:66:6:66:21 | #{...} | StringInterpolationComponent |
+| literals.rb:67:7:67:11 | "bar" | StringLiteral | 0 | literals.rb:67:8:67:10 | bar | StringTextComponent |
+| literals.rb:68:7:68:11 | "bar" | StringLiteral | 0 | literals.rb:68:8:68:10 | bar | StringTextComponent |
+| literals.rb:69:1:69:14 | "foo #{...}" | StringLiteral | 0 | literals.rb:69:2:69:5 | foo | StringTextComponent |
+| literals.rb:69:1:69:14 | "foo #{...}" | StringLiteral | 1 | literals.rb:69:6:69:13 | #{...} | StringInterpolationComponent |
+| literals.rb:70:1:70:14 | "foo #{...}" | StringLiteral | 0 | literals.rb:70:2:70:5 | foo | StringTextComponent |
+| literals.rb:70:1:70:14 | "foo #{...}" | StringLiteral | 1 | literals.rb:70:6:70:13 | #{...} | StringInterpolationComponent |
| literals.rb:86:1:86:10 | :"foo bar" | SymbolLiteral | 0 | literals.rb:86:3:86:9 | foo bar | StringTextComponent |
| literals.rb:87:1:87:10 | :"bar baz" | SymbolLiteral | 0 | literals.rb:87:3:87:9 | bar baz | StringTextComponent |
| literals.rb:88:8:88:12 | "bar" | StringLiteral | 0 | literals.rb:88:9:88:11 | bar | StringTextComponent |
| literals.rb:89:1:89:10 | :"wibble" | SymbolLiteral | 0 | literals.rb:89:4:89:9 | wibble | StringTextComponent |
| literals.rb:90:1:90:17 | :"wibble wobble" | SymbolLiteral | 0 | literals.rb:90:4:90:16 | wibble wobble | StringTextComponent |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | 0 | literals.rb:91:3:91:6 | foo_ | StringTextComponent |
-| literals.rb:91:1:91:16 | :"foo_#{...}" | SymbolLiteral | 1 | literals.rb:91:7:91:15 | #{...} | StringInterpolationComponent |
-| literals.rb:92:1:92:17 | :"foo_#{ 1 + 1 }" | SymbolLiteral | 0 | literals.rb:92:3:92:16 | foo_#{ 1 + 1 } | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 0 | literals.rb:91:3:91:6 | foo_ | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 1 | literals.rb:91:7:91:15 | #{...} | StringInterpolationComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 2 | literals.rb:91:16:91:16 | _ | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 3 | literals.rb:91:17:91:22 | #{...} | StringInterpolationComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 4 | literals.rb:91:23:91:23 | _ | StringTextComponent |
+| literals.rb:91:1:91:30 | :"foo_#{...}_#{...}_#{...}" | SymbolLiteral | 5 | literals.rb:91:24:91:29 | #{...} | StringInterpolationComponent |
+| literals.rb:92:1:92:30 | :"foo_#{ 2 + 2}_#{bar}_#{BAR}" | SymbolLiteral | 0 | literals.rb:92:3:92:29 | foo_#{ 2 + 2}_#{bar}_#{BAR} | StringTextComponent |
| literals.rb:93:1:93:18 | :"foo_#{ 3 - 2 }" | SymbolLiteral | 0 | literals.rb:93:4:93:17 | foo_#{ 3 - 2 } | StringTextComponent |
| literals.rb:103:4:103:6 | "foo" | StringLiteral | 0 | literals.rb:103:4:103:6 | foo | StringTextComponent |
| literals.rb:103:8:103:10 | "bar" | StringLiteral | 0 | literals.rb:103:8:103:10 | bar | StringTextComponent |
@@ -454,10 +500,14 @@ stringComponents
| literals.rb:105:4:105:6 | "foo" | StringLiteral | 0 | literals.rb:105:4:105:6 | foo | StringTextComponent |
| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | 0 | literals.rb:105:8:105:10 | bar | StringTextComponent |
| literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral | 1 | literals.rb:105:11:105:16 | #{...} | StringInterpolationComponent |
-| literals.rb:105:18:105:20 | "baz" | StringLiteral | 0 | literals.rb:105:18:105:20 | baz | StringTextComponent |
+| literals.rb:105:18:105:23 | "#{...}" | StringLiteral | 0 | literals.rb:105:18:105:23 | #{...} | StringInterpolationComponent |
+| literals.rb:105:25:105:30 | "#{...}" | StringLiteral | 0 | literals.rb:105:25:105:30 | #{...} | StringInterpolationComponent |
+| literals.rb:105:32:105:34 | "baz" | StringLiteral | 0 | literals.rb:105:32:105:34 | baz | StringTextComponent |
| literals.rb:106:4:106:6 | "foo" | StringLiteral | 0 | literals.rb:106:4:106:6 | foo | StringTextComponent |
| literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral | 0 | literals.rb:106:8:106:16 | bar#{1+1} | StringTextComponent |
-| literals.rb:106:18:106:20 | "baz" | StringLiteral | 0 | literals.rb:106:18:106:20 | baz | StringTextComponent |
+| literals.rb:106:18:106:23 | "#{bar}" | StringLiteral | 0 | literals.rb:106:18:106:23 | #{bar} | StringTextComponent |
+| literals.rb:106:25:106:30 | "#{BAR}" | StringLiteral | 0 | literals.rb:106:25:106:30 | #{BAR} | StringTextComponent |
+| literals.rb:106:32:106:34 | "baz" | StringLiteral | 0 | literals.rb:106:32:106:34 | baz | StringTextComponent |
| literals.rb:110:4:110:6 | :"foo" | SymbolLiteral | 0 | literals.rb:110:4:110:6 | foo | StringTextComponent |
| literals.rb:110:8:110:10 | :"bar" | SymbolLiteral | 0 | literals.rb:110:8:110:10 | bar | StringTextComponent |
| literals.rb:110:12:110:14 | :"baz" | SymbolLiteral | 0 | literals.rb:110:12:110:14 | baz | StringTextComponent |
@@ -467,19 +517,27 @@ stringComponents
| literals.rb:112:4:112:6 | :"foo" | SymbolLiteral | 0 | literals.rb:112:4:112:6 | foo | StringTextComponent |
| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | 0 | literals.rb:112:8:112:10 | bar | StringTextComponent |
| literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral | 1 | literals.rb:112:11:112:20 | #{...} | StringInterpolationComponent |
-| literals.rb:112:22:112:24 | :"baz" | SymbolLiteral | 0 | literals.rb:112:22:112:24 | baz | StringTextComponent |
+| literals.rb:112:22:112:27 | :"#{...}" | SymbolLiteral | 0 | literals.rb:112:22:112:27 | #{...} | StringInterpolationComponent |
+| literals.rb:112:29:112:34 | :"#{...}" | SymbolLiteral | 0 | literals.rb:112:29:112:34 | #{...} | StringInterpolationComponent |
+| literals.rb:112:36:112:38 | :"baz" | SymbolLiteral | 0 | literals.rb:112:36:112:38 | baz | StringTextComponent |
| literals.rb:113:4:113:6 | :"foo" | SymbolLiteral | 0 | literals.rb:113:4:113:6 | foo | StringTextComponent |
| literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral | 0 | literals.rb:113:8:113:12 | bar#{ | StringTextComponent |
| literals.rb:113:14:113:14 | :"2" | SymbolLiteral | 0 | literals.rb:113:14:113:14 | 2 | StringTextComponent |
| literals.rb:113:16:113:16 | :"+" | SymbolLiteral | 0 | literals.rb:113:16:113:16 | + | StringTextComponent |
| literals.rb:113:18:113:18 | :"4" | SymbolLiteral | 0 | literals.rb:113:18:113:18 | 4 | StringTextComponent |
| literals.rb:113:20:113:20 | :"}" | SymbolLiteral | 0 | literals.rb:113:20:113:20 | } | StringTextComponent |
-| literals.rb:113:22:113:24 | :"baz" | SymbolLiteral | 0 | literals.rb:113:22:113:24 | baz | StringTextComponent |
+| literals.rb:113:22:113:27 | :"#{bar}" | SymbolLiteral | 0 | literals.rb:113:22:113:27 | #{bar} | StringTextComponent |
+| literals.rb:113:29:113:34 | :"#{BAR}" | SymbolLiteral | 0 | literals.rb:113:29:113:34 | #{BAR} | StringTextComponent |
+| literals.rb:113:36:113:38 | :"baz" | SymbolLiteral | 0 | literals.rb:113:36:113:38 | baz | StringTextComponent |
| literals.rb:117:22:117:26 | "baz" | StringLiteral | 0 | literals.rb:117:23:117:25 | baz | StringTextComponent |
| literals.rb:130:1:130:7 | `ls -l` | SubshellLiteral | 0 | literals.rb:130:2:130:6 | ls -l | StringTextComponent |
| literals.rb:131:1:131:9 | `ls -l` | SubshellLiteral | 0 | literals.rb:131:4:131:8 | ls -l | StringTextComponent |
-| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:132:2:132:7 | du -d | StringTextComponent |
-| literals.rb:132:1:132:18 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:132:8:132:17 | #{...} | StringInterpolationComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 0 | literals.rb:132:2:132:7 | du -d | StringTextComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 1 | literals.rb:132:8:132:17 | #{...} | StringInterpolationComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 2 | literals.rb:132:18:132:18 | | StringTextComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 3 | literals.rb:132:19:132:24 | #{...} | StringInterpolationComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 4 | literals.rb:132:25:132:25 | | StringTextComponent |
+| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 5 | literals.rb:132:26:132:31 | #{...} | StringInterpolationComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:133:4:133:9 | du -d | StringTextComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:133:10:133:19 | #{...} | StringInterpolationComponent |
| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
@@ -488,9 +546,11 @@ stringComponents
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | StringEscapeSequenceComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | StringTextComponent |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | StringEscapeSequenceComponent |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
-| literals.rb:140:1:140:18 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | StringInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | StringInterpolationComponent |
| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | StringTextComponent |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | StringTextComponent |
@@ -498,9 +558,11 @@ stringComponents
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | StringEscapeSequenceComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | StringTextComponent |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | StringEscapeSequenceComponent |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
-| literals.rb:146:1:146:20 | /foo#{...}bar/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | StringInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | StringInterpolationComponent |
| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | StringTextComponent |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:150:2:150:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:151:2:151:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
@@ -536,13 +598,27 @@ stringInterpolations
| literals.rb:65:14:65:23 | #{...} | 0 | literals.rb:65:17:65:21 | ... + ... | AddExpr |
| literals.rb:66:6:66:21 | #{...} | 0 | literals.rb:66:9:66:14 | call to blah | MethodCall |
| literals.rb:66:6:66:21 | #{...} | 1 | literals.rb:66:17:66:19 | ... + ... | AddExpr |
+| literals.rb:69:6:69:13 | #{...} | 0 | literals.rb:69:9:69:11 | bar | LocalVariableAccess |
+| literals.rb:70:6:70:13 | #{...} | 0 | literals.rb:70:9:70:11 | BAR | ConstantReadAccess |
| literals.rb:91:7:91:15 | #{...} | 0 | literals.rb:91:10:91:14 | ... + ... | AddExpr |
+| literals.rb:91:17:91:22 | #{...} | 0 | literals.rb:91:19:91:21 | bar | LocalVariableAccess |
+| literals.rb:91:24:91:29 | #{...} | 0 | literals.rb:91:26:91:28 | BAR | ConstantReadAccess |
| literals.rb:105:11:105:16 | #{...} | 0 | literals.rb:105:13:105:15 | ... + ... | AddExpr |
+| literals.rb:105:18:105:23 | #{...} | 0 | literals.rb:105:20:105:22 | bar | LocalVariableAccess |
+| literals.rb:105:25:105:30 | #{...} | 0 | literals.rb:105:27:105:29 | BAR | ConstantReadAccess |
| literals.rb:112:11:112:20 | #{...} | 0 | literals.rb:112:14:112:18 | ... + ... | AddExpr |
+| literals.rb:112:22:112:27 | #{...} | 0 | literals.rb:112:24:112:26 | bar | LocalVariableAccess |
+| literals.rb:112:29:112:34 | #{...} | 0 | literals.rb:112:31:112:33 | BAR | ConstantReadAccess |
| literals.rb:132:8:132:17 | #{...} | 0 | literals.rb:132:11:132:15 | ... + ... | AddExpr |
+| literals.rb:132:19:132:24 | #{...} | 0 | literals.rb:132:21:132:23 | bar | LocalVariableAccess |
+| literals.rb:132:26:132:31 | #{...} | 0 | literals.rb:132:28:132:30 | BAR | ConstantReadAccess |
| literals.rb:133:10:133:19 | #{...} | 0 | literals.rb:133:13:133:17 | ... - ... | SubExpr |
| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
+| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
+| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
+| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
+| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
| literals.rb:158:14:158:22 | #{...} | 0 | literals.rb:158:17:158:20 | call to name | MethodCall |
| literals.rb:172:12:172:29 | #{...} | 0 | literals.rb:172:15:172:27 | call to interpolation | MethodCall |
| literals.rb:177:15:177:32 | #{...} | 0 | literals.rb:177:18:177:30 | call to interpolation | MethodCall |
@@ -553,9 +629,9 @@ concatenatedStrings
| literals.rb:63:1:63:19 | "..." "..." | foobarbaz | 0 | literals.rb:63:1:63:7 | "foo" |
| literals.rb:63:1:63:19 | "..." "..." | foobarbaz | 1 | literals.rb:63:9:63:13 | "bar" |
| literals.rb:63:1:63:19 | "..." "..." | foobarbaz | 2 | literals.rb:63:15:63:19 | "baz" |
-| literals.rb:64:1:64:27 | "..." "..." | | 0 | literals.rb:64:1:64:5 | "foo" |
-| literals.rb:64:1:64:27 | "..." "..." | | 1 | literals.rb:64:7:64:21 | "bar#{...}" |
-| literals.rb:64:1:64:27 | "..." "..." | | 2 | literals.rb:64:23:64:27 | "baz" |
+| literals.rb:64:1:64:27 | "..." "..." | foobar1baz | 0 | literals.rb:64:1:64:5 | "foo" |
+| literals.rb:64:1:64:27 | "..." "..." | foobar1baz | 1 | literals.rb:64:7:64:21 | "bar#{...}" |
+| literals.rb:64:1:64:27 | "..." "..." | foobar1baz | 2 | literals.rb:64:23:64:27 | "baz" |
arrayLiterals
| literals.rb:96:1:96:2 | [...] | 0 |
| literals.rb:97:1:97:9 | [...] | 3 |
@@ -565,13 +641,13 @@ arrayLiterals
| literals.rb:102:1:102:4 | %w(...) | 0 |
| literals.rb:103:1:103:15 | %w(...) | 3 |
| literals.rb:104:1:104:15 | %w(...) | 3 |
-| literals.rb:105:1:105:21 | %w(...) | 3 |
-| literals.rb:106:1:106:21 | %w(...) | 3 |
+| literals.rb:105:1:105:35 | %w(...) | 5 |
+| literals.rb:106:1:106:35 | %w(...) | 5 |
| literals.rb:109:1:109:4 | %i(...) | 0 |
| literals.rb:110:1:110:15 | %i(...) | 3 |
| literals.rb:111:1:111:15 | %i(...) | 3 |
-| literals.rb:112:1:112:25 | %i(...) | 3 |
-| literals.rb:113:1:113:25 | %i(...) | 7 |
+| literals.rb:112:1:112:39 | %i(...) | 5 |
+| literals.rb:113:1:113:39 | %i(...) | 9 |
arrayLiteralElements
| literals.rb:97:1:97:9 | [...] | 0 | literals.rb:97:2:97:2 | 1 | IntegerLiteral |
| literals.rb:97:1:97:9 | [...] | 1 | literals.rb:97:5:97:5 | 2 | IntegerLiteral |
@@ -589,28 +665,36 @@ arrayLiteralElements
| literals.rb:104:1:104:15 | %w(...) | 0 | literals.rb:104:4:104:6 | "foo" | StringLiteral |
| literals.rb:104:1:104:15 | %w(...) | 1 | literals.rb:104:8:104:10 | "bar" | StringLiteral |
| literals.rb:104:1:104:15 | %w(...) | 2 | literals.rb:104:12:104:14 | "baz" | StringLiteral |
-| literals.rb:105:1:105:21 | %w(...) | 0 | literals.rb:105:4:105:6 | "foo" | StringLiteral |
-| literals.rb:105:1:105:21 | %w(...) | 1 | literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral |
-| literals.rb:105:1:105:21 | %w(...) | 2 | literals.rb:105:18:105:20 | "baz" | StringLiteral |
-| literals.rb:106:1:106:21 | %w(...) | 0 | literals.rb:106:4:106:6 | "foo" | StringLiteral |
-| literals.rb:106:1:106:21 | %w(...) | 1 | literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral |
-| literals.rb:106:1:106:21 | %w(...) | 2 | literals.rb:106:18:106:20 | "baz" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 0 | literals.rb:105:4:105:6 | "foo" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 1 | literals.rb:105:8:105:16 | "bar#{...}" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 2 | literals.rb:105:18:105:23 | "#{...}" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 3 | literals.rb:105:25:105:30 | "#{...}" | StringLiteral |
+| literals.rb:105:1:105:35 | %w(...) | 4 | literals.rb:105:32:105:34 | "baz" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 0 | literals.rb:106:4:106:6 | "foo" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 1 | literals.rb:106:8:106:16 | "bar#{1+1}" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 2 | literals.rb:106:18:106:23 | "#{bar}" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 3 | literals.rb:106:25:106:30 | "#{BAR}" | StringLiteral |
+| literals.rb:106:1:106:35 | %w(...) | 4 | literals.rb:106:32:106:34 | "baz" | StringLiteral |
| literals.rb:110:1:110:15 | %i(...) | 0 | literals.rb:110:4:110:6 | :"foo" | SymbolLiteral |
| literals.rb:110:1:110:15 | %i(...) | 1 | literals.rb:110:8:110:10 | :"bar" | SymbolLiteral |
| literals.rb:110:1:110:15 | %i(...) | 2 | literals.rb:110:12:110:14 | :"baz" | SymbolLiteral |
| literals.rb:111:1:111:15 | %i(...) | 0 | literals.rb:111:4:111:6 | :"foo" | SymbolLiteral |
| literals.rb:111:1:111:15 | %i(...) | 1 | literals.rb:111:8:111:10 | :"bar" | SymbolLiteral |
| literals.rb:111:1:111:15 | %i(...) | 2 | literals.rb:111:12:111:14 | :"baz" | SymbolLiteral |
-| literals.rb:112:1:112:25 | %i(...) | 0 | literals.rb:112:4:112:6 | :"foo" | SymbolLiteral |
-| literals.rb:112:1:112:25 | %i(...) | 1 | literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral |
-| literals.rb:112:1:112:25 | %i(...) | 2 | literals.rb:112:22:112:24 | :"baz" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 0 | literals.rb:113:4:113:6 | :"foo" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 1 | literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 2 | literals.rb:113:14:113:14 | :"2" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 3 | literals.rb:113:16:113:16 | :"+" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 4 | literals.rb:113:18:113:18 | :"4" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 5 | literals.rb:113:20:113:20 | :"}" | SymbolLiteral |
-| literals.rb:113:1:113:25 | %i(...) | 6 | literals.rb:113:22:113:24 | :"baz" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 0 | literals.rb:112:4:112:6 | :"foo" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 1 | literals.rb:112:8:112:20 | :"bar#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 2 | literals.rb:112:22:112:27 | :"#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 3 | literals.rb:112:29:112:34 | :"#{...}" | SymbolLiteral |
+| literals.rb:112:1:112:39 | %i(...) | 4 | literals.rb:112:36:112:38 | :"baz" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 0 | literals.rb:113:4:113:6 | :"foo" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 1 | literals.rb:113:8:113:12 | :"bar#{" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 2 | literals.rb:113:14:113:14 | :"2" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 3 | literals.rb:113:16:113:16 | :"+" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 4 | literals.rb:113:18:113:18 | :"4" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 5 | literals.rb:113:20:113:20 | :"}" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 6 | literals.rb:113:22:113:27 | :"#{bar}" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 7 | literals.rb:113:29:113:34 | :"#{BAR}" | SymbolLiteral |
+| literals.rb:113:1:113:39 | %i(...) | 8 | literals.rb:113:36:113:38 | :"baz" | SymbolLiteral |
hashLiterals
| literals.rb:88:1:88:14 | {...} | 1 |
| literals.rb:116:1:116:2 | {...} | 0 |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.rb b/ruby/ql/test/library-tests/ast/literals/literals.rb
index 1c1304d9eef..3918bfc1186 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.rb
+++ b/ruby/ql/test/library-tests/ast/literals/literals.rb
@@ -64,10 +64,10 @@ TRUE
"foo" "bar#{ 1 * 1 }" 'baz' # concatenated, interpolation
"foo #{ "bar #{ 2 + 3 } baz" } qux" # interpolation containing string containing interpolation
"foo #{ blah(); 1+9 }" # multiple statements in interpolation
-
-
-
-
+bar = "bar"
+BAR = "bar"
+"foo #{ bar }" # local variables in interpolation
+"foo #{ BAR }" # constants in interpolation
# characters
?x
@@ -88,8 +88,8 @@ TRUE
{ foo: "bar" }
%s(wibble)
%s[wibble wobble]
-:"foo_#{ 2 + 2}" # interpolation
-:'foo_#{ 1 + 1 }' # no interpolation
+:"foo_#{ 2 + 2}_#{bar}_#{BAR}" # interpolation
+:'foo_#{ 2 + 2}_#{bar}_#{BAR}' # no interpolation
%s(foo_#{ 3 - 2 }) # no interpolation
# arrays
@@ -102,20 +102,20 @@ TRUE
%w()
%w(foo bar baz)
%w!foo bar baz!
-%W[foo bar#{1+1} baz] # interpolation
-%w[foo bar#{1+1} baz] # no interpolation
+%W[foo bar#{1+1} #{bar} #{BAR} baz] # interpolation
+%w[foo bar#{1+1} #{bar} #{BAR} baz] # no interpolation
# arrays of symbols
%i()
%i(foo bar baz)
%i@foo bar baz@
-%I(foo bar#{ 2 + 4 } baz) # interpolation
-%i(foo bar#{ 2 + 4 } baz) # no interpolation
+%I(foo bar#{ 2 + 4 } #{bar} #{BAR} baz) # interpolation
+%i(foo bar#{ 2 + 4 } #{bar} #{BAR} baz) # no interpolation
# hashes
{}
{ foo: 1, :bar => 2, 'baz' => 3 }
-{ foo: 7, **bar } # hash-splat argument
+{ foo: 7, **baz } # hash-splat argument
# ranges
(1..10)
@@ -129,21 +129,21 @@ TRUE
# subshell
`ls -l`
%x(ls -l)
-`du -d #{ 1 + 1 }` # interpolation
-%x@du -d #{ 5 - 4 }@ # interpolation
+`du -d #{ 1 + 1 } #{bar} #{BAR}` # interpolation
+%x@du -d #{ 5 - 4 }@ # interpolation
# regular expressions
//
/foo/
/foo/i
/foo+\sbar\S/
-/foo#{ 1 + 1 }bar/ # interpolation
+/foo#{ 1 + 1 }bar#{bar}#{BAR}/ # interpolation
/foo/oxm
%r[]
%r(foo)
%r:foo:i
%r{foo+\sbar\S}
-%r{foo#{ 1 + 1 }bar} # interpolation
+%r{foo#{ 1 + 1 }bar#{bar}#{BAR}} # interpolation
%r:foo:mxo
# long strings
diff --git a/ruby/ql/test/library-tests/ast/misc/misc.expected b/ruby/ql/test/library-tests/ast/misc/misc.expected
index 45235cd5787..befd5734091 100644
--- a/ruby/ql/test/library-tests/ast/misc/misc.expected
+++ b/ruby/ql/test/library-tests/ast/misc/misc.expected
@@ -4,7 +4,7 @@ undef
| misc.rb:3:1:3:30 | undef ... | 2 | misc.rb:3:18:3:21 | foo= | foo= | MethodName |
| misc.rb:3:1:3:30 | undef ... | 3 | misc.rb:3:24:3:25 | [] | [] | MethodName |
| misc.rb:3:1:3:30 | undef ... | 4 | misc.rb:3:28:3:30 | []= | []= | MethodName |
-| misc.rb:4:1:4:19 | undef ... | 0 | misc.rb:4:7:4:19 | :"foo_#{...}" | (none) | MethodName |
+| misc.rb:4:1:4:19 | undef ... | 0 | misc.rb:4:7:4:19 | :"foo_#{...}" | foo_bar | MethodName |
| misc.rb:5:1:5:35 | undef ... | 0 | misc.rb:5:7:5:9 | nil | nil | MethodName |
| misc.rb:5:1:5:35 | undef ... | 1 | misc.rb:5:12:5:15 | true | true | MethodName |
| misc.rb:5:1:5:35 | undef ... | 2 | misc.rb:5:18:5:22 | false | false | MethodName |
@@ -17,5 +17,5 @@ alias
| misc.rb:8:1:8:14 | alias ... | old | misc.rb:8:12:8:14 | []= | []= | MethodName |
| misc.rb:9:1:9:16 | alias ... | new | misc.rb:9:7:9:11 | super | super | MethodName |
| misc.rb:9:1:9:16 | alias ... | old | misc.rb:9:13:9:16 | self | self | MethodName |
-| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | (none) | MethodName |
+| misc.rb:10:1:10:24 | alias ... | new | misc.rb:10:7:10:17 | :"\\n#{...}" | \\nbar | MethodName |
| misc.rb:10:1:10:24 | alias ... | old | misc.rb:10:19:10:24 | :"foo" | foo | MethodName |
diff --git a/ruby/ql/test/library-tests/regexp/parse.expected b/ruby/ql/test/library-tests/regexp/parse.expected
index af5c9135ee6..756a69e8315 100644
--- a/ruby/ql/test/library-tests/regexp/parse.expected
+++ b/ruby/ql/test/library-tests/regexp/parse.expected
@@ -582,3 +582,14 @@ regexp.rb:
# 71| [RegExpConstant, RegExpNormalChar] f
# 74| [RegExpNamedCharacterProperty] [:digit:]
+
+# 78| [RegExpConstant, RegExpNormalChar] a
+
+# 78| [RegExpSequence] abc
+#-----| 0 -> [RegExpConstant, RegExpNormalChar] a
+#-----| 1 -> [RegExpConstant, RegExpNormalChar] b
+#-----| 2 -> [RegExpConstant, RegExpNormalChar] c
+
+# 78| [RegExpConstant, RegExpNormalChar] b
+
+# 78| [RegExpConstant, RegExpNormalChar] c
diff --git a/ruby/ql/test/library-tests/regexp/regexp.rb b/ruby/ql/test/library-tests/regexp/regexp.rb
index c1b94b52370..28030b914e5 100644
--- a/ruby/ql/test/library-tests/regexp/regexp.rb
+++ b/ruby/ql/test/library-tests/regexp/regexp.rb
@@ -71,4 +71,8 @@
/[A-F[:digit:]a-f]/
# *Not* a POSIX bracket expression; just a regular character class.
-/[:digit:]/
\ No newline at end of file
+/[:digit:]/
+
+# Simple constant interpolation
+A = "a"
+/#{A}bc/
\ No newline at end of file
From 23f1352953e9c43f789e1aa356d47c2875479c5d Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Mon, 13 Dec 2021 16:21:03 +1300
Subject: [PATCH 004/196] Add ReDoS test that uses string interpolation
This exercises the support for resolving string interpolations, and is
based on a real vulnerability:
https://github.com/advisories/GHSA-jxhc-q857-3j6g)
---
.../cwe-1333-exponential-redos/ReDoS.expected | 1 +
.../addressable-LICENSE | 201 ++++++++++++++++++
.../cwe-1333-exponential-redos/tst.rb | 11 +
3 files changed, 213 insertions(+)
create mode 100644 ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE
diff --git a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected
index 9a3d82b41a0..213f0e11189 100644
--- a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected
+++ b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/ReDoS.expected
@@ -94,3 +94,4 @@
| tst.rb:375:11:375:27 | ([[:digit:]]\|\\d)+ | This part of the regular expression may cause exponential backtracking on strings starting with 'X' and containing many repetitions of '0'. |
| tst.rb:378:12:378:18 | (a\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
| tst.rb:379:12:379:18 | (a\|\\w)* | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of 'a'. |
+| tst.rb:390:66:390:67 | .? | This part of the regular expression may cause exponential backtracking on strings containing many repetitions of '00\\\\'. |
diff --git a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE
new file mode 100644
index 00000000000..11069edd790
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/addressable-LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb
index 0d4e893c660..19d22033c10 100644
--- a/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb
+++ b/ruby/ql/test/query-tests/security/cwe-1333-exponential-redos/tst.rb
@@ -378,3 +378,14 @@ bad88 = /X([[:digit:]]|\d)+Y/
bad89 = /\G(a|\w)*$/
bad90 = /\b(a|\w)*$/
+# NOT GOOD; attack: "0".repeat(30) + "!"
+# Adapated from addressable (https://github.com/sporkmonger/addressable)
+# which is licensed under the Apache License 2.0; see file addressable-LICENSE.
+module Bad91
+ ALPHA = "a-zA-Z"
+ DIGIT = "0-9"
+ var_char_class = ALPHA + DIGIT + '_'
+ var_char = "(?:(?:[#{var_char_class}]|%[a-fA-F0-9][a-fA-F0-9])+)"
+ var = "(?:#{var_char}(?:\\.?#{var_char})*)"
+ bad91 = /^#{var}$/
+end
From 301d0bbdf81096f1f0988f01fb72973bc9147f2c Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 10:44:24 +0100
Subject: [PATCH 005/196] Ruby: Restructure test to avoid dead code
---
ruby/ql/test/library-tests/ast/Ast.expected | 275 +++++++++---------
.../library-tests/ast/AstDesugar.expected | 20 +-
.../test/library-tests/ast/ValueText.expected | 77 ++---
.../ast/control/CaseExpr.expected | 98 ++++---
.../ast/control/ControlExpr.expected | 9 +-
.../test/library-tests/ast/control/cases.rb | 7 +-
6 files changed, 248 insertions(+), 238 deletions(-)
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index 57c9704bc40..94b5cb5fda1 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -920,187 +920,190 @@ control/cases.rb:
# 88| getPattern: [VariableReferencePattern] ^...
# 88| getVariableAccess: [LocalVariableAccess] foo
# 89| getBranch: [InClause] in ... then ...
-# 89| getPattern: [LocalVariableAccess] var
+# 89| getPattern: [StringLiteral] "string"
+# 89| getComponent: [StringTextComponent] string
# 90| getBranch: [InClause] in ... then ...
-# 90| getPattern: [StringLiteral] "string"
-# 90| getComponent: [StringTextComponent] string
+# 90| getPattern: [ArrayLiteral] %w(...)
+# 90| getElement: [StringLiteral] "foo"
+# 90| getComponent: [StringTextComponent] foo
+# 90| getElement: [StringLiteral] "bar"
+# 90| getComponent: [StringTextComponent] bar
# 91| getBranch: [InClause] in ... then ...
-# 91| getPattern: [ArrayLiteral] %w(...)
-# 91| getElement: [StringLiteral] "foo"
+# 91| getPattern: [ArrayLiteral] %i(...)
+# 91| getElement: [SymbolLiteral] :"foo"
# 91| getComponent: [StringTextComponent] foo
-# 91| getElement: [StringLiteral] "bar"
+# 91| getElement: [SymbolLiteral] :"bar"
# 91| getComponent: [StringTextComponent] bar
# 92| getBranch: [InClause] in ... then ...
-# 92| getPattern: [ArrayLiteral] %i(...)
-# 92| getElement: [SymbolLiteral] :"foo"
-# 92| getComponent: [StringTextComponent] foo
-# 92| getElement: [SymbolLiteral] :"bar"
-# 92| getComponent: [StringTextComponent] bar
+# 92| getPattern: [RegExpLiteral] /.*abc[0-9]/
+# 92| getParsed: [RegExpSequence] .*abc[0-9]
+# 92| 0: [RegExpStar] .*
+# 92| 0: [RegExpDot] .
+# 92| 1: [RegExpConstant, RegExpNormalChar] a
+# 92| 2: [RegExpConstant, RegExpNormalChar] b
+# 92| 3: [RegExpConstant, RegExpNormalChar] c
+# 92| 4: [RegExpCharacterClass] [0-9]
+# 92| 0: [RegExpCharacterRange] 0-9
+# 92| 0: [RegExpConstant, RegExpNormalChar] 0
+# 92| 1: [RegExpConstant, RegExpNormalChar] 9
+# 92| getComponent: [StringTextComponent] .*abc[0-9]
# 93| getBranch: [InClause] in ... then ...
-# 93| getPattern: [RegExpLiteral] /.*abc[0-9]/
-# 93| getParsed: [RegExpSequence] .*abc[0-9]
-# 93| 0: [RegExpStar] .*
-# 93| 0: [RegExpDot] .
-# 93| 1: [RegExpConstant, RegExpNormalChar] a
-# 93| 2: [RegExpConstant, RegExpNormalChar] b
-# 93| 3: [RegExpConstant, RegExpNormalChar] c
-# 93| 4: [RegExpCharacterClass] [0-9]
-# 93| 0: [RegExpCharacterRange] 0-9
-# 93| 0: [RegExpConstant, RegExpNormalChar] 0
-# 93| 1: [RegExpConstant, RegExpNormalChar] 9
-# 93| getComponent: [StringTextComponent] .*abc[0-9]
+# 93| getPattern: [RangeLiteral] _ .. _
+# 93| getBegin: [IntegerLiteral] 5
+# 93| getEnd: [IntegerLiteral] 10
# 94| getBranch: [InClause] in ... then ...
# 94| getPattern: [RangeLiteral] _ .. _
-# 94| getBegin: [IntegerLiteral] 5
# 94| getEnd: [IntegerLiteral] 10
# 95| getBranch: [InClause] in ... then ...
# 95| getPattern: [RangeLiteral] _ .. _
-# 95| getEnd: [IntegerLiteral] 10
+# 95| getBegin: [IntegerLiteral] 5
# 96| getBranch: [InClause] in ... then ...
-# 96| getPattern: [RangeLiteral] _ .. _
-# 96| getBegin: [IntegerLiteral] 5
+# 96| getPattern: [AsPattern] ... => ...
+# 96| getPattern: [IntegerLiteral] 5
+# 96| getVariableAccess: [LocalVariableAccess] x
# 97| getBranch: [InClause] in ... then ...
-# 97| getPattern: [AsPattern] ... => ...
-# 97| getPattern: [IntegerLiteral] 5
-# 97| getVariableAccess: [LocalVariableAccess] x
+# 97| getPattern: [ConstantReadAccess] Foo
# 98| getBranch: [InClause] in ... then ...
-# 98| getPattern: [AlternativePattern] ... | ...
-# 98| getAlternative: [IntegerLiteral] 5
-# 98| getAlternative: [VariableReferencePattern] ^...
-# 98| getVariableAccess: [LocalVariableAccess] foo
-# 98| getAlternative: [LocalVariableAccess] var
-# 98| getAlternative: [StringLiteral] "string"
-# 98| getComponent: [StringTextComponent] string
+# 98| getPattern: [ConstantReadAccess] Bar
+# 98| getScopeExpr: [ConstantReadAccess] Foo
# 99| getBranch: [InClause] in ... then ...
-# 99| getPattern: [ConstantReadAccess] Foo
+# 99| getPattern: [ConstantReadAccess] Bar
+# 99| getScopeExpr: [ConstantReadAccess] Foo
# 100| getBranch: [InClause] in ... then ...
-# 100| getPattern: [ConstantReadAccess] Bar
-# 100| getScopeExpr: [ConstantReadAccess] Foo
+# 100| getPattern: [AlternativePattern] ... | ...
+# 100| getAlternative: [NilLiteral] nil
+# 100| getAlternative: [Self, SelfVariableAccess] self
+# 100| getAlternative: [BooleanLiteral] true
+# 100| getAlternative: [BooleanLiteral] false
+# 100| getAlternative: [LineLiteral] __LINE__
+# 100| getAlternative: [FileLiteral] __FILE__
+# 100| getAlternative: [EncodingLiteral] __ENCODING__
# 101| getBranch: [InClause] in ... then ...
-# 101| getPattern: [ConstantReadAccess] Bar
-# 101| getScopeExpr: [ConstantReadAccess] Foo
+# 101| getPattern: [Lambda] -> { ... }
+# 101| getParameter: [SimpleParameter] x
+# 101| getDefiningAccess: [LocalVariableAccess] x
+# 101| getStmt: [EqExpr] ... == ...
+# 101| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
+# 101| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 10
# 102| getBranch: [InClause] in ... then ...
-# 102| getPattern: [AlternativePattern] ... | ...
-# 102| getAlternative: [NilLiteral] nil
-# 102| getAlternative: [Self, SelfVariableAccess] self
-# 102| getAlternative: [BooleanLiteral] true
-# 102| getAlternative: [BooleanLiteral] false
-# 102| getAlternative: [LineLiteral] __LINE__
-# 102| getAlternative: [FileLiteral] __FILE__
-# 102| getAlternative: [EncodingLiteral] __ENCODING__
+# 102| getPattern: [SymbolLiteral] :foo
# 103| getBranch: [InClause] in ... then ...
-# 103| getPattern: [Lambda] -> { ... }
-# 103| getParameter: [SimpleParameter] x
-# 103| getDefiningAccess: [LocalVariableAccess] x
-# 103| getStmt: [EqExpr] ... == ...
-# 103| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] x
-# 103| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 10
+# 103| getPattern: [SymbolLiteral] :"foo bar"
+# 103| getComponent: [StringTextComponent] foo bar
# 104| getBranch: [InClause] in ... then ...
-# 104| getPattern: [SymbolLiteral] :foo
+# 104| getPattern: [AlternativePattern] ... | ...
+# 104| getAlternative: [UnaryMinusExpr] - ...
+# 104| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 5
+# 104| getAlternative: [UnaryPlusExpr] + ...
+# 104| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 10
# 105| getBranch: [InClause] in ... then ...
-# 105| getPattern: [SymbolLiteral] :"foo bar"
-# 105| getComponent: [StringTextComponent] foo bar
+# 105| getPattern: [ParenthesizedPattern] ( ... )
+# 105| getPattern: [RangeLiteral] _ .. _
+# 105| getBegin: [IntegerLiteral] 1
# 106| getBranch: [InClause] in ... then ...
-# 106| getPattern: [AlternativePattern] ... | ...
-# 106| getAlternative: [UnaryMinusExpr] - ...
-# 106| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 5
-# 106| getAlternative: [UnaryPlusExpr] + ...
-# 106| getAnOperand/getOperand/getReceiver: [IntegerLiteral] 10
+# 106| getPattern: [ParenthesizedPattern] ( ... )
+# 106| getPattern: [AlternativePattern] ... | ...
+# 106| getAlternative: [IntegerLiteral] 0
+# 106| getAlternative: [StringLiteral] ""
+# 106| getAlternative: [ArrayPattern] [ ..., * ]
+# 106| getAlternative: [HashPattern] { ..., ** }
# 107| getBranch: [InClause] in ... then ...
-# 107| getPattern: [ParenthesizedPattern] ( ... )
-# 107| getPattern: [RangeLiteral] _ .. _
-# 107| getBegin: [IntegerLiteral] 1
-# 108| getBranch: [InClause] in ... then ...
-# 108| getPattern: [ParenthesizedPattern] ( ... )
-# 108| getPattern: [AlternativePattern] ... | ...
-# 108| getAlternative: [IntegerLiteral] 0
-# 108| getAlternative: [StringLiteral] ""
-# 108| getAlternative: [ArrayPattern] [ ..., * ]
-# 108| getAlternative: [HashPattern] { ..., ** }
-# 113| getStmt: [CaseExpr] case ...
-# 113| getValue: [MethodCall] call to expr
-# 113| getReceiver: [Self, SelfVariableAccess] self
-# 114| getBranch: [InClause] in ... then ...
-# 114| getPattern: [ArrayPattern] [ ..., * ]
-# 115| getBranch: [InClause] in ... then ...
-# 115| getPattern: [ArrayPattern] [ ..., * ]
-# 115| getPrefixElement: [LocalVariableAccess] x
-# 116| getBranch: [InClause] in ... then ...
-# 116| getPattern: [ArrayPattern] [ ..., * ]
-# 116| getPrefixElement/getSuffixElement: [LocalVariableAccess] x
+# 107| getPattern: [LocalVariableAccess] var
+# 110| getStmt: [CaseExpr] case ...
+# 110| getValue: [MethodCall] call to expr
+# 110| getReceiver: [Self, SelfVariableAccess] self
+# 111| getBranch: [InClause] in ... then ...
+# 111| getPattern: [AlternativePattern] ... | ...
+# 111| getAlternative: [IntegerLiteral] 5
+# 111| getAlternative: [VariableReferencePattern] ^...
+# 111| getVariableAccess: [LocalVariableAccess] foo
+# 111| getAlternative: [StringLiteral] "string"
+# 111| getComponent: [StringTextComponent] string
+# 111| getAlternative: [LocalVariableAccess] var
+# 116| getStmt: [CaseExpr] case ...
+# 116| getValue: [MethodCall] call to expr
+# 116| getReceiver: [Self, SelfVariableAccess] self
# 117| getBranch: [InClause] in ... then ...
# 117| getPattern: [ArrayPattern] [ ..., * ]
-# 117| getClass: [ConstantReadAccess] Bar
-# 117| getScopeExpr: [ConstantReadAccess] Foo
# 118| getBranch: [InClause] in ... then ...
# 118| getPattern: [ArrayPattern] [ ..., * ]
-# 118| getClass: [ConstantReadAccess] Foo
+# 118| getPrefixElement: [LocalVariableAccess] x
# 119| getBranch: [InClause] in ... then ...
# 119| getPattern: [ArrayPattern] [ ..., * ]
-# 119| getClass: [ConstantReadAccess] Bar
+# 119| getPrefixElement/getSuffixElement: [LocalVariableAccess] x
# 120| getBranch: [InClause] in ... then ...
# 120| getPattern: [ArrayPattern] [ ..., * ]
# 120| getClass: [ConstantReadAccess] Bar
-# 120| getPrefixElement/getSuffixElement: [LocalVariableAccess] a
-# 120| getPrefixElement/getSuffixElement: [LocalVariableAccess] b
-# 120| getRestVariableAccess: [LocalVariableAccess] c
-# 120| getSuffixElement: [LocalVariableAccess] d
-# 120| getSuffixElement: [LocalVariableAccess] e
-# 125| getStmt: [CaseExpr] case ...
-# 125| getValue: [MethodCall] call to expr
-# 125| getReceiver: [Self, SelfVariableAccess] self
-# 126| getBranch: [InClause] in ... then ...
-# 126| getPattern: [FindPattern] [ *,...,* ]
-# 126| getElement: [LocalVariableAccess] x
-# 127| getBranch: [InClause] in ... then ...
-# 127| getPattern: [FindPattern] [ *,...,* ]
-# 127| getPrefixVariableAccess: [LocalVariableAccess] x
-# 127| getElement: [IntegerLiteral] 1
-# 127| getElement: [IntegerLiteral] 2
-# 127| getSuffixVariableAccess: [LocalVariableAccess] y
-# 128| getBranch: [InClause] in ... then ...
-# 128| getPattern: [FindPattern] [ *,...,* ]
-# 128| getClass: [ConstantReadAccess] Bar
-# 128| getScopeExpr: [ConstantReadAccess] Foo
-# 128| getElement: [IntegerLiteral] 1
+# 120| getScopeExpr: [ConstantReadAccess] Foo
+# 121| getBranch: [InClause] in ... then ...
+# 121| getPattern: [ArrayPattern] [ ..., * ]
+# 121| getClass: [ConstantReadAccess] Foo
+# 122| getBranch: [InClause] in ... then ...
+# 122| getPattern: [ArrayPattern] [ ..., * ]
+# 122| getClass: [ConstantReadAccess] Bar
+# 123| getBranch: [InClause] in ... then ...
+# 123| getPattern: [ArrayPattern] [ ..., * ]
+# 123| getClass: [ConstantReadAccess] Bar
+# 123| getPrefixElement/getSuffixElement: [LocalVariableAccess] a
+# 123| getPrefixElement/getSuffixElement: [LocalVariableAccess] b
+# 123| getRestVariableAccess: [LocalVariableAccess] c
+# 123| getSuffixElement: [LocalVariableAccess] d
+# 123| getSuffixElement: [LocalVariableAccess] e
+# 128| getStmt: [CaseExpr] case ...
+# 128| getValue: [MethodCall] call to expr
+# 128| getReceiver: [Self, SelfVariableAccess] self
# 129| getBranch: [InClause] in ... then ...
# 129| getPattern: [FindPattern] [ *,...,* ]
-# 129| getClass: [ConstantReadAccess] Foo
-# 129| getElement: [ConstantReadAccess] Bar
-# 134| getStmt: [CaseExpr] case ...
-# 134| getValue: [MethodCall] call to expr
-# 134| getReceiver: [Self, SelfVariableAccess] self
-# 135| getBranch: [InClause] in ... then ...
-# 135| getPattern: [HashPattern] { ..., ** }
-# 136| getBranch: [InClause] in ... then ...
-# 136| getPattern: [HashPattern] { ..., ** }
-# 136| getKey: [SymbolLiteral] :x
-# 137| getBranch: [InClause] in ... then ...
-# 137| getPattern: [HashPattern] { ..., ** }
-# 137| getClass: [ConstantReadAccess] Bar
-# 137| getScopeExpr: [ConstantReadAccess] Foo
-# 137| getKey: [SymbolLiteral] :x
-# 137| getValue: [IntegerLiteral] 1
+# 129| getElement: [LocalVariableAccess] x
+# 130| getBranch: [InClause] in ... then ...
+# 130| getPattern: [FindPattern] [ *,...,* ]
+# 130| getPrefixVariableAccess: [LocalVariableAccess] x
+# 130| getElement: [IntegerLiteral] 1
+# 130| getElement: [IntegerLiteral] 2
+# 130| getSuffixVariableAccess: [LocalVariableAccess] y
+# 131| getBranch: [InClause] in ... then ...
+# 131| getPattern: [FindPattern] [ *,...,* ]
+# 131| getClass: [ConstantReadAccess] Bar
+# 131| getScopeExpr: [ConstantReadAccess] Foo
+# 131| getElement: [IntegerLiteral] 1
+# 132| getBranch: [InClause] in ... then ...
+# 132| getPattern: [FindPattern] [ *,...,* ]
+# 132| getClass: [ConstantReadAccess] Foo
+# 132| getElement: [ConstantReadAccess] Bar
+# 137| getStmt: [CaseExpr] case ...
+# 137| getValue: [MethodCall] call to expr
+# 137| getReceiver: [Self, SelfVariableAccess] self
# 138| getBranch: [InClause] in ... then ...
# 138| getPattern: [HashPattern] { ..., ** }
-# 138| getClass: [ConstantReadAccess] Bar
-# 138| getScopeExpr: [ConstantReadAccess] Foo
-# 138| getKey: [SymbolLiteral] :x
-# 138| getValue: [IntegerLiteral] 1
-# 138| getKey: [SymbolLiteral] :a
-# 138| getRestVariableAccess: [LocalVariableAccess] rest
# 139| getBranch: [InClause] in ... then ...
# 139| getPattern: [HashPattern] { ..., ** }
-# 139| getClass: [ConstantReadAccess] Foo
-# 139| getKey: [SymbolLiteral] :y
+# 139| getKey: [SymbolLiteral] :x
# 140| getBranch: [InClause] in ... then ...
# 140| getPattern: [HashPattern] { ..., ** }
# 140| getClass: [ConstantReadAccess] Bar
+# 140| getScopeExpr: [ConstantReadAccess] Foo
+# 140| getKey: [SymbolLiteral] :x
+# 140| getValue: [IntegerLiteral] 1
# 141| getBranch: [InClause] in ... then ...
# 141| getPattern: [HashPattern] { ..., ** }
# 141| getClass: [ConstantReadAccess] Bar
-# 141| getKey: [SymbolLiteral] :a
+# 141| getScopeExpr: [ConstantReadAccess] Foo
+# 141| getKey: [SymbolLiteral] :x
# 141| getValue: [IntegerLiteral] 1
+# 141| getKey: [SymbolLiteral] :a
+# 141| getRestVariableAccess: [LocalVariableAccess] rest
+# 142| getBranch: [InClause] in ... then ...
+# 142| getPattern: [HashPattern] { ..., ** }
+# 142| getClass: [ConstantReadAccess] Foo
+# 142| getKey: [SymbolLiteral] :y
+# 143| getBranch: [InClause] in ... then ...
+# 143| getPattern: [HashPattern] { ..., ** }
+# 143| getClass: [ConstantReadAccess] Bar
+# 144| getBranch: [InClause] in ... then ...
+# 144| getPattern: [HashPattern] { ..., ** }
+# 144| getClass: [ConstantReadAccess] Bar
+# 144| getKey: [SymbolLiteral] :a
+# 144| getValue: [IntegerLiteral] 1
modules/classes.rb:
# 2| [Toplevel] classes.rb
# 3| getStmt: [ClassDeclaration] Foo
diff --git a/ruby/ql/test/library-tests/ast/AstDesugar.expected b/ruby/ql/test/library-tests/ast/AstDesugar.expected
index 6acafd116c5..4bc31acf32b 100644
--- a/ruby/ql/test/library-tests/ast/AstDesugar.expected
+++ b/ruby/ql/test/library-tests/ast/AstDesugar.expected
@@ -267,20 +267,20 @@ calls/calls.rb:
# 340| getArgument: [IntegerLiteral] 5
# 340| getArgument: [IntegerLiteral] 6
control/cases.rb:
-# 91| [ArrayLiteral] %w(...)
+# 90| [ArrayLiteral] %w(...)
+# 90| getDesugared: [MethodCall] call to []
+# 90| getReceiver: [ConstantReadAccess] Array
+# 90| getArgument: [StringLiteral] "foo"
+# 90| getComponent: [StringTextComponent] foo
+# 90| getArgument: [StringLiteral] "bar"
+# 90| getComponent: [StringTextComponent] bar
+# 91| [ArrayLiteral] %i(...)
# 91| getDesugared: [MethodCall] call to []
# 91| getReceiver: [ConstantReadAccess] Array
-# 91| getArgument: [StringLiteral] "foo"
+# 91| getArgument: [SymbolLiteral] :"foo"
# 91| getComponent: [StringTextComponent] foo
-# 91| getArgument: [StringLiteral] "bar"
+# 91| getArgument: [SymbolLiteral] :"bar"
# 91| getComponent: [StringTextComponent] bar
-# 92| [ArrayLiteral] %i(...)
-# 92| getDesugared: [MethodCall] call to []
-# 92| getReceiver: [ConstantReadAccess] Array
-# 92| getArgument: [SymbolLiteral] :"foo"
-# 92| getComponent: [StringTextComponent] foo
-# 92| getArgument: [SymbolLiteral] :"bar"
-# 92| getComponent: [StringTextComponent] bar
constants/constants.rb:
# 20| [ArrayLiteral] [...]
# 20| getDesugared: [MethodCall] call to []
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index e2a318c333c..57167453e7b 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -194,45 +194,46 @@
| control/cases.rb:84:7:84:8 | 42 | 42 |
| control/cases.rb:87:6:87:6 | 5 | 5 |
| control/cases.rb:88:7:88:9 | foo | 42 |
-| control/cases.rb:90:6:90:13 | "string" | string |
-| control/cases.rb:91:9:91:11 | "foo" | foo |
-| control/cases.rb:91:13:91:15 | "bar" | bar |
-| control/cases.rb:92:9:92:11 | :"foo" | foo |
-| control/cases.rb:92:13:92:15 | :"bar" | bar |
-| control/cases.rb:93:6:93:17 | /.*abc[0-9]/ | .*abc[0-9] |
-| control/cases.rb:94:6:94:6 | 5 | 5 |
-| control/cases.rb:94:11:94:12 | 10 | 10 |
-| control/cases.rb:95:9:95:10 | 10 | 10 |
+| control/cases.rb:89:6:89:13 | "string" | string |
+| control/cases.rb:90:9:90:11 | "foo" | foo |
+| control/cases.rb:90:13:90:15 | "bar" | bar |
+| control/cases.rb:91:9:91:11 | :"foo" | foo |
+| control/cases.rb:91:13:91:15 | :"bar" | bar |
+| control/cases.rb:92:6:92:17 | /.*abc[0-9]/ | .*abc[0-9] |
+| control/cases.rb:93:6:93:6 | 5 | 5 |
+| control/cases.rb:93:11:93:12 | 10 | 10 |
+| control/cases.rb:94:9:94:10 | 10 | 10 |
+| control/cases.rb:95:6:95:6 | 5 | 5 |
| control/cases.rb:96:6:96:6 | 5 | 5 |
-| control/cases.rb:97:6:97:6 | 5 | 5 |
-| control/cases.rb:98:6:98:6 | 5 | 5 |
-| control/cases.rb:98:23:98:30 | "string" | string |
-| control/cases.rb:102:6:102:8 | nil | nil |
-| control/cases.rb:102:19:102:22 | true | true |
-| control/cases.rb:102:26:102:30 | false | false |
-| control/cases.rb:102:34:102:41 | __LINE__ | 102 |
-| control/cases.rb:102:45:102:52 | __FILE__ | control/cases.rb |
-| control/cases.rb:102:56:102:67 | __ENCODING__ | UTF-8 |
-| control/cases.rb:103:18:103:19 | 10 | 10 |
-| control/cases.rb:104:6:104:9 | :foo | foo |
-| control/cases.rb:105:6:105:15 | :"foo bar" | foo bar |
-| control/cases.rb:106:7:106:7 | 5 | 5 |
-| control/cases.rb:106:12:106:13 | 10 | 10 |
-| control/cases.rb:107:7:107:7 | 1 | 1 |
-| control/cases.rb:108:7:108:7 | 0 | 0 |
-| control/cases.rb:108:11:108:12 | "" | |
-| control/cases.rb:127:11:127:11 | 1 | 1 |
-| control/cases.rb:127:14:127:14 | 2 | 2 |
-| control/cases.rb:128:18:128:18 | 1 | 1 |
-| control/cases.rb:136:7:136:7 | :x | x |
-| control/cases.rb:137:16:137:16 | :x | x |
-| control/cases.rb:137:18:137:18 | 1 | 1 |
-| control/cases.rb:138:16:138:16 | :x | x |
-| control/cases.rb:138:18:138:18 | 1 | 1 |
-| control/cases.rb:138:21:138:21 | :a | a |
-| control/cases.rb:139:11:139:11 | :y | y |
-| control/cases.rb:141:11:141:11 | :a | a |
-| control/cases.rb:141:14:141:14 | 1 | 1 |
+| control/cases.rb:100:6:100:8 | nil | nil |
+| control/cases.rb:100:19:100:22 | true | true |
+| control/cases.rb:100:26:100:30 | false | false |
+| control/cases.rb:100:34:100:41 | __LINE__ | 100 |
+| control/cases.rb:100:45:100:52 | __FILE__ | control/cases.rb |
+| control/cases.rb:100:56:100:67 | __ENCODING__ | UTF-8 |
+| control/cases.rb:101:18:101:19 | 10 | 10 |
+| control/cases.rb:102:6:102:9 | :foo | foo |
+| control/cases.rb:103:6:103:15 | :"foo bar" | foo bar |
+| control/cases.rb:104:7:104:7 | 5 | 5 |
+| control/cases.rb:104:12:104:13 | 10 | 10 |
+| control/cases.rb:105:7:105:7 | 1 | 1 |
+| control/cases.rb:106:7:106:7 | 0 | 0 |
+| control/cases.rb:106:11:106:12 | "" | |
+| control/cases.rb:111:6:111:6 | 5 | 5 |
+| control/cases.rb:111:11:111:13 | foo | 42 |
+| control/cases.rb:111:17:111:24 | "string" | string |
+| control/cases.rb:130:11:130:11 | 1 | 1 |
+| control/cases.rb:130:14:130:14 | 2 | 2 |
+| control/cases.rb:131:18:131:18 | 1 | 1 |
+| control/cases.rb:139:7:139:7 | :x | x |
+| control/cases.rb:140:16:140:16 | :x | x |
+| control/cases.rb:140:18:140:18 | 1 | 1 |
+| control/cases.rb:141:16:141:16 | :x | x |
+| control/cases.rb:141:18:141:18 | 1 | 1 |
+| control/cases.rb:141:21:141:21 | :a | a |
+| control/cases.rb:142:11:142:11 | :y | y |
+| control/cases.rb:144:11:144:11 | :a | a |
+| control/cases.rb:144:14:144:14 | 1 | 1 |
| control/conditionals.rb:2:5:2:5 | 0 | 0 |
| control/conditionals.rb:3:5:3:5 | 0 | 0 |
| control/conditionals.rb:4:5:4:5 | 0 | 0 |
diff --git a/ruby/ql/test/library-tests/ast/control/CaseExpr.expected b/ruby/ql/test/library-tests/ast/control/CaseExpr.expected
index bac914916a7..356b4ee3831 100644
--- a/ruby/ql/test/library-tests/ast/control/CaseExpr.expected
+++ b/ruby/ql/test/library-tests/ast/control/CaseExpr.expected
@@ -3,10 +3,11 @@ caseValues
| cases.rb:26:1:29:3 | case ... | cases.rb:26:6:26:9 | call to expr |
| cases.rb:31:1:37:3 | case ... | cases.rb:31:6:31:9 | call to expr |
| cases.rb:39:1:80:3 | case ... | cases.rb:39:6:39:9 | call to expr |
-| cases.rb:86:1:109:3 | case ... | cases.rb:86:6:86:9 | call to expr |
-| cases.rb:113:1:121:3 | case ... | cases.rb:113:6:113:9 | call to expr |
-| cases.rb:125:1:130:3 | case ... | cases.rb:125:6:125:9 | call to expr |
-| cases.rb:134:1:142:3 | case ... | cases.rb:134:6:134:9 | call to expr |
+| cases.rb:86:1:108:3 | case ... | cases.rb:86:6:86:9 | call to expr |
+| cases.rb:110:1:112:3 | case ... | cases.rb:110:6:110:9 | call to expr |
+| cases.rb:116:1:124:3 | case ... | cases.rb:116:6:116:9 | call to expr |
+| cases.rb:128:1:133:3 | case ... | cases.rb:128:6:128:9 | call to expr |
+| cases.rb:137:1:145:3 | case ... | cases.rb:137:6:137:9 | call to expr |
caseNoValues
| cases.rb:18:1:22:3 | case ... |
caseElseBranches
@@ -16,10 +17,11 @@ caseElseBranches
caseNoElseBranches
| cases.rb:18:1:22:3 | case ... |
| cases.rb:39:1:80:3 | case ... |
-| cases.rb:86:1:109:3 | case ... |
-| cases.rb:113:1:121:3 | case ... |
-| cases.rb:125:1:130:3 | case ... |
-| cases.rb:134:1:142:3 | case ... |
+| cases.rb:86:1:108:3 | case ... |
+| cases.rb:110:1:112:3 | case ... |
+| cases.rb:116:1:124:3 | case ... |
+| cases.rb:128:1:133:3 | case ... |
+| cases.rb:137:1:145:3 | case ... |
caseWhenBranches
| cases.rb:8:1:15:3 | case ... | cases.rb:9:1:10:7 | when ... | 0 | cases.rb:9:6:9:6 | b | cases.rb:9:7:10:7 | then ... |
| cases.rb:8:1:15:3 | case ... | cases.rb:11:1:12:7 | when ... | 0 | cases.rb:11:6:11:6 | c | cases.rb:11:10:12:7 | then ... |
@@ -79,43 +81,43 @@ caseAllBranches
| cases.rb:39:1:80:3 | case ... | 37 | cases.rb:77:3:77:13 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 38 | cases.rb:78:3:78:8 | in ... then ... |
| cases.rb:39:1:80:3 | case ... | 39 | cases.rb:79:3:79:8 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 0 | cases.rb:87:3:87:6 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 1 | cases.rb:88:3:88:9 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 2 | cases.rb:89:3:89:8 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 3 | cases.rb:90:3:90:13 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 4 | cases.rb:91:3:91:16 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 5 | cases.rb:92:3:92:16 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 6 | cases.rb:93:3:93:17 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 7 | cases.rb:94:3:94:12 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 8 | cases.rb:95:3:95:10 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 9 | cases.rb:96:3:96:9 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 10 | cases.rb:97:3:97:11 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 11 | cases.rb:98:3:98:30 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 12 | cases.rb:99:3:99:8 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 13 | cases.rb:100:3:100:13 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 14 | cases.rb:101:3:101:15 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 15 | cases.rb:102:3:102:67 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 16 | cases.rb:103:3:103:21 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 17 | cases.rb:104:3:104:9 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 18 | cases.rb:105:3:105:15 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 19 | cases.rb:106:3:106:13 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 20 | cases.rb:107:3:107:11 | in ... then ... |
-| cases.rb:86:1:109:3 | case ... | 21 | cases.rb:108:3:108:23 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 0 | cases.rb:114:3:114:8 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 1 | cases.rb:115:3:115:9 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 2 | cases.rb:116:3:116:11 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 3 | cases.rb:117:3:117:16 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 4 | cases.rb:118:3:118:11 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 5 | cases.rb:119:3:119:12 | in ... then ... |
-| cases.rb:113:1:121:3 | case ... | 6 | cases.rb:120:3:120:25 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 0 | cases.rb:126:3:126:15 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 1 | cases.rb:127:3:127:20 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 2 | cases.rb:128:3:128:23 | in ... then ... |
-| cases.rb:125:1:130:3 | case ... | 3 | cases.rb:129:3:129:20 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 0 | cases.rb:135:3:135:8 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 1 | cases.rb:136:3:136:10 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 2 | cases.rb:137:3:137:21 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 3 | cases.rb:138:3:138:33 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 4 | cases.rb:139:3:139:14 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 5 | cases.rb:140:3:140:15 | in ... then ... |
-| cases.rb:134:1:142:3 | case ... | 6 | cases.rb:141:3:141:23 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 0 | cases.rb:87:3:87:6 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 1 | cases.rb:88:3:88:9 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 2 | cases.rb:89:3:89:13 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 3 | cases.rb:90:3:90:16 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 4 | cases.rb:91:3:91:16 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 5 | cases.rb:92:3:92:17 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 6 | cases.rb:93:3:93:12 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 7 | cases.rb:94:3:94:10 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 8 | cases.rb:95:3:95:9 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 9 | cases.rb:96:3:96:11 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 10 | cases.rb:97:3:97:8 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 11 | cases.rb:98:3:98:13 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 12 | cases.rb:99:3:99:15 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 13 | cases.rb:100:3:100:67 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 14 | cases.rb:101:3:101:21 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 15 | cases.rb:102:3:102:9 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 16 | cases.rb:103:3:103:15 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 17 | cases.rb:104:3:104:13 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 18 | cases.rb:105:3:105:11 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 19 | cases.rb:106:3:106:23 | in ... then ... |
+| cases.rb:86:1:108:3 | case ... | 20 | cases.rb:107:3:107:8 | in ... then ... |
+| cases.rb:110:1:112:3 | case ... | 0 | cases.rb:111:3:111:30 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 0 | cases.rb:117:3:117:8 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 1 | cases.rb:118:3:118:9 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 2 | cases.rb:119:3:119:11 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 3 | cases.rb:120:3:120:16 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 4 | cases.rb:121:3:121:11 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 5 | cases.rb:122:3:122:12 | in ... then ... |
+| cases.rb:116:1:124:3 | case ... | 6 | cases.rb:123:3:123:25 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 0 | cases.rb:129:3:129:15 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 1 | cases.rb:130:3:130:20 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 2 | cases.rb:131:3:131:23 | in ... then ... |
+| cases.rb:128:1:133:3 | case ... | 3 | cases.rb:132:3:132:20 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 0 | cases.rb:138:3:138:8 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 1 | cases.rb:139:3:139:10 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 2 | cases.rb:140:3:140:21 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 3 | cases.rb:141:3:141:33 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 4 | cases.rb:142:3:142:14 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 5 | cases.rb:143:3:143:15 | in ... then ... |
+| cases.rb:137:1:145:3 | case ... | 6 | cases.rb:144:3:144:23 | in ... then ... |
diff --git a/ruby/ql/test/library-tests/ast/control/ControlExpr.expected b/ruby/ql/test/library-tests/ast/control/ControlExpr.expected
index 9226236873a..953bc10600d 100644
--- a/ruby/ql/test/library-tests/ast/control/ControlExpr.expected
+++ b/ruby/ql/test/library-tests/ast/control/ControlExpr.expected
@@ -3,10 +3,11 @@
| cases.rb:26:1:29:3 | case ... | CaseExpr |
| cases.rb:31:1:37:3 | case ... | CaseExpr |
| cases.rb:39:1:80:3 | case ... | CaseExpr |
-| cases.rb:86:1:109:3 | case ... | CaseExpr |
-| cases.rb:113:1:121:3 | case ... | CaseExpr |
-| cases.rb:125:1:130:3 | case ... | CaseExpr |
-| cases.rb:134:1:142:3 | case ... | CaseExpr |
+| cases.rb:86:1:108:3 | case ... | CaseExpr |
+| cases.rb:110:1:112:3 | case ... | CaseExpr |
+| cases.rb:116:1:124:3 | case ... | CaseExpr |
+| cases.rb:128:1:133:3 | case ... | CaseExpr |
+| cases.rb:137:1:145:3 | case ... | CaseExpr |
| conditionals.rb:10:1:12:3 | if ... | IfExpr |
| conditionals.rb:15:1:19:3 | if ... | IfExpr |
| conditionals.rb:22:1:30:3 | if ... | IfExpr |
diff --git a/ruby/ql/test/library-tests/ast/control/cases.rb b/ruby/ql/test/library-tests/ast/control/cases.rb
index 07bc117b7cb..2c92839d736 100644
--- a/ruby/ql/test/library-tests/ast/control/cases.rb
+++ b/ruby/ql/test/library-tests/ast/control/cases.rb
@@ -86,7 +86,6 @@ foo = 42
case expr
in 5
in ^foo
- in var
in "string"
in %w(foo bar)
in %i(foo bar)
@@ -95,7 +94,6 @@ case expr
in .. 10
in 5 ..
in 5 => x
- in 5 | ^foo | var | "string"
in Foo
in Foo::Bar
in ::Foo::Bar
@@ -106,6 +104,11 @@ case expr
in -5 | +10
in (1 ..)
in (0 | "" | [] | {})
+ in var
+end
+
+case expr
+ in 5 | ^foo | "string" | var
end
# array patterns
From 322f8356dd2f960ca46de880b351e8f143de9bfc Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 10:59:53 +0100
Subject: [PATCH 006/196] Ruby: Include `StringComponent`s in the CFG
---
.../internal/ControlFlowGraphImpl.qll | 4 +
.../controlflow/graph/Cfg.expected | 747 ++++++++++++++----
2 files changed, 608 insertions(+), 143 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
index 1576ff51938..22615dc2575 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
@@ -1350,6 +1350,10 @@ module Trees {
final override ControlFlowTree getChildElement(int i) { result = this.getComponent(i) }
}
+ private class StringComponentComponentTree extends LeafTree, StringComponent {
+ StringComponentComponentTree() { not this instanceof StringInterpolationComponent }
+ }
+
private class ToplevelTree extends BodyStmtTree, Toplevel {
final override AstNode getBodyChild(int i, boolean rescuable) {
result = this.getBeginBlock(i) and rescuable = true
diff --git a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected
index a6f06fc0f71..c4e4780e1ca 100644
--- a/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected
+++ b/ruby/ql/test/library-tests/controlflow/graph/Cfg.expected
@@ -103,10 +103,10 @@ break_ensure.rb:
#-----| -> [ensure: raise] then ...
# 9| self
-#-----| -> "elements nil"
+#-----| -> elements nil
# 9| [ensure: raise] self
-#-----| -> [ensure: raise] "elements nil"
+#-----| -> [ensure: raise] elements nil
# 9| "elements nil"
#-----| -> call to puts
@@ -114,6 +114,12 @@ break_ensure.rb:
# 9| [ensure: raise] "elements nil"
#-----| -> [ensure: raise] call to puts
+# 9| elements nil
+#-----| -> "elements nil"
+
+# 9| [ensure: raise] elements nil
+#-----| -> [ensure: raise] "elements nil"
+
# 13| enter m2
#-----| -> x
@@ -222,13 +228,13 @@ break_ensure.rb:
#-----| -> [ensure: raise] then ...
# 21| self
-#-----| -> "y nil"
+#-----| -> y nil
# 21| [ensure: break] self
-#-----| -> [ensure: break] "y nil"
+#-----| -> [ensure: break] y nil
# 21| [ensure: raise] self
-#-----| -> [ensure: raise] "y nil"
+#-----| -> [ensure: raise] y nil
# 21| "y nil"
#-----| -> call to puts
@@ -239,6 +245,15 @@ break_ensure.rb:
# 21| [ensure: raise] "y nil"
#-----| -> [ensure: raise] call to puts
+# 21| y nil
+#-----| -> "y nil"
+
+# 21| [ensure: break] y nil
+#-----| -> [ensure: break] "y nil"
+
+# 21| [ensure: raise] y nil
+#-----| -> [ensure: raise] "y nil"
+
# 27| enter m3
#-----| -> x
@@ -382,11 +397,14 @@ break_ensure.rb:
#-----| -> exit m3 (normal)
# 41| self
-#-----| -> "Done"
+#-----| -> Done
# 41| "Done"
#-----| -> call to puts
+# 41| Done
+#-----| -> "Done"
+
# 44| enter m4
#-----| -> x
@@ -543,11 +561,14 @@ case.rb:
#-----| -> then ...
# 3| self
-#-----| -> "x2"
+#-----| -> x2
# 3| "x2"
#-----| -> call to puts
+# 3| x2
+#-----| -> "x2"
+
# 4| when ...
#-----| -> 2
@@ -562,11 +583,14 @@ case.rb:
#-----| -> then ...
# 4| self
-#-----| -> "2"
+#-----| -> 2
# 4| "2"
#-----| -> call to puts
+# 4| 2
+#-----| -> "2"
+
# 8| enter case_match
#-----| -> value
@@ -745,11 +769,14 @@ case.rb:
#-----| raise -> exit -> { ... } (abnormal)
# 28| self
-#-----| -> "oops"
+#-----| -> oops
# 28| "oops"
#-----| -> call to raise
+# 28| oops
+#-----| -> "oops"
+
# 32| enter case_match_array
#-----| -> value
@@ -1056,12 +1083,15 @@ case.rb:
#-----| no-match -> in ... then ...
# 75| in ... then ...
-#-----| -> "string"
+#-----| -> string
# 75| "string"
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 75| string
+#-----| -> "string"
+
# 76| in ... then ...
#-----| -> Array
@@ -1070,14 +1100,20 @@ case.rb:
#-----| no-match -> in ... then ...
# 76| Array
-#-----| -> "foo"
+#-----| -> foo
# 76| "foo"
-#-----| -> "bar"
+#-----| -> bar
+
+# 76| foo
+#-----| -> "foo"
# 76| "bar"
#-----| -> call to []
+# 76| bar
+#-----| -> "bar"
+
# 77| in ... then ...
#-----| -> Array
@@ -1086,21 +1122,30 @@ case.rb:
#-----| no-match -> in ... then ...
# 77| Array
-#-----| -> :"foo"
+#-----| -> foo
# 77| :"foo"
-#-----| -> :"bar"
+#-----| -> bar
+
+# 77| foo
+#-----| -> :"foo"
# 77| :"bar"
#-----| -> call to []
+# 77| bar
+#-----| -> :"bar"
+
# 78| in ... then ...
-#-----| -> /.*abc[0-9]/
+#-----| -> .*abc[0-9]
# 78| /.*abc[0-9]/
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 78| .*abc[0-9]
+#-----| -> /.*abc[0-9]/
+
# 79| in ... then ...
#-----| -> 5
@@ -1162,12 +1207,15 @@ case.rb:
# 83| foo
#-----| match -> case ...
-#-----| no-match -> "string"
+#-----| no-match -> string
# 83| "string"
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 83| string
+#-----| -> "string"
+
# 84| in ... then ...
#-----| -> Foo
@@ -1213,12 +1261,15 @@ case.rb:
#-----| no-match -> in ... then ...
# 87| in ... then ...
-#-----| -> :"foo bar"
+#-----| -> foo bar
# 87| :"foo bar"
#-----| match -> case ...
#-----| no-match -> in ... then ...
+# 87| foo bar
+#-----| -> :"foo bar"
+
# 88| in ... then ...
#-----| -> ... | ...
@@ -1372,29 +1423,38 @@ cfg.html.erb:
#-----| -> self
# 6| self
-#-----| -> "application"
+#-----| -> application
# 6| "application"
#-----| -> :media
+# 6| application
+#-----| -> "application"
+
# 6| Pair
#-----| -> call to stylesheet_link_tag
# 6| :media
-#-----| -> "all"
+#-----| -> all
# 6| "all"
#-----| -> Pair
+# 6| all
+#-----| -> "all"
+
# 12| call to link_to
#-----| -> self
# 12| self
-#-----| -> "A"
+#-----| -> A
# 12| "A"
#-----| -> self
+# 12| A
+#-----| -> "A"
+
# 12| call to a
#-----| -> :id
@@ -1402,7 +1462,7 @@ cfg.html.erb:
#-----| -> call to a
# 12| :id
-#-----| -> "a"
+#-----| -> a
# 12| Pair
#-----| -> call to link_to
@@ -1410,15 +1470,21 @@ cfg.html.erb:
# 12| "a"
#-----| -> Pair
+# 12| a
+#-----| -> "a"
+
# 15| call to link_to
#-----| -> self
# 15| self
-#-----| -> "B"
+#-----| -> B
# 15| "B"
#-----| -> self
+# 15| B
+#-----| -> "B"
+
# 15| call to a
#-----| -> call to link_to
@@ -1429,11 +1495,14 @@ cfg.html.erb:
#-----| -> self
# 16| self
-#-----| -> "C"
+#-----| -> C
# 16| "C"
#-----| -> self
+# 16| C
+#-----| -> "C"
+
# 16| call to b
#-----| -> call to link_to
@@ -1457,11 +1526,14 @@ cfg.html.erb:
#-----| -> then ...
# 19| self
-#-----| -> "D"
+#-----| -> D
# 19| "D"
#-----| -> self
+# 19| D
+#-----| -> "D"
+
# 19| call to d
#-----| -> call to link_to
@@ -1475,11 +1547,14 @@ cfg.html.erb:
#-----| -> else ...
# 21| self
-#-----| -> "E"
+#-----| -> E
# 21| "E"
#-----| -> self
+# 21| E
+#-----| -> "E"
+
# 21| call to e
#-----| -> call to link_to
@@ -1552,10 +1627,13 @@ cfg.rb:
#-----| -> Array
# 7| Array
-#-----| -> b
+#-----| -> one
# 7| :"one#{...}"
-#-----| -> :"another"
+#-----| -> another
+
+# 7| one
+#-----| -> b
# 7| #{...}
#-----| -> :"one#{...}"
@@ -1566,14 +1644,20 @@ cfg.rb:
# 7| :"another"
#-----| -> call to []
+# 7| another
+#-----| -> :"another"
+
# 9| call to []
#-----| -> self
# 9| Array
-#-----| -> b
+#-----| -> one
# 9| "one#{...}"
-#-----| -> "another"
+#-----| -> another
+
+# 9| one
+#-----| -> b
# 9| #{...}
#-----| -> "one#{...}"
@@ -1584,6 +1668,9 @@ cfg.rb:
# 9| "another"
#-----| -> call to []
+# 9| another
+#-----| -> "another"
+
# 12| call to puts
#-----| -> END { ... }
@@ -1600,11 +1687,14 @@ cfg.rb:
#-----| -> BEGIN { ... }
# 16| self
-#-----| -> "hello"
+#-----| -> hello
# 16| "hello"
#-----| -> call to puts
+# 16| hello
+#-----| -> "hello"
+
# 19| END { ... }
#-----| -> 41
@@ -1731,11 +1821,14 @@ cfg.rb:
#-----| -> then ...
# 42| self
-#-----| -> "one"
+#-----| -> one
# 42| "one"
#-----| -> call to puts
+# 42| one
+#-----| -> "one"
+
# 43| when ...
#-----| -> 2
@@ -1758,11 +1851,14 @@ cfg.rb:
#-----| -> then ...
# 43| self
-#-----| -> "some"
+#-----| -> some
# 43| "some"
#-----| -> call to puts
+# 43| some
+#-----| -> "some"
+
# 44| else ...
#-----| -> case ...
@@ -1770,11 +1866,14 @@ cfg.rb:
#-----| -> else ...
# 44| self
-#-----| -> "many"
+#-----| -> many
# 44| "many"
#-----| -> call to puts
+# 44| many
+#-----| -> "many"
+
# 47| case ...
#-----| -> chained
@@ -1798,11 +1897,14 @@ cfg.rb:
#-----| -> then ...
# 48| self
-#-----| -> "one"
+#-----| -> one
# 48| "one"
#-----| -> call to puts
+# 48| one
+#-----| -> "one"
+
# 49| when ...
#-----| -> b
@@ -1833,16 +1935,19 @@ cfg.rb:
#-----| -> then ...
# 49| self
-#-----| -> "some"
+#-----| -> some
# 49| "some"
#-----| -> call to puts
+# 49| some
+#-----| -> "some"
+
# 52| ... = ...
#-----| -> character
# 52| chained
-#-----| -> "a"
+#-----| -> a
# 52| "a"
#-----| -> chained
@@ -1850,8 +1955,11 @@ cfg.rb:
# 52| "..." "..."
#-----| -> ... = ...
+# 52| a
+#-----| -> "a"
+
# 52| "#{...}"
-#-----| -> "string"
+#-----| -> string
# 52| #{...}
#-----| -> "#{...}"
@@ -1862,6 +1970,9 @@ cfg.rb:
# 52| "string"
#-----| -> "..." "..."
+# 52| string
+#-----| -> "string"
+
# 54| ... = ...
#-----| -> Silly
@@ -1893,8 +2004,8 @@ cfg.rb:
#-----| -> self
# 60| ... < ...
-#-----| true -> "hello"
-#-----| false -> "bye"
+#-----| true -> hello
+#-----| false -> bye
# 60| ... ? ... : ...
#-----| -> ... = ...
@@ -1911,18 +2022,27 @@ cfg.rb:
# 60| "hello"
#-----| -> ... ? ... : ...
+# 60| hello
+#-----| -> "hello"
+
# 60| "bye"
#-----| -> ... ? ... : ...
+# 60| bye
+#-----| -> "bye"
+
# 61| ... = ...
#-----| -> __synth__0
# 61| C
-#-----| -> "constant"
+#-----| -> constant
# 61| "constant"
#-----| -> ... = ...
+# 61| constant
+#-----| -> "constant"
+
# 62| ...
#-----| -> pattern
@@ -2111,11 +2231,14 @@ cfg.rb:
#-----| -> exit print (normal)
# 70| self
-#-----| -> "silly"
+#-----| -> silly
# 70| "silly"
#-----| -> call to puts
+# 70| silly
+#-----| -> "silly"
+
# 74| ... = ...
#-----| -> x
@@ -2179,11 +2302,14 @@ cfg.rb:
#-----| -> else ...
# 83| self
-#-----| -> "ok"
+#-----| -> ok
# 83| "ok"
#-----| -> call to puts
+# 83| ok
+#-----| -> "ok"
+
# 84| ensure ...
#-----| -> escape
@@ -2191,26 +2317,35 @@ cfg.rb:
#-----| -> ensure ...
# 85| self
-#-----| -> "end"
+#-----| -> end
# 85| "end"
#-----| -> call to puts
+# 85| end
+#-----| -> "end"
+
# 88| ... = ...
#-----| -> Array
# 88| escape
-#-----| -> x
+#-----| -> \u1234
# 88| "\u1234#{...}\n"
#-----| -> ... = ...
+# 88| \u1234
+#-----| -> x
+
# 88| #{...}
-#-----| -> "\u1234#{...}\n"
+#-----| -> \n
# 88| x
#-----| -> #{...}
+# 88| \n
+#-----| -> "\u1234#{...}\n"
+
# 90| enter { ... }
#-----| -> __synth__0__1
@@ -2290,31 +2425,43 @@ cfg.rb:
#-----| -> map2
# 97| map1
-#-----| -> "a"
+#-----| -> a
# 97| {...}
#-----| -> ... = ...
# 97| Pair
-#-----| -> "c"
+#-----| -> c
# 97| "a"
-#-----| -> "b"
+#-----| -> b
+
+# 97| a
+#-----| -> "a"
# 97| "b"
#-----| -> Pair
+# 97| b
+#-----| -> "b"
+
# 97| Pair
#-----| -> :e
# 97| "c"
-#-----| -> "d"
+#-----| -> d
+
+# 97| c
+#-----| -> "c"
# 97| "d"
#-----| -> Pair
+# 97| d
+#-----| -> "d"
+
# 97| :e
-#-----| -> "f"
+#-----| -> f
# 97| Pair
#-----| -> {...}
@@ -2322,6 +2469,9 @@ cfg.rb:
# 97| "f"
#-----| -> Pair
+# 97| f
+#-----| -> "f"
+
# 98| ... = ...
#-----| -> parameters
@@ -2332,7 +2482,7 @@ cfg.rb:
#-----| -> ... = ...
# 98| ** ...
-#-----| -> "x"
+#-----| -> x
# 98| map1
#-----| -> ** ...
@@ -2341,11 +2491,17 @@ cfg.rb:
#-----| -> map1
# 98| "x"
-#-----| -> "y"
+#-----| -> y
+
+# 98| x
+#-----| -> "x"
# 98| "y"
#-----| -> Pair
+# 98| y
+#-----| -> "y"
+
# 98| ** ...
#-----| -> {...}
@@ -2401,25 +2557,32 @@ cfg.rb:
#-----| -> table
# 106| type
-#-----| -> "healthy"
+#-----| -> healthy
# 106| "healthy"
#-----| -> ... = ...
+# 106| healthy
+#-----| -> "healthy"
+
# 107| ... = ...
#-----| -> self
# 107| table
-#-----| -> "food"
+#-----| -> food
# 107| "food"
#-----| -> ... = ...
+# 107| food
+#-----| -> "food"
+
# 108| call to puts
#-----| -> b
# 108| self
-#-----| -> table
+#-----| ->
+#-----| SELECT * FROM
# 108| ( ... )
#-----| -> call to puts
@@ -2427,18 +2590,44 @@ cfg.rb:
# 108| < ( ... )
+# 108|
+# 108| SELECT * FROM
+#-----| -> table
+
# 109| #{...}
-#-----| -> type
+#-----| ->
# 109| table
#-----| -> #{...}
+# 109|
+#-----| -> \n
+
+# 109| \n
+#-----| ->
+#-----| WHERE
+
+# 109|
+# 109| WHERE
+#-----| -> type
+
# 110| #{...}
-#-----| -> < = true
# 110| type
#-----| -> #{...}
+# 110| = true
+#-----| -> \n
+
+# 110| \n
+#-----| ->
+#-----|
+
+# 110|
+# 110|
+#-----| -> < ... if ...
@@ -2446,11 +2635,14 @@ cfg.rb:
#-----| -> C
# 113| self
-#-----| -> "hi"
+#-----| -> hi
# 113| "hi"
#-----| -> call to puts
+# 113| hi
+#-----| -> "hi"
+
# 113| ... > ...
#-----| false -> ... if ...
#-----| true -> self
@@ -2620,17 +2812,29 @@ cfg.rb:
#-----| -> Constant
# 129| regex
-#-----| -> range
+#-----| -> hello
# 129| /hello\s+[#{...}]/
#-----| -> ... = ...
+# 129| hello
+#-----| -> \s
+
+# 129| \s
+#-----| -> +[
+
+# 129| +[
+#-----| -> range
+
# 129| #{...}
-#-----| -> /hello\s+[#{...}]/
+#-----| -> ]
# 129| range
#-----| -> #{...}
+# 129| ]
+#-----| -> /hello\s+[#{...}]/
+
# 130| ... = ...
#-----| -> EmptyClass
@@ -2663,11 +2867,14 @@ cfg.rb:
#-----| -> ... rescue ...
# 136| self
-#-----| -> "div by zero"
+#-----| -> div by zero
# 136| "div by zero"
#-----| -> call to puts
+# 136| div by zero
+#-----| -> "div by zero"
+
# 138| ...
#-----| -> M
@@ -2770,11 +2977,14 @@ cfg.rb:
#-----| -> self
# 146| self
-#-----| -> "singleton"
+#-----| -> singleton
# 146| "singleton"
#-----| -> call to puts
+# 146| singleton
+#-----| -> "singleton"
+
# 147| call to puts
#-----| -> exit print (normal)
@@ -2867,13 +3077,16 @@ cfg.rb:
#-----| -> symbol
# 160| scriptfile
-#-----| -> self
+#-----| -> cat "
# 160| `cat "#{...}"`
#-----| -> ... = ...
+# 160| cat "
+#-----| -> self
+
# 160| #{...}
-#-----| -> `cat "#{...}"`
+#-----| -> "
# 160| call to __FILE__
#-----| -> #{...}
@@ -2881,6 +3094,9 @@ cfg.rb:
# 160| self
#-----| -> call to __FILE__
+# 160| "
+#-----| -> `cat "#{...}"`
+
# 162| ... = ...
#-----| -> delimited_symbol
@@ -2894,11 +3110,14 @@ cfg.rb:
#-----| -> x
# 164| delimited_symbol
-#-----| -> 12
+#-----| -> goodbye-
# 164| :"goodbye-#{...}"
#-----| -> ... = ...
+# 164| goodbye-
+#-----| -> 12
+
# 164| #{...}
#-----| -> :"goodbye-#{...}"
@@ -2970,11 +3189,14 @@ cfg.rb:
#-----| -> then ...
# 172| self
-#-----| -> "hi"
+#-----| -> hi
# 172| "hi"
#-----| -> call to puts
+# 172| hi
+#-----| -> "hi"
+
# 172| else ...
#-----| -> unless ...
@@ -2982,11 +3204,14 @@ cfg.rb:
#-----| -> else ...
# 172| self
-#-----| -> "bye"
+#-----| -> bye
# 172| "bye"
#-----| -> call to puts
+# 172| bye
+#-----| -> "bye"
+
# 174| call to puts
#-----| -> ... unless ...
@@ -2994,11 +3219,14 @@ cfg.rb:
#-----| -> x
# 174| self
-#-----| -> "hi"
+#-----| -> hi
# 174| "hi"
#-----| -> call to puts
+# 174| hi
+#-----| -> "hi"
+
# 174| ... == ...
#-----| true -> ... unless ...
#-----| false -> self
@@ -3044,11 +3272,14 @@ cfg.rb:
#-----| -> do ...
# 176| self
-#-----| -> "hello"
+#-----| -> hello
# 176| "hello"
#-----| -> call to puts
+# 176| hello
+#-----| -> "hello"
+
# 178| ... = ...
#-----| -> i
@@ -3068,11 +3299,14 @@ cfg.rb:
#-----| -> i
# 179| self
-#-----| -> "hello"
+#-----| -> hello
# 179| "hello"
#-----| -> call to puts
+# 179| hello
+#-----| -> "hello"
+
# 179| i
#-----| -> i
@@ -3173,11 +3407,14 @@ cfg.rb:
#-----| -> i
# 188| self
-#-----| -> "hello"
+#-----| -> hello
# 188| "hello"
#-----| -> call to puts
+# 188| hello
+#-----| -> "hello"
+
# 188| i
#-----| -> i
@@ -3920,11 +4157,14 @@ exit.rb:
#-----| -> exit m1 (normal)
# 5| self
-#-----| -> "x <= 2"
+#-----| -> x <= 2
# 5| "x <= 2"
#-----| -> call to puts
+# 5| x <= 2
+#-----| -> "x <= 2"
+
# 8| enter m2
#-----| -> x
@@ -3959,20 +4199,26 @@ exit.rb:
#-----| exit -> exit m2 (abnormal)
# 10| self
-#-----| -> "abort!"
+#-----| -> abort!
# 10| "abort!"
#-----| -> call to abort
+# 10| abort!
+#-----| -> "abort!"
+
# 12| call to puts
#-----| -> exit m2 (normal)
# 12| self
-#-----| -> "x <= 2"
+#-----| -> x <= 2
# 12| "x <= 2"
#-----| -> call to puts
+# 12| x <= 2
+#-----| -> "x <= 2"
+
heredoc.rb:
# 1| enter double_heredoc
#-----| -> self
@@ -3997,14 +4243,28 @@ heredoc.rb:
#-----| -> exit double_heredoc (normal)
# 2| self
-#-----| -> <
+#-----| hello
+#-----|
# 2| < <
+#-----| world
+#-----|
# 2| < call to puts
+# 2|
+# 2| hello
+# 2|
+#-----| -> < < x
@@ -4048,11 +4308,14 @@ ifs.rb:
#-----| -> then ...
# 3| self
-#-----| -> "x is greater than 2"
+#-----| -> x is greater than 2
# 3| "x is greater than 2"
#-----| -> call to puts
+# 3| x is greater than 2
+#-----| -> "x is greater than 2"
+
# 4| elsif ...
#-----| -> if ...
@@ -4117,11 +4380,14 @@ ifs.rb:
#-----| -> then ...
# 5| self
-#-----| -> "x is 1"
+#-----| -> x is 1
# 5| "x is 1"
#-----| -> call to puts
+# 5| x is 1
+#-----| -> "x is 1"
+
# 6| else ...
#-----| -> elsif ...
@@ -4129,11 +4395,14 @@ ifs.rb:
#-----| -> else ...
# 7| self
-#-----| -> "I can't guess the number"
+#-----| -> I can't guess the number
# 7| "I can't guess the number"
#-----| -> call to puts
+# 7| I can't guess the number
+#-----| -> "I can't guess the number"
+
# 11| enter m2
#-----| -> b
@@ -4273,10 +4542,10 @@ ifs.rb:
#-----| return -> exit m4 (normal)
# 29| [false] ( ... )
-#-----| false -> "!b2 || !b3"
+#-----| false -> !b2 || !b3
# 29| [true] ( ... )
-#-----| true -> "b2 || b3"
+#-----| true -> b2 || b3
# 29| ... ? ... : ...
#-----| -> return
@@ -4302,9 +4571,15 @@ ifs.rb:
# 29| "b2 || b3"
#-----| -> ... ? ... : ...
+# 29| b2 || b3
+#-----| -> "b2 || b3"
+
# 29| "!b2 || !b3"
#-----| -> ... ? ... : ...
+# 29| !b2 || !b3
+#-----| -> "!b2 || !b3"
+
# 32| enter m5
#-----| -> b1
@@ -4335,10 +4610,10 @@ ifs.rb:
#-----| -> exit m5 (normal)
# 33| [false] ( ... )
-#-----| false -> "!b2 || !b4 || !b5"
+#-----| false -> !b2 || !b4 || !b5
# 33| [true] ( ... )
-#-----| true -> "b2 || b4 || b5"
+#-----| true -> b2 || b4 || b5
# 33| [false] if ...
#-----| false -> [false] ( ... )
@@ -4396,12 +4671,18 @@ ifs.rb:
# 33| "b2 || b4 || b5"
#-----| -> then ...
+# 33| b2 || b4 || b5
+#-----| -> "b2 || b4 || b5"
+
# 33| else ...
#-----| -> if ...
# 33| "!b2 || !b4 || !b5"
#-----| -> else ...
+# 33| !b2 || !b4 || !b5
+#-----| -> "!b2 || !b4 || !b5"
+
# 36| enter conditional_method_def
#-----| -> self
@@ -4420,11 +4701,14 @@ ifs.rb:
#-----| -> exit conditional_method_def (normal)
# 37| self
-#-----| -> "bla"
+#-----| -> bla
# 37| "bla"
#-----| -> call to puts
+# 37| bla
+#-----| -> "bla"
+
# 38| ... == ...
#-----| false -> conditional_method_def
#-----| true -> ... unless ...
@@ -4483,11 +4767,14 @@ ifs.rb:
#-----| -> then ...
# 48| self
-#-----| -> "true"
+#-----| -> true
# 48| "true"
#-----| -> call to puts
+# 48| true
+#-----| -> "true"
+
# 49| else ...
#-----| -> if ...
@@ -4495,11 +4782,14 @@ ifs.rb:
#-----| -> exit empty_else (normal)
# 51| self
-#-----| -> "done"
+#-----| -> done
# 51| "done"
#-----| -> call to puts
+# 51| done
+#-----| -> "done"
+
# 54| enter disjunct
#-----| -> b1
@@ -4547,11 +4837,14 @@ ifs.rb:
#-----| -> then ...
# 56| self
-#-----| -> "b1 or b2"
+#-----| -> b1 or b2
# 56| "b1 or b2"
#-----| -> call to puts
+# 56| b1 or b2
+#-----| -> "b1 or b2"
+
loops.rb:
# 1| enter m1
#-----| -> x
@@ -4721,20 +5014,26 @@ loops.rb:
#-----| -> do ...
# 19| self
-#-----| -> "Iter"
+#-----| -> Iter
# 19| "Iter"
#-----| -> call to puts
+# 19| Iter
+#-----| -> "Iter"
+
# 21| call to puts
#-----| -> exit m2 (normal)
# 21| self
-#-----| -> "Done"
+#-----| -> Done
# 21| "Done"
#-----| -> call to puts
+# 21| Done
+#-----| -> "Done"
+
# 24| enter m3
#-----| -> Array
@@ -4875,20 +5174,26 @@ raise.rb:
#-----| raise -> exit m1 (abnormal)
# 9| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 9| "x > 2"
#-----| -> call to raise
+# 9| x > 2
+#-----| -> "x > 2"
+
# 11| call to puts
#-----| -> exit m1 (normal)
# 11| self
-#-----| -> "x <= 2"
+#-----| -> x <= 2
# 11| "x <= 2"
#-----| -> call to puts
+# 11| x <= 2
+#-----| -> "x <= 2"
+
# 14| enter m2
#-----| -> b
@@ -4936,20 +5241,26 @@ raise.rb:
#-----| -> then ...
# 20| self
-#-----| -> "Rescued"
+#-----| -> Rescued
# 20| "Rescued"
#-----| -> call to puts
+# 20| Rescued
+#-----| -> "Rescued"
+
# 22| call to puts
#-----| -> exit m2 (normal)
# 22| self
-#-----| -> "End m2"
+#-----| -> End m2
# 22| "End m2"
#-----| -> call to puts
+# 22| End m2
+#-----| -> "End m2"
+
# 25| enter m3
#-----| -> b
@@ -4990,20 +5301,26 @@ raise.rb:
#-----| -> then ...
# 31| self
-#-----| -> "Rescued"
+#-----| -> Rescued
# 31| "Rescued"
#-----| -> call to puts
+# 31| Rescued
+#-----| -> "Rescued"
+
# 33| call to puts
#-----| -> exit m3 (normal)
# 33| self
-#-----| -> "End m3"
+#-----| -> End m3
# 33| "End m3"
#-----| -> call to puts
+# 33| End m3
+#-----| -> "End m3"
+
# 36| enter m4
#-----| -> b
@@ -5047,20 +5364,26 @@ raise.rb:
#-----| -> then ...
# 42| self
-#-----| -> "Rescued {e}"
+#-----| -> Rescued {e}
# 42| "Rescued {e}"
#-----| -> call to puts
+# 42| Rescued {e}
+#-----| -> "Rescued {e}"
+
# 44| call to puts
#-----| -> exit m4 (normal)
# 44| self
-#-----| -> "End m4"
+#-----| -> End m4
# 44| "End m4"
#-----| -> call to puts
+# 44| End m4
+#-----| -> "End m4"
+
# 47| enter m5
#-----| -> b
@@ -5101,11 +5424,14 @@ raise.rb:
#-----| -> exit m5 (normal)
# 54| self
-#-----| -> "End m5"
+#-----| -> End m5
# 54| "End m5"
#-----| -> call to puts
+# 54| End m5
+#-----| -> "End m5"
+
# 57| enter m6
#-----| -> b
@@ -5160,20 +5486,26 @@ raise.rb:
#-----| -> then ...
# 63| self
-#-----| -> "Rescued {e}"
+#-----| -> Rescued {e}
# 63| "Rescued {e}"
#-----| -> call to puts
+# 63| Rescued {e}
+#-----| -> "Rescued {e}"
+
# 65| call to puts
#-----| -> exit m6 (normal)
# 65| self
-#-----| -> "End m6"
+#-----| -> End m6
# 65| "End m6"
#-----| -> call to puts
+# 65| End m6
+#-----| -> "End m6"
+
# 68| enter m7
#-----| -> x
@@ -5209,17 +5541,20 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 70| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 70| "x > 2"
#-----| -> call to raise
+# 70| x > 2
+#-----| -> "x > 2"
+
# 71| elsif ...
#-----| -> if ...
# 71| ... < ...
#-----| false -> elsif ...
-#-----| true -> "x < 0"
+#-----| true -> x < 0
#-----| raise -> [ensure: raise] self
# 71| x
@@ -5234,16 +5569,22 @@ raise.rb:
# 72| "x < 0"
#-----| -> return
+# 72| x < 0
+#-----| -> "x < 0"
+
# 74| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 74| self
-#-----| -> "0 <= x <= 2"
+#-----| -> 0 <= x <= 2
# 74| "0 <= x <= 2"
#-----| -> call to puts
+# 74| 0 <= x <= 2
+#-----| -> "0 <= x <= 2"
+
# 75| ensure ...
#-----| -> exit m7 (normal)
@@ -5263,13 +5604,13 @@ raise.rb:
#-----| -> [ensure: raise] ensure ...
# 76| self
-#-----| -> "ensure"
+#-----| -> ensure
# 76| [ensure: return] self
-#-----| -> [ensure: return] "ensure"
+#-----| -> [ensure: return] ensure
# 76| [ensure: raise] self
-#-----| -> [ensure: raise] "ensure"
+#-----| -> [ensure: raise] ensure
# 76| "ensure"
#-----| -> call to puts
@@ -5280,6 +5621,15 @@ raise.rb:
# 76| [ensure: raise] "ensure"
#-----| -> [ensure: raise] call to puts
+# 76| ensure
+#-----| -> "ensure"
+
+# 76| [ensure: return] ensure
+#-----| -> [ensure: return] "ensure"
+
+# 76| [ensure: raise] ensure
+#-----| -> [ensure: raise] "ensure"
+
# 79| enter m8
#-----| -> x
@@ -5301,11 +5651,14 @@ raise.rb:
#-----| -> x
# 80| self
-#-----| -> "Begin m8"
+#-----| -> Begin m8
# 80| "Begin m8"
#-----| -> call to puts
+# 80| Begin m8
+#-----| -> "Begin m8"
+
# 82| if ...
#-----| -> self
@@ -5324,17 +5677,20 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 83| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 83| "x > 2"
#-----| -> call to raise
+# 83| x > 2
+#-----| -> "x > 2"
+
# 84| elsif ...
#-----| -> if ...
# 84| ... < ...
#-----| false -> elsif ...
-#-----| true -> "x < 0"
+#-----| true -> x < 0
#-----| raise -> [ensure: raise] self
# 84| x
@@ -5349,16 +5705,22 @@ raise.rb:
# 85| "x < 0"
#-----| -> return
+# 85| x < 0
+#-----| -> "x < 0"
+
# 87| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 87| self
-#-----| -> "0 <= x <= 2"
+#-----| -> 0 <= x <= 2
# 87| "0 <= x <= 2"
#-----| -> call to puts
+# 87| 0 <= x <= 2
+#-----| -> "0 <= x <= 2"
+
# 88| ensure ...
#-----| -> self
@@ -5378,13 +5740,13 @@ raise.rb:
#-----| -> [ensure: raise] ensure ...
# 89| self
-#-----| -> "ensure"
+#-----| -> ensure
# 89| [ensure: return] self
-#-----| -> [ensure: return] "ensure"
+#-----| -> [ensure: return] ensure
# 89| [ensure: raise] self
-#-----| -> [ensure: raise] "ensure"
+#-----| -> [ensure: raise] ensure
# 89| "ensure"
#-----| -> call to puts
@@ -5395,15 +5757,27 @@ raise.rb:
# 89| [ensure: raise] "ensure"
#-----| -> [ensure: raise] call to puts
+# 89| ensure
+#-----| -> "ensure"
+
+# 89| [ensure: return] ensure
+#-----| -> [ensure: return] "ensure"
+
+# 89| [ensure: raise] ensure
+#-----| -> [ensure: raise] "ensure"
+
# 91| call to puts
#-----| -> exit m8 (normal)
# 91| self
-#-----| -> "End m8"
+#-----| -> End m8
# 91| "End m8"
#-----| -> call to puts
+# 91| End m8
+#-----| -> "End m8"
+
# 94| enter m9
#-----| -> x
@@ -5432,11 +5806,14 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 95| self
-#-----| -> "Begin m9"
+#-----| -> Begin m9
# 95| "Begin m9"
#-----| -> call to puts
+# 95| Begin m9
+#-----| -> "Begin m9"
+
# 97| if ...
#-----| -> self
@@ -5455,17 +5832,20 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 98| self
-#-----| -> "x > 2"
+#-----| -> x > 2
# 98| "x > 2"
#-----| -> call to raise
+# 98| x > 2
+#-----| -> "x > 2"
+
# 99| elsif ...
#-----| -> if ...
# 99| ... < ...
#-----| false -> elsif ...
-#-----| true -> "x < 0"
+#-----| true -> x < 0
#-----| raise -> [ensure: raise] self
# 99| x
@@ -5480,16 +5860,22 @@ raise.rb:
# 100| "x < 0"
#-----| -> return
+# 100| x < 0
+#-----| -> "x < 0"
+
# 102| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 102| self
-#-----| -> "0 <= x <= 2"
+#-----| -> 0 <= x <= 2
# 102| "0 <= x <= 2"
#-----| -> call to puts
+# 102| 0 <= x <= 2
+#-----| -> "0 <= x <= 2"
+
# 103| ensure ...
#-----| -> self
@@ -5512,13 +5898,13 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 104| self
-#-----| -> "outer ensure"
+#-----| -> outer ensure
# 104| [ensure: return] self
-#-----| -> [ensure: return] "outer ensure"
+#-----| -> [ensure: return] outer ensure
# 104| [ensure: raise] self
-#-----| -> [ensure: raise] "outer ensure"
+#-----| -> [ensure: raise] outer ensure
# 104| "outer ensure"
#-----| -> call to puts
@@ -5529,6 +5915,15 @@ raise.rb:
# 104| [ensure: raise] "outer ensure"
#-----| -> [ensure: raise] call to puts
+# 104| outer ensure
+#-----| -> "outer ensure"
+
+# 104| [ensure: return] outer ensure
+#-----| -> [ensure: return] "outer ensure"
+
+# 104| [ensure: raise] outer ensure
+#-----| -> [ensure: raise] "outer ensure"
+
# 106| if ...
#-----| -> self
@@ -5560,13 +5955,13 @@ raise.rb:
#-----| raise -> [ensure: raise, ensure(1): raise] self
# 107| self
-#-----| -> "b1 is true"
+#-----| -> b1 is true
# 107| [ensure: return] self
-#-----| -> [ensure: return] "b1 is true"
+#-----| -> [ensure: return] b1 is true
# 107| [ensure: raise] self
-#-----| -> [ensure: raise] "b1 is true"
+#-----| -> [ensure: raise] b1 is true
# 107| "b1 is true"
#-----| -> call to raise
@@ -5577,6 +5972,15 @@ raise.rb:
# 107| [ensure: raise] "b1 is true"
#-----| -> [ensure: raise] call to raise
+# 107| b1 is true
+#-----| -> "b1 is true"
+
+# 107| [ensure: return] b1 is true
+#-----| -> [ensure: return] "b1 is true"
+
+# 107| [ensure: raise] b1 is true
+#-----| -> [ensure: raise] "b1 is true"
+
# 109| ensure ...
#-----| -> ensure ...
@@ -5620,22 +6024,22 @@ raise.rb:
#-----| raise -> [ensure: raise] self
# 110| self
-#-----| -> "inner ensure"
+#-----| -> inner ensure
# 110| [ensure(1): raise] self
-#-----| -> [ensure(1): raise] "inner ensure"
+#-----| -> [ensure(1): raise] inner ensure
# 110| [ensure: return] self
-#-----| -> [ensure: return] "inner ensure"
+#-----| -> [ensure: return] inner ensure
# 110| [ensure: return, ensure(1): raise] self
-#-----| -> [ensure: return, ensure(1): raise] "inner ensure"
+#-----| -> [ensure: return, ensure(1): raise] inner ensure
# 110| [ensure: raise] self
-#-----| -> [ensure: raise] "inner ensure"
+#-----| -> [ensure: raise] inner ensure
# 110| [ensure: raise, ensure(1): raise] self
-#-----| -> [ensure: raise, ensure(1): raise] "inner ensure"
+#-----| -> [ensure: raise, ensure(1): raise] inner ensure
# 110| "inner ensure"
#-----| -> call to puts
@@ -5655,16 +6059,37 @@ raise.rb:
# 110| [ensure: raise, ensure(1): raise] "inner ensure"
#-----| -> [ensure: raise, ensure(1): raise] call to puts
+# 110| inner ensure
+#-----| -> "inner ensure"
+
+# 110| [ensure(1): raise] inner ensure
+#-----| -> [ensure(1): raise] "inner ensure"
+
+# 110| [ensure: return] inner ensure
+#-----| -> [ensure: return] "inner ensure"
+
+# 110| [ensure: return, ensure(1): raise] inner ensure
+#-----| -> [ensure: return, ensure(1): raise] "inner ensure"
+
+# 110| [ensure: raise] inner ensure
+#-----| -> [ensure: raise] "inner ensure"
+
+# 110| [ensure: raise, ensure(1): raise] inner ensure
+#-----| -> [ensure: raise, ensure(1): raise] "inner ensure"
+
# 113| call to puts
#-----| -> self
#-----| raise -> [ensure: raise] self
# 113| self
-#-----| -> "End m9"
+#-----| -> End m9
# 113| "End m9"
#-----| -> call to puts
+# 113| End m9
+#-----| -> "End m9"
+
# 114| ensure ...
#-----| -> exit m9 (normal)
@@ -5684,13 +6109,13 @@ raise.rb:
#-----| -> [ensure: raise] b2
# 115| self
-#-----| -> "method ensure"
+#-----| -> method ensure
# 115| [ensure: return] self
-#-----| -> [ensure: return] "method ensure"
+#-----| -> [ensure: return] method ensure
# 115| [ensure: raise] self
-#-----| -> [ensure: raise] "method ensure"
+#-----| -> [ensure: raise] method ensure
# 115| "method ensure"
#-----| -> call to puts
@@ -5701,6 +6126,15 @@ raise.rb:
# 115| [ensure: raise] "method ensure"
#-----| -> [ensure: raise] call to puts
+# 115| method ensure
+#-----| -> "method ensure"
+
+# 115| [ensure: return] method ensure
+#-----| -> [ensure: return] "method ensure"
+
+# 115| [ensure: raise] method ensure
+#-----| -> [ensure: raise] "method ensure"
+
# 116| if ...
#-----| -> ensure ...
@@ -5732,13 +6166,13 @@ raise.rb:
#-----| raise -> exit m9 (abnormal)
# 117| self
-#-----| -> "b2 is true"
+#-----| -> b2 is true
# 117| [ensure: return] self
-#-----| -> [ensure: return] "b2 is true"
+#-----| -> [ensure: return] b2 is true
# 117| [ensure: raise] self
-#-----| -> [ensure: raise] "b2 is true"
+#-----| -> [ensure: raise] b2 is true
# 117| "b2 is true"
#-----| -> call to raise
@@ -5749,6 +6183,15 @@ raise.rb:
# 117| [ensure: raise] "b2 is true"
#-----| -> [ensure: raise] call to raise
+# 117| b2 is true
+#-----| -> "b2 is true"
+
+# 117| [ensure: return] b2 is true
+#-----| -> [ensure: return] "b2 is true"
+
+# 117| [ensure: raise] b2 is true
+#-----| -> [ensure: raise] "b2 is true"
+
# 121| enter m10
#-----| -> p
@@ -5771,11 +6214,14 @@ raise.rb:
#-----| raise -> exit m10 (abnormal)
# 121| self
-#-----| -> "Exception"
+#-----| -> Exception
# 121| "Exception"
#-----| -> call to raise
+# 121| Exception
+#-----| -> "Exception"
+
# 124| ensure ...
#-----| -> exit m10 (normal)
@@ -5783,11 +6229,14 @@ raise.rb:
#-----| -> ensure ...
# 125| self
-#-----| -> "Will not get executed if p is..."
+#-----| -> Will not get executed if p is not supplied
# 125| "Will not get executed if p is..."
#-----| -> call to puts
+# 125| Will not get executed if p is not supplied
+#-----| -> "Will not get executed if p is..."
+
# 128| enter m11
#-----| -> b
@@ -5842,11 +6291,14 @@ raise.rb:
#-----| -> then ...
# 135| self
-#-----| -> "ExceptionB"
+#-----| -> ExceptionB
# 135| "ExceptionB"
#-----| -> call to puts
+# 135| ExceptionB
+#-----| -> "ExceptionB"
+
# 136| ensure ...
#-----| -> self
@@ -5860,10 +6312,10 @@ raise.rb:
#-----| -> [ensure: raise] ensure ...
# 137| self
-#-----| -> "Ensure"
+#-----| -> Ensure
# 137| [ensure: raise] self
-#-----| -> [ensure: raise] "Ensure"
+#-----| -> [ensure: raise] Ensure
# 137| "Ensure"
#-----| -> call to puts
@@ -5871,15 +6323,24 @@ raise.rb:
# 137| [ensure: raise] "Ensure"
#-----| -> [ensure: raise] call to puts
+# 137| Ensure
+#-----| -> "Ensure"
+
+# 137| [ensure: raise] Ensure
+#-----| -> [ensure: raise] "Ensure"
+
# 139| call to puts
#-----| -> exit m11 (normal)
# 139| self
-#-----| -> "End m11"
+#-----| -> End m11
# 139| "End m11"
#-----| -> call to puts
+# 139| End m11
+#-----| -> "End m11"
+
# 142| enter m12
#-----| -> b
From 799ec23b0d7ae0608de382acfe9b928a680d9c39 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 11:01:34 +0100
Subject: [PATCH 007/196] Ruby: Generalize `ExprChildMapping` logic to
`AstNode`s
---
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 36 +++++++++----------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 369a79209ab..30e31833d84 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -132,7 +132,7 @@ class StringComponentCfgNode extends AstCfgNode {
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
-private Expr desugar(Expr n) {
+private AstNode desugar(AstNode n) {
result = n.getDesugared()
or
not exists(n.getDesugared()) and
@@ -147,10 +147,10 @@ abstract private class ExprChildMapping extends Expr {
* Holds if `child` is a (possibly nested) child of this expression
* for which we would like to find a matching CFG child.
*/
- abstract predicate relevantChild(Expr child);
+ abstract predicate relevantChild(AstNode child);
pragma[nomagic]
- private predicate reachesBasicBlock(Expr child, CfgNode cfn, BasicBlock bb) {
+ private predicate reachesBasicBlock(AstNode child, CfgNode cfn, BasicBlock bb) {
this.relevantChild(child) and
cfn = this.getAControlFlowNode() and
bb.getANode() = cfn
@@ -170,16 +170,16 @@ abstract private class ExprChildMapping extends Expr {
* The path never escapes the syntactic scope of this expression.
*/
cached
- predicate hasCfgChild(Expr child, CfgNode cfn, CfgNode cfnChild) {
+ predicate hasCfgChild(AstNode child, CfgNode cfn, CfgNode cfnChild) {
this.reachesBasicBlock(child, cfn, cfnChild.getBasicBlock()) and
- cfnChild = desugar(child).getAControlFlowNode()
+ cfnChild.getNode() = desugar(child)
}
}
/** Provides classes for control-flow nodes that wrap AST expressions. */
module ExprNodes {
private class LiteralChildMapping extends ExprChildMapping, Literal {
- override predicate relevantChild(Expr e) { none() }
+ override predicate relevantChild(AstNode n) { none() }
}
/** A control-flow node that wraps an `ArrayLiteral` AST expression. */
@@ -192,7 +192,7 @@ module ExprNodes {
}
private class AssignExprChildMapping extends ExprChildMapping, AssignExpr {
- override predicate relevantChild(Expr e) { e = this.getAnOperand() }
+ override predicate relevantChild(AstNode n) { n = this.getAnOperand() }
}
/** A control-flow node that wraps an `AssignExpr` AST expression. */
@@ -209,7 +209,7 @@ module ExprNodes {
}
private class OperationExprChildMapping extends ExprChildMapping, Operation {
- override predicate relevantChild(Expr e) { e = this.getAnOperand() }
+ override predicate relevantChild(AstNode n) { n = this.getAnOperand() }
}
/** A control-flow node that wraps an `Operation` AST expression. */
@@ -292,7 +292,7 @@ module ExprNodes {
}
private class BlockArgumentChildMapping extends ExprChildMapping, BlockArgument {
- override predicate relevantChild(Expr e) { e = this.getValue() }
+ override predicate relevantChild(AstNode n) { n = this.getValue() }
}
/** A control-flow node that wraps a `BlockArgument` AST expression. */
@@ -306,8 +306,8 @@ module ExprNodes {
}
private class CallExprChildMapping extends ExprChildMapping, Call {
- override predicate relevantChild(Expr e) {
- e = [this.getAnArgument(), this.(MethodCall).getReceiver(), this.(MethodCall).getBlock()]
+ override predicate relevantChild(AstNode n) {
+ n = [this.getAnArgument(), this.(MethodCall).getReceiver(), this.(MethodCall).getBlock()]
}
}
@@ -340,7 +340,7 @@ module ExprNodes {
}
private class CaseExprChildMapping extends ExprChildMapping, CaseExpr {
- override predicate relevantChild(Expr e) { e = this.getValue() }
+ override predicate relevantChild(AstNode e) { e = this.getValue() }
}
/** A control-flow node that wraps a `MethodCall` AST expression. */
@@ -361,7 +361,7 @@ module ExprNodes {
}
private class ConditionalExprChildMapping extends ExprChildMapping, ConditionalExpr {
- override predicate relevantChild(Expr e) { e = this.getCondition() or e = this.getBranch(_) }
+ override predicate relevantChild(AstNode n) { n = [this.getCondition(), this.getBranch(_)] }
}
/** A control-flow node that wraps a `ConditionalExpr` AST expression. */
@@ -381,7 +381,7 @@ module ExprNodes {
}
private class ConstantAccessChildMapping extends ExprChildMapping, ConstantAccess {
- override predicate relevantChild(Expr e) { e = this.getScopeExpr() }
+ override predicate relevantChild(AstNode n) { n = this.getScopeExpr() }
}
/** A control-flow node that wraps a `ConditionalExpr` AST expression. */
@@ -397,7 +397,7 @@ module ExprNodes {
}
private class StmtSequenceChildMapping extends ExprChildMapping, StmtSequence {
- override predicate relevantChild(Expr e) { e = this.getLastStmt() }
+ override predicate relevantChild(AstNode n) { n = this.getLastStmt() }
}
/** A control-flow node that wraps a `StmtSequence` AST expression. */
@@ -411,7 +411,7 @@ module ExprNodes {
}
private class ForExprChildMapping extends ExprChildMapping, ForExpr {
- override predicate relevantChild(Expr e) { e = this.getValue() }
+ override predicate relevantChild(AstNode n) { n = this.getValue() }
}
/** A control-flow node that wraps a `ForExpr` AST expression. */
@@ -430,7 +430,7 @@ module ExprNodes {
}
private class PairChildMapping extends ExprChildMapping, Pair {
- override predicate relevantChild(Expr e) { e = this.getKey() or e = this.getValue() }
+ override predicate relevantChild(AstNode n) { n = [this.getKey(), this.getValue()] }
}
/** A control-flow node that wraps a `Pair` AST expression. */
@@ -475,7 +475,7 @@ module ExprNodes {
}
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
- override predicate relevantChild(Expr e) { e = this.getComponent(_) }
+ override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
/** A control-flow node that wraps a `StringlikeLiteral` AST expression. */
From c3fd272f9b54c32e4d257c34fc0592173bb59b6a Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Fri, 17 Dec 2021 11:03:07 +0100
Subject: [PATCH 008/196] Ruby: Simplify `getValueText` logic for
`StringlikeLiteral`s
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 21 +------------------
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 21 ++++---------------
.../test/library-tests/ast/ValueText.expected | 1 -
3 files changed, 5 insertions(+), 38 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 181c23fbf6e..1f5350bdb33 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -10,15 +10,7 @@ private import codeql.ruby.controlflow.CfgNodes
*
* This is the QL root class for all literals.
*/
-class Literal extends Expr, TLiteral {
- /**
- * Gets the source text for this literal, if this is a simple literal.
- *
- * For complex literals, such as arrays, hashes, and strings with
- * interpolations, this predicate has no result.
- */
- override string getValueText() { none() }
-}
+class Literal extends Expr, TLiteral { }
/**
* A numeric literal, i.e. an integer, floating-point, rational, or complex
@@ -411,17 +403,6 @@ class StringlikeLiteral extends Literal, TStringlikeLiteral {
result = ""
}
- override string getValueText() {
- forall(StringComponent c | c = this.getComponent(_) |
- not c instanceof StringInterpolationComponent
- ) and
- result =
- concat(StringComponent c, int i | c = this.getComponent(i) | c.getValueText() order by i)
- or
- exists(this.getComponent(_)) and
- result = this.getAControlFlowNode().(ExprNodes::StringlikeLiteralCfgNode).getValueText()
- }
-
override string toString() {
exists(string full, string summary |
full =
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 30e31833d84..8c35c4fc1b0 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -485,7 +485,7 @@ module ExprNodes {
final override StringlikeLiteral getExpr() { result = super.getExpr() }
/** Gets the `n`th component of this `StringlikeLiteral` */
- StringComponentCfgNode getComponent(int n) { result.getNode() = e.getComponent(n) }
+ StringComponentCfgNode getComponent(int n) { e.hasCfgChild(e.getComponent(n), this, result) }
/** Gets a component of this `StringlikeLiteral` */
StringComponentCfgNode getAComponent() { result = this.getComponent(_) }
@@ -494,26 +494,13 @@ module ExprNodes {
// if all interpolations have a known string value, we will get a result
language[monotonicAggregates]
override string getValueText() {
- result = e.getValueText()
- or
result =
- concat(StringComponent c, int i |
- c = e.getComponent(i)
+ concat(StringComponentCfgNode c, int i |
+ c = this.getComponent(i)
|
- getComponentValueText(c) order by i
+ c.getValueText() order by i
)
}
-
- /**
- * Get the `ValueText()` of a `StringComponent`.
- * If the component has a CFG node, defer to that (in order to resolve variables in interpolations).
- * Otherwise, defer to the AST node.
- */
- private string getComponentValueText(StringComponent c) {
- exists(StringComponentCfgNode n | n.getNode() = c | result = n.getValueText())
- or
- not exists(StringComponentCfgNode n | n.getNode() = c) and result = c.getValueText()
- }
}
/** A control-flow node that wraps a `StringLiteral` AST expression. */
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index 57167453e7b..a456501c0c8 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -614,7 +614,6 @@
| modules/modules.rb:55:8:55:30 | "module Foo::Bar again" | module Foo::Bar again |
| modules/modules.rb:56:17:56:17 | 4 | 4 |
| modules/toplevel.rb:1:6:1:12 | "world" | world |
-| modules/toplevel.rb:3:12:3:16 | "!!!" | !!! |
| modules/toplevel.rb:5:14:5:20 | "hello" | hello |
| operations/operations.rb:3:5:3:5 | 0 | 0 |
| operations/operations.rb:4:5:4:5 | 0 | 0 |
From ac9cac78bc1705a99cd91a6ac02e7d3342a46179 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Tue, 21 Dec 2021 09:19:56 +0100
Subject: [PATCH 009/196] Ruby: Fix typo
---
.../codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
index 22615dc2575..c56d1e6369d 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
@@ -1350,8 +1350,8 @@ module Trees {
final override ControlFlowTree getChildElement(int i) { result = this.getComponent(i) }
}
- private class StringComponentComponentTree extends LeafTree, StringComponent {
- StringComponentComponentTree() { not this instanceof StringInterpolationComponent }
+ private class StringComponentTree extends LeafTree, StringComponent {
+ StringComponentTree() { not this instanceof StringInterpolationComponent }
}
private class ToplevelTree extends BodyStmtTree, Toplevel {
From 43ddc54f2b262317364b20b97a507a5a3f49a364 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Thu, 16 Dec 2021 13:24:31 +1300
Subject: [PATCH 010/196] Ruby: Add Module#const_get as a code execution
Module#const_get takes a single string argument and interprets it as the
name of a constant. It then looks up the constant and returns its value.
Object.const_get("Math::PI")
# => 3.141592653589793
By itself, this method is not as dangerous as e.g. eval, but if the
value returned is a class that is then instantiated, this can allow an
attacker to instantiate arbitrary Ruby classes.
As a result, I think it's safe to say that any remote input flowing into
this call is a potential vulnerability. A real-world example of this is
https://github.com/advisories/GHSA-52p9-v744-mwjj.
---
.../ruby/frameworks/StandardLibrary.qll | 12 +++++++++
.../frameworks/StandardLibrary.expected | 7 +++++
.../frameworks/StandardLibrary.ql | 4 +++
.../library-tests/frameworks/const_get.rb | 27 +++++++++++++++++++
.../security/cwe-094/CodeInjection.expected | 6 +++++
.../security/cwe-094/CodeInjection.rb | 13 +++++++++
6 files changed, 69 insertions(+)
create mode 100644 ruby/ql/test/library-tests/frameworks/const_get.rb
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll b/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll
index ce8c443dda2..e66251e819c 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/StandardLibrary.qll
@@ -335,6 +335,18 @@ class ModuleEvalCallCodeExecution extends CodeExecution::Range, DataFlow::CallNo
override DataFlow::Node getCode() { result = this.getArgument(0) }
}
+/**
+ * A call to `Module#const_get`, which interprets its argument as a Ruby constant.
+ * Passing user input to this method may result in instantiation of arbitrary Ruby classes.
+ */
+class ModuleConstGetCallCodeExecution extends CodeExecution::Range, DataFlow::CallNode {
+ ModuleConstGetCallCodeExecution() {
+ this.asExpr().getExpr().(UnknownMethodCall).getMethodName() = "const_get"
+ }
+
+ override DataFlow::Node getCode() { result = this.getArgument(0) }
+}
+
/** Flow summary for `Regexp.escape` and its alias, `Regexp.quote`. */
class RegexpEscapeSummary extends SummarizedCallable {
RegexpEscapeSummary() { this = "Regexp.escape" }
diff --git a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
index 36fea1b31cd..9534a8be6de 100644
--- a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
+++ b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
@@ -93,3 +93,10 @@ loggerLoggingCallInputs
| Logging.rb:73:5:73:63 | call to log | Logging.rb:73:36:73:45 | "message1" |
| Logging.rb:74:5:74:76 | call to log | Logging.rb:74:36:74:45 | "message2" |
| Logging.rb:74:5:74:76 | call to log | Logging.rb:74:48:74:58 | "progname2" |
+moduleConstGetCallCodeExecutions
+| const_get.rb:1:1:1:24 | call to const_get | const_get.rb:1:18:1:23 | "Math" |
+| const_get.rb:2:1:2:28 | call to const_get | const_get.rb:2:22:2:27 | "Math" |
+| const_get.rb:3:1:3:20 | call to const_get | const_get.rb:3:16:3:19 | "PI" |
+| const_get.rb:4:1:4:19 | call to const_get | const_get.rb:4:16:4:18 | :PI |
+| const_get.rb:22:1:22:33 | call to const_get | const_get.rb:22:18:22:32 | "Foo::Baz::VAL" |
+| const_get.rb:23:1:23:25 | call to const_get | const_get.rb:23:15:23:24 | "Bar::VAL" |
diff --git a/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql b/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql
index 2e6a62ba8fd..bb8102b68e4 100644
--- a/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql
+++ b/ruby/ql/test/library-tests/frameworks/StandardLibrary.ql
@@ -32,3 +32,7 @@ query DataFlow::Node moduleEvalCallCodeExecutions(ModuleEvalCallCodeExecution e)
}
query DataFlow::Node loggerLoggingCallInputs(LoggerLoggingCall c) { result = c.getAnInput() }
+
+query DataFlow::Node moduleConstGetCallCodeExecutions(ModuleConstGetCallCodeExecution e) {
+ result = e.getCode()
+}
diff --git a/ruby/ql/test/library-tests/frameworks/const_get.rb b/ruby/ql/test/library-tests/frameworks/const_get.rb
new file mode 100644
index 00000000000..40b52ee0329
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/const_get.rb
@@ -0,0 +1,27 @@
+Object.const_get("Math")
+self.class.const_get("Math")
+Math.const_get("PI")
+Math.const_get(:PI)
+
+module Foo
+ class Bar
+ VAL = 10
+
+ def const_get(x)
+ "my custom const_get method"
+ end
+ end
+
+ class Baz < Bar
+ def self.const_get(x)
+ "another custom const_get method"
+ end
+ end
+end
+
+Object.const_get("Foo::Baz::VAL")
+Foo.const_get("Bar::VAL")
+
+# Should not be identified as a use of Module#const_get
+Foo::Bar.new.const_get 5
+Foo::Baz.const_get 5
\ No newline at end of file
diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected
index f9e4dd35642..bcda3f9dc1e 100644
--- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected
+++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.expected
@@ -3,6 +3,8 @@ edges
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:6:10:6:13 | code |
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:18:20:18:23 | code |
| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:21:21:21:24 | code |
+| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:27:15:27:18 | code |
+| CodeInjection.rb:3:12:3:24 | ...[...] : | CodeInjection.rb:30:19:30:22 | code |
nodes
| CodeInjection.rb:3:12:3:17 | call to params : | semmle.label | call to params : |
| CodeInjection.rb:3:12:3:24 | ...[...] : | semmle.label | ...[...] : |
@@ -10,9 +12,13 @@ nodes
| CodeInjection.rb:9:10:9:15 | call to params | semmle.label | call to params |
| CodeInjection.rb:18:20:18:23 | code | semmle.label | code |
| CodeInjection.rb:21:21:21:24 | code | semmle.label | code |
+| CodeInjection.rb:27:15:27:18 | code | semmle.label | code |
+| CodeInjection.rb:30:19:30:22 | code | semmle.label | code |
subpaths
#select
| CodeInjection.rb:6:10:6:13 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:6:10:6:13 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
| CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | CodeInjection.rb:9:10:9:15 | call to params | This code execution depends on $@. | CodeInjection.rb:9:10:9:15 | call to params | a user-provided value |
| CodeInjection.rb:18:20:18:23 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:18:20:18:23 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
| CodeInjection.rb:21:21:21:24 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:21:21:21:24 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
+| CodeInjection.rb:27:15:27:18 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:27:15:27:18 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
+| CodeInjection.rb:30:19:30:22 | code | CodeInjection.rb:3:12:3:17 | call to params : | CodeInjection.rb:30:19:30:22 | code | This code execution depends on $@. | CodeInjection.rb:3:12:3:17 | call to params | a user-provided value |
diff --git a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb
index 80ee5bee133..bee8357a9a5 100644
--- a/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb
+++ b/ruby/ql/test/query-tests/security/cwe-094/CodeInjection.rb
@@ -22,6 +22,15 @@ class UsersController < ActionController::Base
# GOOD
Bar.class_eval(code)
+
+ # BAD
+ const_get(code)
+
+ # BAD
+ Foo.const_get(code)
+
+ # GOOD
+ Bar.const_get(code)
end
def update
@@ -50,4 +59,8 @@ class Bar
def self.class_eval(x)
true
end
+
+ def self.const_get(x)
+ true
+ end
end
\ No newline at end of file
From e4eb2c2a5980c4712b9391042d2d68135def4c9a Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Tue, 11 Jan 2022 15:21:12 -0800
Subject: [PATCH 011/196] Update docs on the output of `resolve qlpacks`
The output has changed and there are no more upgrades
packs. There are also other changes included here.
---
.../getting-started-with-the-codeql-cli.rst | 98 ++++++++++---------
1 file changed, 51 insertions(+), 47 deletions(-)
diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
index eaf47ec62f3..4651c6d1acd 100644
--- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
+++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
@@ -4,7 +4,7 @@ Getting started with the CodeQL CLI
===================================
To run CodeQL commands, you need to set up the CLI so that it can access
-the tools, queries, and libraries required to create and analyze databases.
+the tools, queries, and libraries required to create and analyze databases.
.. include:: ../reusables/license-note.rst
@@ -18,16 +18,16 @@ structures. To get started quickly, we recommend adopting a relatively simple
setup, as outlined in the steps below.
If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply
-follow the steps below. For macOS version 10.15 ("Catalina") or newer, steps 1
-and 4 are slightly different---for further details, see the sections labeled
+follow the steps below. For macOS version 10.15 ("Catalina") or newer, steps 1
+and 4 are slightly different---for further details, see the sections labeled
**Information for macOS "Catalina" (or newer) users**. If you are using macOS
on Apple Silicon (e.g. Apple M1), ensure that the `Xcode command-line developer
tools `__ and `Rosetta 2
`__ are installed.
For information about installing the CodeQL CLI in a CI system to create results
-to display in GitHub as code scanning alerts, see
-`Installing CodeQL CLI in your CI system `__
+to display in GitHub as code scanning alerts, see
+`Installing CodeQL CLI in your CI system `__
in the GitHub documentation.
1. Download the CodeQL CLI zip package
@@ -42,9 +42,9 @@ Conditions `__.
There are several different versions of the CLI available to download, depending
on your use case:
-
+
- If you want to use the most up to date CodeQL tools and features, download the
- version tagged ``latest``.
+ version tagged ``latest``.
- If you want to create CodeQL databases to upload to LGTM Enterprise, download
the version that is compatible with the relevant LGTM Enterprise version
@@ -53,9 +53,9 @@ Conditions `__.
`__ on GitHub. Using the
correct version of the CLI ensures that your CodeQL databases are
compatible with your version of LGTM Enterprise. For more information,
- see `Preparing CodeQL databases to upload to LGTM
+ see `Preparing CodeQL databases to upload to LGTM
`__
- in the LGTM admin help.
+ in the LGTM admin help.
If you use Linux, Windows, or macOS version 10.14 ("Mojave") or earlier, simply
`download the zip archive
@@ -72,12 +72,12 @@ Alternatively, you can download ``codeql.zip``, which contains the CLI for all s
**Information for macOS "Catalina" (or newer) users**
.. pull-quote:: macOS "Catalina" (or newer)
-
- If you use macOS version 10.15 ("Catalina"), version 11 ("Big Sur"), or the upcoming
- version 12 ("Monterey"), you need to ensure that your web browser does not automatically
- extract zip files. If you use Safari, complete the following steps before downloading
+
+ If you use macOS version 10.15 ("Catalina"), version 11 ("Big Sur"), or the upcoming
+ version 12 ("Monterey"), you need to ensure that your web browser does not automatically
+ extract zip files. If you use Safari, complete the following steps before downloading
the CodeQL CLI zip archive:
-
+
i. Open Safari.
ii. From the Safari menu, select **Preferences...**.
iii. Click the **General** Tab.
@@ -101,22 +101,22 @@ further options on the command line.
3. Obtain a local copy of the CodeQL queries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The `CodeQL repository `__ contains
+The `CodeQL repository `__ contains
the queries and libraries required for CodeQL analysis of C/C++, C#, Java,
JavaScript/TypeScript, Python, and Ruby.
-Clone a copy of this repository into ``codeql-home``.
-
-By default, the root of the cloned repository will be called ``codeql``.
-Rename this folder ``codeql-repo`` to avoid conflicting with the CodeQL
-CLI that you will extract in step 4. If you use git on the command line, you can
-clone and rename the repository in a single step by running
+Clone a copy of this repository into ``codeql-home``.
+
+By default, the root of the cloned repository will be called ``codeql``.
+Rename this folder ``codeql-repo`` to avoid conflicting with the CodeQL
+CLI that you will extract in step 4. If you use git on the command line, you can
+clone and rename the repository in a single step by running
``git clone git@github.com:github/codeql.git codeql-repo`` in the ``codeql-home`` folder.
The CodeQL libraries and queries for Go analysis live in the `CodeQL for Go
repository `__. Clone a copy of this
-repository into ``codeql-home``.
+repository into ``codeql-home``.
-The cloned repositories should have a sibling relationship.
+The cloned repositories should have a sibling relationship.
For example, if the root of the cloned CodeQL repository is
``$HOME/codeql-home/codeql-repo``, then the root of the cloned CodeQL for Go
repository should be ``$HOME/codeql-home/codeql-go``.
@@ -134,29 +134,29 @@ see ":doc:`About QL packs `."
- For the queries used on `LGTM.com `__, check out the
``lgtm.com`` branch. You should use this branch for databases you've built
using the CodeQL CLI, fetched from code scanning on GitHub, or recently downloaded from LGTM.com.
- The queries on the ``lgtm.com`` branch are more likely to be compatible
- with the ``latest`` CLI, so you'll be less likely to have to upgrade
- newly-created databases than if you use the ``main`` branch. Older databases
+ The queries on the ``lgtm.com`` branch are more likely to be compatible
+ with the ``latest`` CLI, so you'll be less likely to have to upgrade
+ newly-created databases than if you use the ``main`` branch. Older databases
may need to be upgraded before you can analyze them.
-
- - For the most up to date CodeQL queries, check out the ``main`` branch.
+
+ - For the most up to date CodeQL queries, check out the ``main`` branch.
This branch represents the very latest version of CodeQL's analysis. Even
databases created using the most recent version of the CLI may have to be
upgraded before you can analyze them. For more information, see
":doc:`Upgrading CodeQL databases `."
-
+
- For the queries used in a particular LGTM Enterprise release, check out the
branch tagged with the relevant release number. For example, the branch
tagged ``v1.27.0`` corresponds to LGTM Enterprise 1.27. You must use this
version if you want to upload data to LGTM Enterprise. For further
- information, see `Preparing CodeQL databases to upload to LGTM
+ information, see `Preparing CodeQL databases to upload to LGTM
`__
in the LGTM admin help.
4. Extract the zip archive
~~~~~~~~~~~~~~~~~~~~~~~~~~
-For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier)
+For Linux, Windows, and macOS users (version 10.14 "Mojave", and earlier)
simply
extract the zip archive into the directory you created in step 2.
@@ -171,16 +171,16 @@ For example, if the path to your copy of the CodeQL repository is
**Information for macOS "Catalina" (or newer) users**
.. pull-quote:: macOS "Catalina"
-
- macOS "Catalina", "Big Sur", or "Monterey" users should run the following
- commands in the Terminal, where ``${install_loc}`` is the path to the
+
+ macOS "Catalina", "Big Sur", or "Monterey" users should run the following
+ commands in the Terminal, where ``${install_loc}`` is the path to the
directory you created in step 2:
-
+
i. ``mv ~/Downloads/codeql*.zip ${install_loc}``
ii. ``cd ${install_loc}``
iii. ``/usr/bin/xattr -c codeql*.zip``
iv. ``unzip codeql*.zip``
-
+
5. Launch ``codeql``
~~~~~~~~~~~~~~~~~~~~
@@ -191,7 +191,7 @@ executable in a couple of ways:
```` is the folder where you extracted the CodeQL CLI
package.
- By adding ``/codeql`` to your ``PATH``, so that you
- can run the executable as just ``codeql``.
+ can run the executable as just ``codeql``.
At this point, you can execute CodeQL commands. For a full list of the CodeQL
CLI commands, see the "`CodeQL CLI manual <../manual>`__."
@@ -212,16 +212,20 @@ up to create and analyze databases:
- Run ``codeql resolve languages`` to show which languages are
available for database creation. This will list the languages supported by
- default in your CodeQL CLI package.
+ default in your CodeQL CLI package.
- Run ``codeql resolve qlpacks`` to show which QL packs the CLI can find. This
- will display the names of the QL packs included in the CodeQL repositories:
- ``codeql-cpp``, ``codeql-csharp``, ``codeql-go``,
- ``codeql-java``, ``codeql-javascript``, and ``codeql-python``. The CodeQL
- repositories also contain 'upgrade' packs and 'legacy' packs. Upgrade packs
- are used by the CLI when you want to upgrade a database so that it can be
- analyzed with a newer version of the CodeQL toolchain than was used to create
- it. Legacy packs ensure that custom queries and libraries created using older
- products are compatible with your version of CodeQL.
+ will display the names of all the QL packs directly available to the CodeQL CLI.
+ This should include:
+
+ - Query packs for each supported language, e.g., ``codeql/{language}-queries``.
+ These packs contain the standard queries that will be run for each analysis.
+ - Library packs for each supported language, e.g., ``codeql/{language}-all``. These
+ packs contain query libraries, such as control flow and data flow libraries, that
+ may be useful to other query authors.
+ - Example packs for each supported language, e.g., ``codeql/{language}-examples``.
+ These packs contain useful snippets of CodeQL that query auhtors may want To use.
+ - Legacy packs that ensure custom queries and libraries created using older products are
+ compatible with your version of CodeQL.
.. _using-two-versions-of-the-codeql-cli:
@@ -242,4 +246,4 @@ recommended directory setup depends on which versions you want to install:
directory. For example, if you unpack version 2.0.2 into
``$HOME/codeql-home/codeql-cli``, the older version should be
unpacked into ``$HOME/codeql-older-version/old-codeql-cli``. Here, the common
- grandparent is the ``$HOME`` directory.
+ grandparent is the ``$HOME`` directory.
From c6deccf863354377bb7d40143b05ab450be3bc05 Mon Sep 17 00:00:00 2001
From: Andrew Eisenberg
Date: Thu, 13 Jan 2022 09:02:10 -0800
Subject: [PATCH 012/196] Minor fixes to the getting started docs
Co-authored-by: Felicity Chapman
---
.../codeql-cli/getting-started-with-the-codeql-cli.rst | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
index 4651c6d1acd..3c91fc75209 100644
--- a/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
+++ b/docs/codeql/codeql-cli/getting-started-with-the-codeql-cli.rst
@@ -217,13 +217,13 @@ up to create and analyze databases:
will display the names of all the QL packs directly available to the CodeQL CLI.
This should include:
- - Query packs for each supported language, e.g., ``codeql/{language}-queries``.
+ - Query packs for each supported language, for example, ``codeql/{language}-queries``.
These packs contain the standard queries that will be run for each analysis.
- - Library packs for each supported language, e.g., ``codeql/{language}-all``. These
+ - Library packs for each supported language, for example, ``codeql/{language}-all``. These
packs contain query libraries, such as control flow and data flow libraries, that
- may be useful to other query authors.
- - Example packs for each supported language, e.g., ``codeql/{language}-examples``.
- These packs contain useful snippets of CodeQL that query auhtors may want To use.
+ may be useful to query writers.
+ - Example packs for each supported language, for example, ``codeql/{language}-examples``.
+ These packs contain useful snippets of CodeQL that query writers may find useful.
- Legacy packs that ensure custom queries and libraries created using older products are
compatible with your version of CodeQL.
From d09f48ecb418d84218d01780119ac0b7d1449ab0 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Sun, 16 Jan 2022 20:56:13 +0000
Subject: [PATCH 013/196] Ruby: flag up protect_from_forgery calls without an
exception strategy
---
.../ruby/frameworks/ActionController.qll | 20 +++++++++++++++++++
.../cwe-352/CSRFProtectionDisabled.qhelp | 11 ++++++++++
.../cwe-352/CSRFProtectionDisabled.ql | 8 ++++----
3 files changed, 35 insertions(+), 4 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll
index a47c7644272..ec4a44418cc 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/ActionController.qll
@@ -297,3 +297,23 @@ class ActionControllerSkipForgeryProtectionCall extends CSRFProtectionSetting::R
override boolean getVerificationSetting() { result = false }
}
+
+/**
+ * A call to `protect_from_forgery`.
+ */
+private class ActionControllerProtectFromForgeryCall extends CSRFProtectionSetting::Range {
+ private ActionControllerContextCall callExpr;
+
+ ActionControllerProtectFromForgeryCall() {
+ callExpr = this.asExpr().getExpr() and
+ callExpr.getMethodName() = "protect_from_forgery"
+ }
+
+ private string getWithValueText() { result = callExpr.getKeywordArgument("with").getValueText() }
+
+ // Calls without `with: :exception` can allow for bypassing CSRF protection
+ // in some scenarios.
+ override boolean getVerificationSetting() {
+ if this.getWithValueText() = "exception" then result = true else result = false
+ }
+}
diff --git a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp
index b496ce0eca5..8b5ff38d5a3 100644
--- a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp
+++ b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.qhelp
@@ -50,12 +50,23 @@
skip_before_action.
+
+ Care should be taken when using the Rails
+ protect_from_forgery method to prevent CSRF. The default
+ behaviour of this method is to null the session when an invalid CSRF token
+ is provided. This may not be sufficient to avoid a CSRF vulnerability -
+ for example if parts of the session are memoized. Calling
+ protect_from_forgery with: :exception can help to avoid this
+ by raising an exception on an invalid CSRF token instead.
+
+
Wikipedia: Cross-site request forgery
OWASP: Cross-site request forgery
Securing Rails Applications: Cross-Site Request Forgery (CSRF)
+ Veracode: When Rails' protect_from_forgery Fails .
diff --git a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql
index 6b997450f53..65028241fe1 100644
--- a/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql
+++ b/ruby/ql/src/queries/security/cwe-352/CSRFProtectionDisabled.ql
@@ -1,7 +1,7 @@
/**
- * @name CSRF protection disabled
- * @description Disabling CSRF protection makes the application vulnerable to
- * a Cross-Site Request Forgery (CSRF) attack.
+ * @name CSRF protection weakened or disabled
+ * @description Disabling or weakening CSRF protection may make the application
+ * vulnerable to a Cross-Site Request Forgery (CSRF) attack.
* @kind problem
* @problem.severity warning
* @security-severity 8.8
@@ -16,4 +16,4 @@ import codeql.ruby.Concepts
from CSRFProtectionSetting s
where s.getVerificationSetting() = false
-select s, "Potential CSRF vulnerability due to forgery protection being disabled."
+select s, "Potential CSRF vulnerability due to forgery protection being disabled or weakened."
From 16aa53a928580163dca89b15ff5371bf7f80e1bc Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Mon, 17 Jan 2022 10:35:34 +0000
Subject: [PATCH 014/196] Add security tag to java/random-used-once
Raised in https://github.com/github/codeql/issues/7601, this is one of the only .ql files that has a security-severity score but not the tag "security", including many other queries that live outside the `Security/` subdirectory.
Besides this the only other files with this security-severity-but-no-security-tag combination are:
```
java/ql/src/Frameworks/JavaEE/EJB/EjbContainerInterference.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbFileIO.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbNative.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbReflection.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbSecurityConfiguration.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbSerialization.ql
java/ql/src/Frameworks/JavaEE/EJB/EjbSetSocketOrUrlFactory.ql
```
Given their location I'm assuming these queries are disabled by default and likely shouldn't changed?
---
java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
index f502d07440f..6bf44839dd4 100644
--- a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
+++ b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
@@ -9,6 +9,7 @@
* @id java/random-used-once
* @tags reliability
* maintainability
+ * security
* external/cwe/cwe-335
*/
From c17bd2964093f1d7b31a4bb6177478057b79d660 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:39:54 +0100
Subject: [PATCH 015/196] C#: Rename C# code file and update test.
---
.../csharp10/{RecordTypeSealedToString.cs => RecordTypes.cs} | 0
.../library-tests/csharp10/recordTypeSealedToString.expected | 2 +-
2 files changed, 1 insertion(+), 1 deletion(-)
rename csharp/ql/test/library-tests/csharp10/{RecordTypeSealedToString.cs => RecordTypes.cs} (100%)
diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
similarity index 100%
rename from csharp/ql/test/library-tests/csharp10/RecordTypeSealedToString.cs
rename to csharp/ql/test/library-tests/csharp10/RecordTypes.cs
diff --git a/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected b/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected
index c8f326c449c..1da3b58b9e3 100644
--- a/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected
+++ b/csharp/ql/test/library-tests/csharp10/recordTypeSealedToString.expected
@@ -1 +1 @@
-| RecordTypeSealedToString.cs:5:35:5:42 | ToString |
+| RecordTypes.cs:5:35:5:42 | ToString |
From dc76775d07041e5bdac73a326a40852536b1c07d Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:43:33 +0100
Subject: [PATCH 016/196] C#: Consider 'record' a type modifier in the
extractor (it can be applied to both class and struct).
---
csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs
index 3d6cb01837e..a94f0b54747 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Modifier.cs
@@ -111,6 +111,9 @@ namespace Semmle.Extraction.CSharp.Entities
if (nt is null)
throw new InternalError(symbol, "Symbol kind is inconsistent with its type");
+ if (nt.IsRecord)
+ HasModifier(cx, trapFile, key, "record");
+
if (nt.TypeKind == TypeKind.Struct)
{
if (nt.IsReadOnly)
From 55cb2aa1604dfe895a01ef9b90bee54d8d492f1e Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:45:27 +0100
Subject: [PATCH 017/196] C#: Use modifier to decide, if a type is a record
like type and implement support for record struct types.
---
csharp/ql/lib/semmle/code/cil/Types.qll | 2 +-
csharp/ql/lib/semmle/code/csharp/Type.qll | 16 ++++++++++++++++
2 files changed, 17 insertions(+), 1 deletion(-)
diff --git a/csharp/ql/lib/semmle/code/cil/Types.qll b/csharp/ql/lib/semmle/code/cil/Types.qll
index 1dfaa0191a1..6bb980d6a87 100644
--- a/csharp/ql/lib/semmle/code/cil/Types.qll
+++ b/csharp/ql/lib/semmle/code/cil/Types.qll
@@ -61,7 +61,7 @@ class Class extends ValueOrRefType {
}
/** A `record`. */
-class Record extends Class {
+deprecated class Record extends Class {
Record() { this.isRecord() }
}
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index 5aeaeb904d5..ac7e3390a5d 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -372,6 +372,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
nested_types(this, _, result)
}
+ override predicate isRecord() { this.hasModifier("record") }
+
override string toString() { result = Type.super.toString() }
}
@@ -711,6 +713,20 @@ class Struct extends ValueType, @struct_type {
override string getAPrimaryQlClass() { result = "Struct" }
}
+/**
+ * A `record struct`, for example
+ * ```csharp
+ * record struct RS {
+ * ...
+ * }
+ * ```
+ */
+class RecordStruct extends Struct {
+ RecordStruct() { this.isRecord() }
+
+ override string getAPrimaryQlClass() { result = "RecordStruct" }
+}
+
/**
* A reference type.
*
From 9770f098397bc2aec0f3c7fed70fa851663884d4 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 14:00:39 +0100
Subject: [PATCH 018/196] C#: Deprecate Record and introduce RecordClass
instead. Also make flow summary support for record struct constructors.
---
csharp/ql/lib/semmle/code/csharp/Type.qll | 28 +++++++++++++++----
.../code/csharp/dataflow/FlowSummary.qll | 2 +-
.../ql/lib/semmle/code/csharp/exprs/Expr.qll | 4 ++-
.../library-tests/csharp9/PrintAst.expected | 20 ++++++-------
.../ql/test/library-tests/csharp9/record.ql | 4 +--
.../dataflow/tuples/PrintAst.expected | 2 +-
6 files changed, 40 insertions(+), 20 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index ac7e3390a5d..57db0fa11a7 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -451,6 +451,14 @@ class SimpleType extends ValueType, @simple_type {
override SystemNamespace getDeclaringNamespace() { any() }
}
+/**
+ * A `record` like type.
+ * This can be either a `class` or a `struct`.
+ */
+abstract class RecordType extends ValueOrRefType {
+ RecordType() { this.isRecord() }
+}
+
/**
* The Boolean type, `bool`.
*/
@@ -721,7 +729,7 @@ class Struct extends ValueType, @struct_type {
* }
* ```
*/
-class RecordStruct extends Struct {
+class RecordStruct extends RecordType, Struct {
RecordStruct() { this.isRecord() }
override string getAPrimaryQlClass() { result = "RecordStruct" }
@@ -781,6 +789,18 @@ class Class extends RefType, @class_type {
override string getAPrimaryQlClass() { result = "Class" }
}
+/**
+ * DEPRECATED: Use `RecordClass` instead.
+ */
+deprecated class Record extends Class {
+ Record() { this.isRecord() }
+
+ /** Gets the clone method of this record. */
+ RecordCloneMethod getCloneMethod() { result = this.getAMember() }
+
+ override string getAPrimaryQlClass() { result = "Record" }
+}
+
/**
* A `record`, for example
*
@@ -790,13 +810,11 @@ class Class extends RefType, @class_type {
* }
* ```
*/
-class Record extends Class {
- Record() { this.isRecord() }
-
+class RecordClass extends RecordType, Class {
/** Gets the clone method of this record. */
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
- override string getAPrimaryQlClass() { result = "Record" }
+ override string getAPrimaryQlClass() { result = "RecordClass" }
}
/**
diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll
index 94b3d8d7d4d..270991757f6 100644
--- a/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll
+++ b/csharp/ql/lib/semmle/code/csharp/dataflow/FlowSummary.qll
@@ -111,7 +111,7 @@ module SummaryComponentStack {
class SummarizedCallable = Impl::Public::SummarizedCallable;
private predicate recordConstructorFlow(Constructor c, int i, Property p) {
- c = any(Record r).getAMember() and
+ c = any(RecordType r).getAMember() and
exists(string name |
c.getParameter(i).getName() = name and
c.getDeclaringType().getAMember(name) = p
diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
index 1007d2cefe6..1a869f2458c 100644
--- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
+++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll
@@ -1175,7 +1175,9 @@ class WithExpr extends Expr, @with_expr {
Expr getExpr() { result = this.getChild(0) }
/** Gets the clone method of the `record` that is targetted by this `with` expression. */
- RecordCloneMethod getCloneMethod() { result = this.getExpr().getType().(Record).getCloneMethod() }
+ RecordCloneMethod getCloneMethod() {
+ result = this.getExpr().getType().(RecordClass).getCloneMethod()
+ }
override string toString() { result = "... with { ... }" }
diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
index cb6414d9bb4..5c76d399ed2 100644
--- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
@@ -776,7 +776,7 @@ ParenthesizedPattern.cs:
# 26| 0: [TypeMention] string
# 26| 2: [IntLiteral] 5
Record.cs:
-# 4| [Record] Person
+# 4| [Record,RecordClass] Person
# 4| 11: [NEOperator] !=
#-----| 2: (Parameters)
# 4| 0: [Parameter] left
@@ -806,7 +806,7 @@ Record.cs:
# 9| 1: [TupleExpr] (..., ...)
# 9| 0: [ParameterAccess] access to parameter first
# 9| 1: [ParameterAccess] access to parameter last
-# 12| [Record] Teacher
+# 12| [Record,RecordClass] Teacher
# 12| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 12| 0: [Parameter] left
@@ -834,7 +834,7 @@ Record.cs:
# 17| 4: [AssignExpr] ... = ...
# 17| 0: [PropertyCall] access to property Subject
# 17| 1: [ParameterAccess] access to parameter sub
-# 20| [Record] Student
+# 20| [Record,RecordClass] Student
# 20| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 20| 0: [Parameter] left
@@ -862,7 +862,7 @@ Record.cs:
# 24| 4: [AssignExpr] ... = ...
# 24| 0: [PropertyCall] access to property Level
# 24| 1: [ParameterAccess] access to parameter level
-# 27| [Record] Person1
+# 27| [Record,RecordClass] Person1
# 27| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 27| 0: [Parameter] left
@@ -889,7 +889,7 @@ Record.cs:
# 27| 4: [Setter] set_LastName
#-----| 2: (Parameters)
# 27| 0: [Parameter] value
-# 29| [Record] Teacher1
+# 29| [Record,RecordClass] Teacher1
# 29| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 29| 0: [Parameter] left
@@ -913,7 +913,7 @@ Record.cs:
# 29| 4: [Setter] set_Subject
#-----| 2: (Parameters)
# 29| 0: [Parameter] value
-# 32| [Record] Student1
+# 32| [Record,RecordClass] Student1
# 32| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 32| 0: [Parameter] left
@@ -937,7 +937,7 @@ Record.cs:
# 32| 4: [Setter] set_Level
#-----| 2: (Parameters)
# 32| 0: [Parameter] value
-# 35| [Record] Pet
+# 35| [Record,RecordClass] Pet
# 35| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 35| 0: [Parameter] left
@@ -963,7 +963,7 @@ Record.cs:
# 38| -1: [TypeAccess] access to type Console
# 38| 0: [TypeMention] Console
# 38| 0: [StringLiteral] "Shredding furniture"
-# 41| [Record] Dog
+# 41| [Record,RecordClass] Dog
# 41| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 41| 0: [Parameter] left
@@ -1002,7 +1002,7 @@ Record.cs:
# 50| 0: [MethodCall] call to method ToString
# 50| -1: [LocalVariableAccess] access to local variable s
# 50| 1: [StringLiteral] " is a dog"
-# 54| [Record] R1
+# 54| [Record,RecordClass] R1
# 54| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 54| 0: [Parameter] left
@@ -1022,7 +1022,7 @@ Record.cs:
# 54| 4: [Setter] set_A
#-----| 2: (Parameters)
# 54| 0: [Parameter] value
-# 56| [Record] R2
+# 56| [Record,RecordClass] R2
# 56| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 56| 0: [Parameter] left
diff --git a/csharp/ql/test/library-tests/csharp9/record.ql b/csharp/ql/test/library-tests/csharp9/record.ql
index 9a8da357d69..7fc45550365 100644
--- a/csharp/ql/test/library-tests/csharp9/record.ql
+++ b/csharp/ql/test/library-tests/csharp9/record.ql
@@ -1,6 +1,6 @@
import csharp
-query predicate records(Record t, string i, RecordCloneMethod clone) {
+query predicate records(RecordClass t, string i, RecordCloneMethod clone) {
t.getABaseInterface().toStringWithTypes() = i and
clone = t.getCloneMethod() and
t.fromSource()
@@ -10,7 +10,7 @@ private string getMemberName(Member m) {
result = m.getDeclaringType().getQualifiedName() + "." + m.toStringWithTypes()
}
-query predicate members(Record t, string ms, string l) {
+query predicate members(RecordClass t, string ms, string l) {
t.fromSource() and
exists(Member m | t.hasMember(m) |
ms = getMemberName(m) and
diff --git a/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected b/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected
index bfec8378220..6b509daa1bb 100644
--- a/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected
+++ b/csharp/ql/test/library-tests/dataflow/tuples/PrintAst.expected
@@ -281,7 +281,7 @@ Tuples.cs:
# 81| 2: [ExprStmt] ...;
# 81| 0: [MethodCall] call to method Sink
# 81| 0: [LocalVariableAccess] access to local variable q
-# 85| 9: [Record] R1
+# 85| 9: [RecordClass] R1
# 85| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 85| 0: [Parameter] left
From 746fd603d8fd53f6be539a117b046d55e5cb690b Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 14:01:45 +0100
Subject: [PATCH 019/196] C#: Add flow summary test for record struct
constructors.
---
.../dataflow/fields/FieldFlow.expected | 123 ++++++++++--------
.../test/library-tests/dataflow/fields/J.cs | 14 +-
2 files changed, 83 insertions(+), 54 deletions(-)
diff --git a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected
index 14e2c3d27b7..3ca4859dbed 100644
--- a/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected
+++ b/csharp/ql/test/library-tests/dataflow/fields/FieldFlow.expected
@@ -776,28 +776,36 @@ edges
| I.cs:39:9:39:9 | access to parameter i [field Field1] : Object | I.cs:40:14:40:14 | access to parameter i [field Field1] : Object |
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | I.cs:40:14:40:21 | access to field Field1 |
-| J.cs:12:17:12:33 | call to method Source : Object | J.cs:13:29:13:29 | access to local variable o : Object |
-| J.cs:12:17:12:33 | call to method Source : Object | J.cs:13:29:13:29 | access to local variable o : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | J.cs:14:14:14:21 | access to property Prop1 |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | J.cs:18:14:18:21 | access to property Prop1 |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | J.cs:22:14:22:21 | access to property Prop1 |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | J.cs:23:14:23:21 | access to property Prop2 |
+| J.cs:14:17:14:33 | call to method Source : Object | J.cs:15:34:15:34 | access to local variable o : Object |
+| J.cs:14:17:14:33 | call to method Source : Object | J.cs:15:34:15:34 | access to local variable o : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | J.cs:16:14:16:21 | access to property Prop1 |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | J.cs:16:14:16:21 | access to property Prop1 |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | J.cs:20:14:20:21 | access to property Prop1 |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | J.cs:20:14:20:21 | access to property Prop1 |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | J.cs:24:14:24:21 | access to property Prop1 |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | J.cs:24:14:24:21 | access to property Prop1 |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | J.cs:25:14:25:21 | access to property Prop2 |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | J.cs:25:14:25:21 | access to property Prop2 |
+| J.cs:34:17:34:33 | call to method Source : Object | J.cs:35:35:35:35 | access to local variable o : Object |
+| J.cs:34:17:34:33 | call to method Source : Object | J.cs:35:35:35:35 | access to local variable o : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | J.cs:36:14:36:21 | access to property Prop1 |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | J.cs:36:14:36:21 | access to property Prop1 |
nodes
| A.cs:5:17:5:28 | call to method Source : C | semmle.label | call to method Source : C |
| A.cs:5:17:5:28 | call to method Source : C | semmle.label | call to method Source : C |
@@ -1637,32 +1645,42 @@ nodes
| I.cs:40:14:40:14 | access to parameter i [field Field1] : Object | semmle.label | access to parameter i [field Field1] : Object |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
| I.cs:40:14:40:21 | access to field Field1 | semmle.label | access to field Field1 |
-| J.cs:12:17:12:33 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:12:17:12:33 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object |
-| J.cs:13:18:13:36 | object creation of type Record [property Prop1] : Object | semmle.label | object creation of type Record [property Prop1] : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object |
-| J.cs:13:29:13:29 | access to local variable o : Object | semmle.label | access to local variable o : Object |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
-| J.cs:14:14:14:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
-| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:14:14:14:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
-| J.cs:18:14:18:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
-| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:18:14:18:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
-| J.cs:21:18:21:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:21:36:21:52 | call to method Source : Object | semmle.label | call to method Source : Object |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
-| J.cs:22:14:22:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
-| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:22:14:22:21 | access to property Prop1 | semmle.label | access to property Prop1 |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
-| J.cs:23:14:23:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
-| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
-| J.cs:23:14:23:21 | access to property Prop2 | semmle.label | access to property Prop2 |
+| J.cs:14:17:14:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:14:17:14:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:15:18:15:41 | object creation of type RecordClass [property Prop1] : Object | semmle.label | object creation of type RecordClass [property Prop1] : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:15:34:15:34 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:16:14:16:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:16:14:16:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:16:14:16:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
+| J.cs:20:14:20:15 | access to local variable r2 [property Prop1] : Object | semmle.label | access to local variable r2 [property Prop1] : Object |
+| J.cs:20:14:20:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:20:14:20:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
+| J.cs:23:18:23:54 | ... with { ... } [property Prop2] : Object | semmle.label | ... with { ... } [property Prop2] : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:23:36:23:52 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
+| J.cs:24:14:24:15 | access to local variable r3 [property Prop1] : Object | semmle.label | access to local variable r3 [property Prop1] : Object |
+| J.cs:24:14:24:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:24:14:24:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
+| J.cs:25:14:25:15 | access to local variable r3 [property Prop2] : Object | semmle.label | access to local variable r3 [property Prop2] : Object |
+| J.cs:25:14:25:21 | access to property Prop2 | semmle.label | access to property Prop2 |
+| J.cs:25:14:25:21 | access to property Prop2 | semmle.label | access to property Prop2 |
+| J.cs:34:17:34:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:34:17:34:33 | call to method Source : Object | semmle.label | call to method Source : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:35:18:35:42 | object creation of type RecordStruct [property Prop1] : Object | semmle.label | object creation of type RecordStruct [property Prop1] : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:35:35:35:35 | access to local variable o : Object | semmle.label | access to local variable o : Object |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:36:14:36:15 | access to local variable r1 [property Prop1] : Object | semmle.label | access to local variable r1 [property Prop1] : Object |
+| J.cs:36:14:36:21 | access to property Prop1 | semmle.label | access to property Prop1 |
+| J.cs:36:14:36:21 | access to property Prop1 | semmle.label | access to property Prop1 |
subpaths
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
| A.cs:6:24:6:24 | access to local variable c : C | A.cs:147:32:147:32 | c : C | A.cs:149:20:149:27 | object creation of type B [field c] : C | A.cs:6:17:6:25 | call to method Make [field c] : C |
@@ -1815,7 +1833,8 @@ subpaths
| I.cs:23:14:23:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source : Object | I.cs:23:14:23:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source : Object | call to method Source : Object |
| I.cs:27:14:27:21 | access to field Field1 | I.cs:7:18:7:34 | call to method Source : Object | I.cs:27:14:27:21 | access to field Field1 | $@ | I.cs:7:18:7:34 | call to method Source : Object | call to method Source : Object |
| I.cs:40:14:40:21 | access to field Field1 | I.cs:31:13:31:29 | call to method Source : Object | I.cs:40:14:40:21 | access to field Field1 | $@ | I.cs:31:13:31:29 | call to method Source : Object | call to method Source : Object |
-| J.cs:14:14:14:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:14:14:14:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object |
-| J.cs:18:14:18:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:18:14:18:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object |
-| J.cs:22:14:22:21 | access to property Prop1 | J.cs:12:17:12:33 | call to method Source : Object | J.cs:22:14:22:21 | access to property Prop1 | $@ | J.cs:12:17:12:33 | call to method Source : Object | call to method Source : Object |
-| J.cs:23:14:23:21 | access to property Prop2 | J.cs:21:36:21:52 | call to method Source : Object | J.cs:23:14:23:21 | access to property Prop2 | $@ | J.cs:21:36:21:52 | call to method Source : Object | call to method Source : Object |
+| J.cs:16:14:16:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source : Object | J.cs:16:14:16:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source : Object | call to method Source : Object |
+| J.cs:20:14:20:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source : Object | J.cs:20:14:20:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source : Object | call to method Source : Object |
+| J.cs:24:14:24:21 | access to property Prop1 | J.cs:14:17:14:33 | call to method Source : Object | J.cs:24:14:24:21 | access to property Prop1 | $@ | J.cs:14:17:14:33 | call to method Source : Object | call to method Source : Object |
+| J.cs:25:14:25:21 | access to property Prop2 | J.cs:23:36:23:52 | call to method Source : Object | J.cs:25:14:25:21 | access to property Prop2 | $@ | J.cs:23:36:23:52 | call to method Source : Object | call to method Source : Object |
+| J.cs:36:14:36:21 | access to property Prop1 | J.cs:34:17:34:33 | call to method Source : Object | J.cs:36:14:36:21 | access to property Prop1 | $@ | J.cs:34:17:34:33 | call to method Source : Object | call to method Source : Object |
diff --git a/csharp/ql/test/library-tests/dataflow/fields/J.cs b/csharp/ql/test/library-tests/dataflow/fields/J.cs
index b53cdb2e97e..8ac0404cd99 100644
--- a/csharp/ql/test/library-tests/dataflow/fields/J.cs
+++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs
@@ -3,14 +3,16 @@ namespace System.Runtime.CompilerServices
internal static class IsExternalInit { }
}
-public record Record(object Prop1, object Prop2) { }
+public record class RecordClass(object Prop1, object Prop2) { }
+
+public record struct RecordStruct(object Prop1, object Prop2) { }
public class J
{
private void M1()
{
var o = Source(1);
- var r1 = new Record(o, null);
+ var r1 = new RecordClass(o, null);
Sink(r1.Prop1); // $ hasValueFlow=1
Sink(r1.Prop2); // no flow
@@ -27,6 +29,14 @@ public class J
Sink(r4.Prop2); // no flow
}
+ private void M2()
+ {
+ var o = Source(1);
+ var r1 = new RecordStruct(o, null);
+ Sink(r1.Prop1); // $ hasValueFlow=1
+ Sink(r1.Prop2); // no flow
+ }
+
public static void Sink(object o) { }
static T Source(object source) => throw null;
From 6c1bb4a3a9c9a9447f8804f2b4f1058f528e5cc7 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Fri, 14 Jan 2022 16:49:44 +0100
Subject: [PATCH 020/196] C#: Add test case for record class and record
structs.
---
csharp/ql/test/library-tests/csharp10/RecordTypes.cs | 8 +++++++-
.../test/library-tests/csharp10/recordTypes.expected | 11 +++++++++++
csharp/ql/test/library-tests/csharp10/recordTypes.ql | 7 +++++++
3 files changed, 25 insertions(+), 1 deletion(-)
create mode 100644 csharp/ql/test/library-tests/csharp10/recordTypes.expected
create mode 100644 csharp/ql/test/library-tests/csharp10/recordTypes.ql
diff --git a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
index 14dc3d77138..92ad18085f0 100644
--- a/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
+++ b/csharp/ql/test/library-tests/csharp10/RecordTypes.cs
@@ -3,4 +3,10 @@ using System;
public record MyEntry(string Name, string Address)
{
sealed public override string ToString() => $"{Name} lives at {Address}";
-};
\ No newline at end of file
+};
+
+public record class MyClassRecord(DateTime stuff) { }
+
+public readonly record struct MyReadonlyRecordStruct(string Stuff) { }
+
+public record struct MyRecordStruct(int Stuff) { }
diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.expected b/csharp/ql/test/library-tests/csharp10/recordTypes.expected
new file mode 100644
index 00000000000..75cef2ac7e7
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/recordTypes.expected
@@ -0,0 +1,11 @@
+recordTypes
+| RecordTypes.cs:3:1:6:2 | MyEntry |
+| RecordTypes.cs:8:1:8:53 | MyClassRecord |
+| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct |
+| RecordTypes.cs:12:1:12:50 | MyRecordStruct |
+recordStructs
+| RecordTypes.cs:10:1:10:70 | MyReadonlyRecordStruct |
+| RecordTypes.cs:12:1:12:50 | MyRecordStruct |
+recordClass
+| RecordTypes.cs:3:1:6:2 | MyEntry |
+| RecordTypes.cs:8:1:8:53 | MyClassRecord |
diff --git a/csharp/ql/test/library-tests/csharp10/recordTypes.ql b/csharp/ql/test/library-tests/csharp10/recordTypes.ql
new file mode 100644
index 00000000000..1f96dab12da
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/recordTypes.ql
@@ -0,0 +1,7 @@
+import csharp
+
+query predicate recordTypes(RecordType rt) { any() }
+
+query predicate recordStructs(RecordStruct rs) { any() }
+
+query predicate recordClass(RecordClass r) { any() }
From b927aad6ed214e28148cf4984db6217571b5d6f0 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 14:43:21 +0100
Subject: [PATCH 021/196] C#: Address review comments related to record
structs.
---
csharp/ql/lib/semmle/code/csharp/Type.qll | 6 +-----
.../library-tests/csharp9/PrintAst.expected | 20 +++++++++----------
.../test/library-tests/dataflow/fields/J.cs | 4 ++--
3 files changed, 13 insertions(+), 17 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/Type.qll b/csharp/ql/lib/semmle/code/csharp/Type.qll
index 57db0fa11a7..c7f1515990b 100644
--- a/csharp/ql/lib/semmle/code/csharp/Type.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Type.qll
@@ -455,7 +455,7 @@ class SimpleType extends ValueType, @simple_type {
* A `record` like type.
* This can be either a `class` or a `struct`.
*/
-abstract class RecordType extends ValueOrRefType {
+class RecordType extends ValueOrRefType {
RecordType() { this.isRecord() }
}
@@ -730,8 +730,6 @@ class Struct extends ValueType, @struct_type {
* ```
*/
class RecordStruct extends RecordType, Struct {
- RecordStruct() { this.isRecord() }
-
override string getAPrimaryQlClass() { result = "RecordStruct" }
}
@@ -797,8 +795,6 @@ deprecated class Record extends Class {
/** Gets the clone method of this record. */
RecordCloneMethod getCloneMethod() { result = this.getAMember() }
-
- override string getAPrimaryQlClass() { result = "Record" }
}
/**
diff --git a/csharp/ql/test/library-tests/csharp9/PrintAst.expected b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
index 5c76d399ed2..e346a782c4f 100644
--- a/csharp/ql/test/library-tests/csharp9/PrintAst.expected
+++ b/csharp/ql/test/library-tests/csharp9/PrintAst.expected
@@ -776,7 +776,7 @@ ParenthesizedPattern.cs:
# 26| 0: [TypeMention] string
# 26| 2: [IntLiteral] 5
Record.cs:
-# 4| [Record,RecordClass] Person
+# 4| [RecordClass] Person
# 4| 11: [NEOperator] !=
#-----| 2: (Parameters)
# 4| 0: [Parameter] left
@@ -806,7 +806,7 @@ Record.cs:
# 9| 1: [TupleExpr] (..., ...)
# 9| 0: [ParameterAccess] access to parameter first
# 9| 1: [ParameterAccess] access to parameter last
-# 12| [Record,RecordClass] Teacher
+# 12| [RecordClass] Teacher
# 12| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 12| 0: [Parameter] left
@@ -834,7 +834,7 @@ Record.cs:
# 17| 4: [AssignExpr] ... = ...
# 17| 0: [PropertyCall] access to property Subject
# 17| 1: [ParameterAccess] access to parameter sub
-# 20| [Record,RecordClass] Student
+# 20| [RecordClass] Student
# 20| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 20| 0: [Parameter] left
@@ -862,7 +862,7 @@ Record.cs:
# 24| 4: [AssignExpr] ... = ...
# 24| 0: [PropertyCall] access to property Level
# 24| 1: [ParameterAccess] access to parameter level
-# 27| [Record,RecordClass] Person1
+# 27| [RecordClass] Person1
# 27| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 27| 0: [Parameter] left
@@ -889,7 +889,7 @@ Record.cs:
# 27| 4: [Setter] set_LastName
#-----| 2: (Parameters)
# 27| 0: [Parameter] value
-# 29| [Record,RecordClass] Teacher1
+# 29| [RecordClass] Teacher1
# 29| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 29| 0: [Parameter] left
@@ -913,7 +913,7 @@ Record.cs:
# 29| 4: [Setter] set_Subject
#-----| 2: (Parameters)
# 29| 0: [Parameter] value
-# 32| [Record,RecordClass] Student1
+# 32| [RecordClass] Student1
# 32| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 32| 0: [Parameter] left
@@ -937,7 +937,7 @@ Record.cs:
# 32| 4: [Setter] set_Level
#-----| 2: (Parameters)
# 32| 0: [Parameter] value
-# 35| [Record,RecordClass] Pet
+# 35| [RecordClass] Pet
# 35| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 35| 0: [Parameter] left
@@ -963,7 +963,7 @@ Record.cs:
# 38| -1: [TypeAccess] access to type Console
# 38| 0: [TypeMention] Console
# 38| 0: [StringLiteral] "Shredding furniture"
-# 41| [Record,RecordClass] Dog
+# 41| [RecordClass] Dog
# 41| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 41| 0: [Parameter] left
@@ -1002,7 +1002,7 @@ Record.cs:
# 50| 0: [MethodCall] call to method ToString
# 50| -1: [LocalVariableAccess] access to local variable s
# 50| 1: [StringLiteral] " is a dog"
-# 54| [Record,RecordClass] R1
+# 54| [RecordClass] R1
# 54| 12: [NEOperator] !=
#-----| 2: (Parameters)
# 54| 0: [Parameter] left
@@ -1022,7 +1022,7 @@ Record.cs:
# 54| 4: [Setter] set_A
#-----| 2: (Parameters)
# 54| 0: [Parameter] value
-# 56| [Record,RecordClass] R2
+# 56| [RecordClass] R2
# 56| 13: [NEOperator] !=
#-----| 2: (Parameters)
# 56| 0: [Parameter] left
diff --git a/csharp/ql/test/library-tests/dataflow/fields/J.cs b/csharp/ql/test/library-tests/dataflow/fields/J.cs
index 8ac0404cd99..4353d646b49 100644
--- a/csharp/ql/test/library-tests/dataflow/fields/J.cs
+++ b/csharp/ql/test/library-tests/dataflow/fields/J.cs
@@ -31,9 +31,9 @@ public class J
private void M2()
{
- var o = Source(1);
+ var o = Source(2);
var r1 = new RecordStruct(o, null);
- Sink(r1.Prop1); // $ hasValueFlow=1
+ Sink(r1.Prop1); // $ hasValueFlow=2
Sink(r1.Prop2); // no flow
}
From c1a51d94a2b28fa361cff02a82914f57add7850c Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Mon, 17 Jan 2022 17:44:52 +0000
Subject: [PATCH 022/196] Ruby: add test for protect_from_forgery without
exception strategy
---
.../cwe-352/CSRFProtectionDisabled.expected | 9 +++++----
.../app/controllers/application_controller.rb | 18 ++++++++++++++++++
.../app/controllers/articles_controller.rb | 15 +++++++++++++++
.../app/controllers/users_controller.rb | 2 +-
4 files changed, 39 insertions(+), 5 deletions(-)
create mode 100644 ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
diff --git a/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected b/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected
index c51f71a04d3..d80c52afc66 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected
+++ b/ruby/ql/test/query-tests/security/cwe-352/CSRFProtectionDisabled.expected
@@ -1,4 +1,5 @@
-| railsapp/app/controllers/users_controller.rb:4:3:4:47 | call to skip_before_action | Potential CSRF vulnerability due to forgery protection being disabled. |
-| railsapp/config/application.rb:15:5:15:53 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled. |
-| railsapp/config/environments/development.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled. |
-| railsapp/config/environments/production.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled. |
+| railsapp/app/controllers/application_controller.rb:5:3:5:22 | call to protect_from_forgery | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/app/controllers/users_controller.rb:4:3:4:47 | call to skip_before_action | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/config/application.rb:15:5:15:53 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/config/environments/development.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
+| railsapp/config/environments/production.rb:5:3:5:51 | call to allow_forgery_protection= | Potential CSRF vulnerability due to forgery protection being disabled or weakened. |
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb
index 09705d12ab4..6ff599938e8 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/application_controller.rb
@@ -1,2 +1,20 @@
class ApplicationController < ActionController::Base
+
+ # BAD: `protect_from_forgery` without `with: :exception` can expose an
+ # application to CSRF attacks in some circumstances
+ protect_from_forgery
+
+ before_action authz_guard
+
+ def current_user
+ @current_user ||= User.find_by_id(session[:user_id])
+ end
+
+ def logged_in?
+ !current_user.nil?
+ end
+
+ def authz_guard
+ render(plain: "not logged in") unless logged_in?
+ end
end
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
new file mode 100644
index 00000000000..2a0037f4b25
--- /dev/null
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
@@ -0,0 +1,15 @@
+class ArticlesController < ApplicationController
+ prepend_before_action :user_authored_article?, only: [:delete_authored_article]
+
+ def delete_authored_article
+ article.destroy
+ end
+
+ def article
+ @article ||= Article.find(params[:article_id])
+ end
+
+ def user_authored_article?
+ @article.author_id = current_user.id
+ end
+end
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb
index 138a342b3cb..596a7b0108f 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/users_controller.rb
@@ -4,7 +4,7 @@ class UsersController < ApplicationController
skip_before_action :verify_authenticity_token
def change_email
- user = User.find_by(name: params[:user_name])
+ user = current_user
user.email = params[:new_email]
user.save!
end
From c9467d7e94e36f0a02b5f9dcfec4fb8fb75bcab7 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:32:17 +0100
Subject: [PATCH 023/196] C#: Add new tables to the dbscheme line span pragma.
---
csharp/ql/lib/semmlecode.csharp.dbscheme | 16 +++++++++++++---
1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme b/csharp/ql/lib/semmlecode.csharp.dbscheme
index 193c35b0e37..ff083666c7f 100644
--- a/csharp/ql/lib/semmlecode.csharp.dbscheme
+++ b/csharp/ql/lib/semmlecode.csharp.dbscheme
@@ -385,7 +385,7 @@ directive_endregions(
directive_lines(
unique int id: @directive_line,
- int kind: int ref); /* 0: default, 1: hidden, 2: numeric */
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
directive_line_value(
unique int id: @directive_line ref,
@@ -393,8 +393,18 @@ directive_line_value(
directive_line_file(
unique int id: @directive_line ref,
- int file: @file ref
-)
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
directive_nullables(
unique int id: @directive_nullable,
From a197befb5f997a6235929f2f5c69643db94735f1 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:35:03 +0100
Subject: [PATCH 024/196] C#: Add shared base class for line and line span
pragmas.
---
.../LineOrSpanDirective.cs | 32 +++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
new file mode 100644
index 00000000000..546e1571596
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
@@ -0,0 +1,32 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.IO;
+
+namespace Semmle.Extraction.CSharp.Entities
+{
+ internal enum LineDirectiveKind
+ {
+ Default = 0,
+ Hidden = 1,
+ Numeric = 2,
+ Span = 3
+ }
+
+ internal abstract class LineOrSpanDirective : PreprocessorDirective where T : LineOrSpanDirectiveTriviaSyntax
+ {
+ protected LineOrSpanDirective(Context cx, T trivia)
+ : base(cx, trivia)
+ {
+ }
+
+ protected override void PopulatePreprocessor(TextWriter trapFile)
+ {
+ if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText))
+ {
+ var file = File.Create(Context, Symbol.File.ValueText);
+ trapFile.directive_line_file(this, file);
+ }
+ }
+ }
+}
From 195d40c04e33fc0c26cae654c4d6da8d672c23f7 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:37:10 +0100
Subject: [PATCH 025/196] C#: Add new class needed for LineSpanDirective and
modify existing implementation to use the new types.
---
.../PreprocessorDirectives/LineDirective.cs | 16 +++-----
.../LineSpanDirective.cs | 40 +++++++++++++++++++
.../Semmle.Extraction.CSharp/Tuples.cs | 12 ++++--
3 files changed, 55 insertions(+), 13 deletions(-)
create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
index 6afae54a129..d4075a6f4a9 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
@@ -5,7 +5,7 @@ using System.IO;
namespace Semmle.Extraction.CSharp.Entities
{
- internal class LineDirective : PreprocessorDirective
+ internal class LineDirective : LineOrSpanDirective
{
private LineDirective(Context cx, LineDirectiveTriviaSyntax trivia)
: base(cx, trivia)
@@ -16,9 +16,9 @@ namespace Semmle.Extraction.CSharp.Entities
{
var type = Symbol.Line.Kind() switch
{
- SyntaxKind.DefaultKeyword => 0,
- SyntaxKind.HiddenKeyword => 1,
- SyntaxKind.NumericLiteralToken => 2,
+ SyntaxKind.DefaultKeyword => LineDirectiveKind.Default,
+ SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden,
+ SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric,
_ => throw new InternalError(Symbol, "Unhandled line token kind")
};
@@ -28,13 +28,9 @@ namespace Semmle.Extraction.CSharp.Entities
{
var value = (int)Symbol.Line.Value!;
trapFile.directive_line_value(this, value);
-
- if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText))
- {
- var file = File.Create(Context, Symbol.File.ValueText);
- trapFile.directive_line_file(this, file);
- }
}
+
+ base.PopulatePreprocessor(trapFile);
}
public static LineDirective Create(Context cx, LineDirectiveTriviaSyntax line) =>
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
new file mode 100644
index 00000000000..7d8396d7b04
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
@@ -0,0 +1,40 @@
+using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.Syntax;
+using System.IO;
+
+namespace Semmle.Extraction.CSharp.Entities
+{
+ internal class LineSpanDirective : LineOrSpanDirective
+ {
+ private LineSpanDirective(Context cx, LineSpanDirectiveTriviaSyntax trivia)
+ : base(cx, trivia) { }
+ public static LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax line) =>
+ LineSpanDirectiveFactory.Instance.CreateEntity(cx, line, line);
+
+ protected override void PopulatePreprocessor(TextWriter trapFile)
+ {
+ trapFile.directive_lines(this, LineDirectiveKind.Span);
+
+ var startLine = (int)Symbol.Start.Line.Value!;
+ var startColumn = (int)Symbol.Start.Character.Value!;
+ var endLine = (int)Symbol.End.Line.Value!;
+ var endColumn = (int)Symbol.End.Character.Value!;
+ trapFile.directive_line_span(this, startLine, startColumn, endLine, endColumn);
+
+ var offset = Symbol.CharacterOffset.Value;
+ if (offset is not null)
+ {
+ trapFile.directive_line_offset(this, (int)offset);
+ }
+ base.PopulatePreprocessor(trapFile);
+ }
+
+ private class LineSpanDirectiveFactory : CachedEntityFactory
+ {
+ public static LineSpanDirectiveFactory Instance { get; } = new LineSpanDirectiveFactory();
+
+ public override LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax init) => new(cx, init);
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
index 028a0259a55..225c11ada22 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
@@ -413,15 +413,21 @@ namespace Semmle.Extraction.CSharp
internal static void directive_nullables(this TextWriter trapFile, NullableDirective directive, int setting, int target) =>
trapFile.WriteTuple("directive_nullables", directive, setting, target);
- internal static void directive_lines(this TextWriter trapFile, LineDirective directive, int kind) =>
- trapFile.WriteTuple("directive_lines", directive, kind);
+ internal static void directive_lines(this TextWriter trapFile, LineOrSpanDirective directive, LineDirectiveKind kind) where T : LineOrSpanDirectiveTriviaSyntax =>
+ trapFile.WriteTuple("directive_lines", directive, (int)kind);
internal static void directive_line_value(this TextWriter trapFile, LineDirective directive, int line) =>
trapFile.WriteTuple("directive_line_value", directive, line);
- internal static void directive_line_file(this TextWriter trapFile, LineDirective directive, Extraction.Entities.File file) =>
+ internal static void directive_line_file(this TextWriter trapFile, LineOrSpanDirective directive, Extraction.Entities.File file) where T : LineOrSpanDirectiveTriviaSyntax =>
trapFile.WriteTuple("directive_line_file", directive, file);
+ internal static void directive_line_offset(this TextWriter trapFile, LineSpanDirective directive, int offset) =>
+ trapFile.WriteTuple("directive_line_offset", directive, offset);
+
+ internal static void directive_line_span(this TextWriter trapFile, LineSpanDirective directive, int startLine, int startColumn, int endLine, int endColumn) =>
+ trapFile.WriteTuple("directive_line_span", directive, startLine, startColumn, endLine, endColumn);
+
internal static void directive_regions(this TextWriter trapFile, RegionDirective directive, string name) =>
trapFile.WriteTuple("directive_regions", directive, name);
From af380f846e79bddc8944e6f40d8c16f6a18c9b6d Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:37:44 +0100
Subject: [PATCH 026/196] C#: Add support in the extractor for the
LineSpanDirective.
---
.../Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs | 3 +++
1 file changed, 3 insertions(+)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
index 49b1e96990a..273853cb320 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
@@ -62,6 +62,9 @@ namespace Semmle.Extraction.CSharp.Populators
Entities.LineDirective.Create(cx, node);
}
+ public override void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) =>
+ Entities.LineSpanDirective.Create(cx, node);
+
private readonly Stack regionStarts = new Stack();
public override void VisitRegionDirectiveTrivia(RegionDirectiveTriviaSyntax node)
From 7e264668d8b7c2cbba814696fdac94d62ec61b0b Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:43:41 +0100
Subject: [PATCH 027/196] C#: Refator directive visitor to use expression body.
---
.../Populators/DirectiveVisitor.cs | 36 +++++--------------
1 file changed, 9 insertions(+), 27 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
index 273853cb320..9df04a7cfa5 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/DirectiveVisitor.cs
@@ -17,50 +17,32 @@ namespace Semmle.Extraction.CSharp.Populators
///
public IEnumerable BranchesTaken => branchesTaken;
- public DirectiveVisitor(Context cx) : base(SyntaxWalkerDepth.StructuredTrivia)
- {
+ public DirectiveVisitor(Context cx) : base(SyntaxWalkerDepth.StructuredTrivia) =>
this.cx = cx;
- }
- public override void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node)
- {
+ public override void VisitPragmaWarningDirectiveTrivia(PragmaWarningDirectiveTriviaSyntax node) =>
Entities.PragmaWarningDirective.Create(cx, node);
- }
- public override void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node)
- {
+ public override void VisitPragmaChecksumDirectiveTrivia(PragmaChecksumDirectiveTriviaSyntax node) =>
Entities.PragmaChecksumDirective.Create(cx, node);
- }
- public override void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node)
- {
+ public override void VisitDefineDirectiveTrivia(DefineDirectiveTriviaSyntax node) =>
Entities.DefineDirective.Create(cx, node);
- }
- public override void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node)
- {
+ public override void VisitUndefDirectiveTrivia(UndefDirectiveTriviaSyntax node) =>
Entities.UndefineDirective.Create(cx, node);
- }
- public override void VisitWarningDirectiveTrivia(WarningDirectiveTriviaSyntax node)
- {
+ public override void VisitWarningDirectiveTrivia(WarningDirectiveTriviaSyntax node) =>
Entities.WarningDirective.Create(cx, node);
- }
- public override void VisitErrorDirectiveTrivia(ErrorDirectiveTriviaSyntax node)
- {
+ public override void VisitErrorDirectiveTrivia(ErrorDirectiveTriviaSyntax node) =>
Entities.ErrorDirective.Create(cx, node);
- }
- public override void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node)
- {
+ public override void VisitNullableDirectiveTrivia(NullableDirectiveTriviaSyntax node) =>
Entities.NullableDirective.Create(cx, node);
- }
- public override void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node)
- {
+ public override void VisitLineDirectiveTrivia(LineDirectiveTriviaSyntax node) =>
Entities.LineDirective.Create(cx, node);
- }
public override void VisitLineSpanDirectiveTrivia(LineSpanDirectiveTriviaSyntax node) =>
Entities.LineSpanDirective.Create(cx, node);
From 93255dfe1391d9250661871229e43d7167101c11 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:38:26 +0100
Subject: [PATCH 028/196] C#: Add QL library support for the Line span
directive.
---
.../lib/semmle/code/csharp/Preprocessor.qll | 29 +++++++++++++++----
1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
index 3342dd5c59c..ac6408440e8 100644
--- a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
@@ -208,21 +208,40 @@ class HiddenLineDirective extends LineDirective {
override string getAPrimaryQlClass() { result = "HiddenLineDirective" }
}
+abstract private class NumericOrSpanLineDirective extends LineDirective {
+ /** Gets the referenced file of this directive. */
+ File getReferencedFile() { directive_line_file(this, result) }
+}
+
/**
- * A numeric `#line` directive, such as `#line 200 file`
+ * A numeric `#line` directive, such as `#line 200 file`.
*/
-class NumericLineDirective extends LineDirective {
+class NumericLineDirective extends NumericOrSpanLineDirective {
NumericLineDirective() { directive_lines(this, 2) }
/** Gets the line number of this directive. */
int getLine() { directive_line_value(this, result) }
- /** Gets the referenced file of this directive. */
- File getReferencedFile() { directive_line_file(this, result) }
-
override string getAPrimaryQlClass() { result = "NumericLineDirective" }
}
+/**
+ * A line span `#line` directive, such as `#line (1, 1) - (3, 10) 5 file`.
+ */
+class SpanLineDirective extends NumericOrSpanLineDirective {
+ SpanLineDirective() { directive_lines(this, 3) }
+
+ /** Gets the offset of this directive. */
+ int getOffset() { directive_line_offset(this, result) }
+
+ /** Gets the span of this directive. */
+ predicate span(int startLine, int startColumn, int endLine, int endColumn) {
+ directive_line_span(this, startLine, startColumn, endLine, endColumn)
+ }
+
+ override string getAPrimaryQlClass() { result = "SpanLineDirective" }
+}
+
/**
* A `#region` directive.
*/
From 8b048ca17e31f8c9259a63108d6714a0d7fa89cc Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:39:31 +0100
Subject: [PATCH 029/196] C#: Add line span pragma example.
---
csharp/ql/test/library-tests/csharp10/LinePragmas.cs | 12 ++++++++++++
.../test/library-tests/csharp10/LinePragmasRef1.cs | 0
.../test/library-tests/csharp10/LinePragmasRef2.cs | 0
3 files changed, 12 insertions(+)
create mode 100644 csharp/ql/test/library-tests/csharp10/LinePragmas.cs
create mode 100644 csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs
create mode 100644 csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs
diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmas.cs b/csharp/ql/test/library-tests/csharp10/LinePragmas.cs
new file mode 100644
index 00000000000..73fff46f6fc
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/LinePragmas.cs
@@ -0,0 +1,12 @@
+using System;
+
+public class MyLineDirective
+{
+ public static void M1()
+ {
+#line (1, 1) - (1, 30) 5 "LinePragmasRef1.cs"
+ int i = 0;
+#line (2, 1) - (5, 32) "LinePragmasRef2.cs"
+ int j = 0;
+ }
+}
\ No newline at end of file
diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs b/csharp/ql/test/library-tests/csharp10/LinePragmasRef1.cs
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs b/csharp/ql/test/library-tests/csharp10/LinePragmasRef2.cs
new file mode 100644
index 00000000000..e69de29bb2d
From ac47c96f48df6a12fd0f8097b3931eeecfbbf3fd Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 12 Jan 2022 16:40:07 +0100
Subject: [PATCH 030/196] C#: Add Line span pragma test case.
---
.../library-tests/csharp10/linePragmas.expected | 5 +++++
.../ql/test/library-tests/csharp10/linePragmas.ql | 13 +++++++++++++
2 files changed, 18 insertions(+)
create mode 100644 csharp/ql/test/library-tests/csharp10/linePragmas.expected
create mode 100644 csharp/ql/test/library-tests/csharp10/linePragmas.ql
diff --git a/csharp/ql/test/library-tests/csharp10/linePragmas.expected b/csharp/ql/test/library-tests/csharp10/linePragmas.expected
new file mode 100644
index 00000000000..2d88fa7582f
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/linePragmas.expected
@@ -0,0 +1,5 @@
+linespan_directives
+| LinePragmas.cs:7:1:7:45 | #line ... | 1 | 1 | 1 | 30 | LinePragmasRef1.cs:0:0:0:0 | LinePragmasRef1.cs |
+| LinePragmas.cs:9:1:9:43 | #line ... | 2 | 1 | 5 | 32 | LinePragmasRef2.cs:0:0:0:0 | LinePragmasRef2.cs |
+linespan_offset
+| LinePragmas.cs:7:1:7:45 | #line ... | 5 | LinePragmasRef1.cs:0:0:0:0 | LinePragmasRef1.cs |
diff --git a/csharp/ql/test/library-tests/csharp10/linePragmas.ql b/csharp/ql/test/library-tests/csharp10/linePragmas.ql
new file mode 100644
index 00000000000..41bf0a60d31
--- /dev/null
+++ b/csharp/ql/test/library-tests/csharp10/linePragmas.ql
@@ -0,0 +1,13 @@
+import csharp
+
+query predicate linespan_directives(
+ SpanLineDirective directive, int startLine, int startColumn, int endLine, int endColumn, File file
+) {
+ file = directive.getReferencedFile() and
+ directive.span(startLine, startColumn, endLine, endColumn)
+}
+
+query predicate linespan_offset(SpanLineDirective directive, int offset, File file) {
+ file = directive.getReferencedFile() and
+ offset = directive.getOffset()
+}
From 8fd116fbd7d0fc0c26f60bf247a9bbd71a9423e3 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 09:38:39 +0100
Subject: [PATCH 031/196] C#: Add upgrade scripts for the new tables requires
for the line span pragma.
---
.../old.dbscheme | 2088 ++++++++++++++++
.../semmlecode.csharp.dbscheme | 2098 +++++++++++++++++
.../upgrade.properties | 2 +
3 files changed, 4188 insertions(+)
create mode 100644 csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme
create mode 100644 csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme
create mode 100644 csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties
diff --git a/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme
new file mode 100644
index 00000000000..193c35b0e37
--- /dev/null
+++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/old.dbscheme
@@ -0,0 +1,2088 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | --cil
+ * 3 | f1.cs
+ * 4 | f2.cs
+ * 5 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location_default ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+/*
+ * External artifacts
+ */
+
+externalDefects(
+ unique int id: @externalDefect,
+ string queryPath: string ref,
+ int location: @location ref,
+ string message: string ref,
+ float severity: float ref);
+
+externalMetrics(
+ unique int id: @externalMetric,
+ string queryPath: string ref,
+ int location: @location ref,
+ float value: float ref);
+
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+snapshotDate(
+ unique date snapshotDate: date ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * Duplicate code
+ */
+
+duplicateCode(
+ unique int id: @duplication,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+similarCode(
+ unique int id: @similarity,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+@duplication_or_similarity = @duplication | @similarity
+
+tokens(
+ int id: @duplication_or_similarity ref,
+ int offset: int ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @external_element
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@external_element = @externalMetric | @externalDefect | @externalDataElement;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref
+)
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ unique int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+compiler_generated(unique int id: @modifiable_direct ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_compiler_generated(
+ unique int id: @expr ref);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
+
+/* Common Intermediate Language - CIL */
+
+case @cil_instruction.opcode of
+ 0 = @cil_nop
+| 1 = @cil_break
+| 2 = @cil_ldarg_0
+| 3 = @cil_ldarg_1
+| 4 = @cil_ldarg_2
+| 5 = @cil_ldarg_3
+| 6 = @cil_ldloc_0
+| 7 = @cil_ldloc_1
+| 8 = @cil_ldloc_2
+| 9 = @cil_ldloc_3
+| 10 = @cil_stloc_0
+| 11 = @cil_stloc_1
+| 12 = @cil_stloc_2
+| 13 = @cil_stloc_3
+| 14 = @cil_ldarg_s
+| 15 = @cil_ldarga_s
+| 16 = @cil_starg_s
+| 17 = @cil_ldloc_s
+| 18 = @cil_ldloca_s
+| 19 = @cil_stloc_s
+| 20 = @cil_ldnull
+| 21 = @cil_ldc_i4_m1
+| 22 = @cil_ldc_i4_0
+| 23 = @cil_ldc_i4_1
+| 24 = @cil_ldc_i4_2
+| 25 = @cil_ldc_i4_3
+| 26 = @cil_ldc_i4_4
+| 27 = @cil_ldc_i4_5
+| 28 = @cil_ldc_i4_6
+| 29 = @cil_ldc_i4_7
+| 30 = @cil_ldc_i4_8
+| 31 = @cil_ldc_i4_s
+| 32 = @cil_ldc_i4
+| 33 = @cil_ldc_i8
+| 34 = @cil_ldc_r4
+| 35 = @cil_ldc_r8
+| 37 = @cil_dup
+| 38 = @cil_pop
+| 39 = @cil_jmp
+| 40 = @cil_call
+| 41 = @cil_calli
+| 42 = @cil_ret
+| 43 = @cil_br_s
+| 44 = @cil_brfalse_s
+| 45 = @cil_brtrue_s
+| 46 = @cil_beq_s
+| 47 = @cil_bge_s
+| 48 = @cil_bgt_s
+| 49 = @cil_ble_s
+| 50 = @cil_blt_s
+| 51 = @cil_bne_un_s
+| 52 = @cil_bge_un_s
+| 53 = @cil_bgt_un_s
+| 54 = @cil_ble_un_s
+| 55 = @cil_blt_un_s
+| 56 = @cil_br
+| 57 = @cil_brfalse
+| 58 = @cil_brtrue
+| 59 = @cil_beq
+| 60 = @cil_bge
+| 61 = @cil_bgt
+| 62 = @cil_ble
+| 63 = @cil_blt
+| 64 = @cil_bne_un
+| 65 = @cil_bge_un
+| 66 = @cil_bgt_un
+| 67 = @cil_ble_un
+| 68 = @cil_blt_un
+| 69 = @cil_switch
+| 70 = @cil_ldind_i1
+| 71 = @cil_ldind_u1
+| 72 = @cil_ldind_i2
+| 73 = @cil_ldind_u2
+| 74 = @cil_ldind_i4
+| 75 = @cil_ldind_u4
+| 76 = @cil_ldind_i8
+| 77 = @cil_ldind_i
+| 78 = @cil_ldind_r4
+| 79 = @cil_ldind_r8
+| 80 = @cil_ldind_ref
+| 81 = @cil_stind_ref
+| 82 = @cil_stind_i1
+| 83 = @cil_stind_i2
+| 84 = @cil_stind_i4
+| 85 = @cil_stind_i8
+| 86 = @cil_stind_r4
+| 87 = @cil_stind_r8
+| 88 = @cil_add
+| 89 = @cil_sub
+| 90 = @cil_mul
+| 91 = @cil_div
+| 92 = @cil_div_un
+| 93 = @cil_rem
+| 94 = @cil_rem_un
+| 95 = @cil_and
+| 96 = @cil_or
+| 97 = @cil_xor
+| 98 = @cil_shl
+| 99 = @cil_shr
+| 100 = @cil_shr_un
+| 101 = @cil_neg
+| 102 = @cil_not
+| 103 = @cil_conv_i1
+| 104 = @cil_conv_i2
+| 105 = @cil_conv_i4
+| 106 = @cil_conv_i8
+| 107 = @cil_conv_r4
+| 108 = @cil_conv_r8
+| 109 = @cil_conv_u4
+| 110 = @cil_conv_u8
+| 111 = @cil_callvirt
+| 112 = @cil_cpobj
+| 113 = @cil_ldobj
+| 114 = @cil_ldstr
+| 115 = @cil_newobj
+| 116 = @cil_castclass
+| 117 = @cil_isinst
+| 118 = @cil_conv_r_un
+| 121 = @cil_unbox
+| 122 = @cil_throw
+| 123 = @cil_ldfld
+| 124 = @cil_ldflda
+| 125 = @cil_stfld
+| 126 = @cil_ldsfld
+| 127 = @cil_ldsflda
+| 128 = @cil_stsfld
+| 129 = @cil_stobj
+| 130 = @cil_conv_ovf_i1_un
+| 131 = @cil_conv_ovf_i2_un
+| 132 = @cil_conv_ovf_i4_un
+| 133 = @cil_conv_ovf_i8_un
+| 134 = @cil_conv_ovf_u1_un
+| 135 = @cil_conv_ovf_u2_un
+| 136 = @cil_conv_ovf_u4_un
+| 137 = @cil_conv_ovf_u8_un
+| 138 = @cil_conv_ovf_i_un
+| 139 = @cil_conv_ovf_u_un
+| 140 = @cil_box
+| 141 = @cil_newarr
+| 142 = @cil_ldlen
+| 143 = @cil_ldelema
+| 144 = @cil_ldelem_i1
+| 145 = @cil_ldelem_u1
+| 146 = @cil_ldelem_i2
+| 147 = @cil_ldelem_u2
+| 148 = @cil_ldelem_i4
+| 149 = @cil_ldelem_u4
+| 150 = @cil_ldelem_i8
+| 151 = @cil_ldelem_i
+| 152 = @cil_ldelem_r4
+| 153 = @cil_ldelem_r8
+| 154 = @cil_ldelem_ref
+| 155 = @cil_stelem_i
+| 156 = @cil_stelem_i1
+| 157 = @cil_stelem_i2
+| 158 = @cil_stelem_i4
+| 159 = @cil_stelem_i8
+| 160 = @cil_stelem_r4
+| 161 = @cil_stelem_r8
+| 162 = @cil_stelem_ref
+| 163 = @cil_ldelem
+| 164 = @cil_stelem
+| 165 = @cil_unbox_any
+| 179 = @cil_conv_ovf_i1
+| 180 = @cil_conv_ovf_u1
+| 181 = @cil_conv_ovf_i2
+| 182 = @cil_conv_ovf_u2
+| 183 = @cil_conv_ovf_i4
+| 184 = @cil_conv_ovf_u4
+| 185 = @cil_conv_ovf_i8
+| 186 = @cil_conv_ovf_u8
+| 194 = @cil_refanyval
+| 195 = @cil_ckinfinite
+| 198 = @cil_mkrefany
+| 208 = @cil_ldtoken
+| 209 = @cil_conv_u2
+| 210 = @cil_conv_u1
+| 211 = @cil_conv_i
+| 212 = @cil_conv_ovf_i
+| 213 = @cil_conv_ovf_u
+| 214 = @cil_add_ovf
+| 215 = @cil_add_ovf_un
+| 216 = @cil_mul_ovf
+| 217 = @cil_mul_ovf_un
+| 218 = @cil_sub_ovf
+| 219 = @cil_sub_ovf_un
+| 220 = @cil_endfinally
+| 221 = @cil_leave
+| 222 = @cil_leave_s
+| 223 = @cil_stind_i
+| 224 = @cil_conv_u
+| 65024 = @cil_arglist
+| 65025 = @cil_ceq
+| 65026 = @cil_cgt
+| 65027 = @cil_cgt_un
+| 65028 = @cil_clt
+| 65029 = @cil_clt_un
+| 65030 = @cil_ldftn
+| 65031 = @cil_ldvirtftn
+| 65033 = @cil_ldarg
+| 65034 = @cil_ldarga
+| 65035 = @cil_starg
+| 65036 = @cil_ldloc
+| 65037 = @cil_ldloca
+| 65038 = @cil_stloc
+| 65039 = @cil_localloc
+| 65041 = @cil_endfilter
+| 65042 = @cil_unaligned
+| 65043 = @cil_volatile
+| 65044 = @cil_tail
+| 65045 = @cil_initobj
+| 65046 = @cil_constrained
+| 65047 = @cil_cpblk
+| 65048 = @cil_initblk
+| 65050 = @cil_rethrow
+| 65052 = @cil_sizeof
+| 65053 = @cil_refanytype
+| 65054 = @cil_readonly
+;
+
+// CIL ignored instructions
+
+@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
+
+// CIL local/parameter/field access
+
+@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
+@cil_starg_any = @cil_starg | @cil_starg_s;
+
+@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
+@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
+
+@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
+@cil_stfld_any = @cil_stfld | @cil_stsfld;
+
+@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
+@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
+@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
+@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
+
+@cil_stack_access = @cil_local_access | @cil_arg_access;
+@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
+
+@cil_access = @cil_read_access | @cil_write_access;
+
+// CIL constant/literal instructions
+
+@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
+
+@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
+ @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
+
+@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
+
+@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
+
+// Control flow
+
+@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
+@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
+ @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
+ @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
+ @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
+@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
+@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
+@cil_leave_any = @cil_leave | @cil_leave_s;
+@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
+
+// CIL call instructions
+
+@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
+
+// CIL expression instructions
+
+@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
+ @cil_newarr | @cil_ldtoken | @cil_sizeof |
+ @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
+
+@cil_unary_expr =
+ @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
+ @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
+ @cil_ldind | @cil_unbox;
+
+@cil_conversion_operation =
+ @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
+ @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
+ @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
+ @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
+ @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
+ @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
+ @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_i | @cil_conv_u | @cil_conv_r_un;
+
+@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
+ @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
+
+@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
+ @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
+
+@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
+
+@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
+
+@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
+ @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
+ @cil_sub_ovf | @cil_sub_ovf_un;
+
+@cil_unary_bitwise_operation = @cil_not;
+
+@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
+
+@cil_unary_arithmetic_operation = @cil_neg;
+
+@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
+
+// Elements that retrieve an address of something
+@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
+
+// CIL array instructions
+
+@cil_read_array =
+ @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
+ @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
+ @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
+
+@cil_write_array = @cil_stelem | @cil_stelem_ref |
+ @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
+ @cil_stelem_r4 | @cil_stelem_r8;
+
+@cil_throw_any = @cil_throw | @cil_rethrow;
+
+#keyset[impl, index]
+cil_instruction(
+ unique int id: @cil_instruction,
+ int opcode: int ref,
+ int index: int ref,
+ int impl: @cil_method_implementation ref);
+
+cil_jump(
+ unique int instruction: @cil_jump ref,
+ int target: @cil_instruction ref);
+
+cil_access(
+ unique int instruction: @cil_instruction ref,
+ int target: @cil_accessible ref);
+
+cil_value(
+ unique int instruction: @cil_literal ref,
+ string value: string ref);
+
+#keyset[instruction, index]
+cil_switch(
+ int instruction: @cil_switch ref,
+ int index: int ref,
+ int target: @cil_instruction ref);
+
+cil_instruction_location(
+ unique int id: @cil_instruction ref,
+ int loc: @location ref);
+
+cil_type_location(
+ int id: @cil_type ref,
+ int loc: @location ref);
+
+cil_method_location(
+ int id: @cil_method ref,
+ int loc: @location ref);
+
+@cil_namespace = @namespace;
+
+@cil_type_container = @cil_type | @cil_namespace | @cil_method;
+
+case @cil_type.kind of
+ 0 = @cil_valueorreftype
+| 1 = @cil_typeparameter
+| 2 = @cil_array_type
+| 3 = @cil_pointer_type
+| 4 = @cil_function_pointer_type
+;
+
+cil_type(
+ unique int id: @cil_type,
+ string name: string ref,
+ int kind: int ref,
+ int parent: @cil_type_container ref,
+ int sourceDecl: @cil_type ref);
+
+cil_pointer_type(
+ unique int id: @cil_pointer_type ref,
+ int pointee: @cil_type ref);
+
+cil_array_type(
+ unique int id: @cil_array_type ref,
+ int element_type: @cil_type ref,
+ int rank: int ref);
+
+cil_function_pointer_return_type(
+ unique int id: @cil_function_pointer_type ref,
+ int return_type: @cil_type ref);
+
+cil_method(
+ unique int id: @cil_method,
+ string name: string ref,
+ int parent: @cil_type ref,
+ int return_type: @cil_type ref);
+
+cil_method_source_declaration(
+ unique int method: @cil_method ref,
+ int source: @cil_method ref);
+
+cil_method_implementation(
+ unique int id: @cil_method_implementation,
+ int method: @cil_method ref,
+ int location: @assembly ref);
+
+cil_implements(
+ int id: @cil_method ref,
+ int decl: @cil_method ref);
+
+#keyset[parent, name]
+cil_field(
+ unique int id: @cil_field,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int field_type: @cil_type ref);
+
+@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
+@cil_named_element = @cil_declaration | @cil_namespace;
+@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
+@cil_accessible = @cil_declaration;
+@cil_variable = @cil_field | @cil_stack_variable;
+@cil_stack_variable = @cil_local_variable | @cil_parameter;
+@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
+@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
+@cil_parameterizable = @cil_method | @cil_function_pointer_type;
+@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
+
+#keyset[parameterizable, index]
+cil_parameter(
+ unique int id: @cil_parameter,
+ int parameterizable: @cil_parameterizable ref,
+ int index: int ref,
+ int param_type: @cil_type ref);
+
+cil_parameter_in(unique int id: @cil_parameter ref);
+cil_parameter_out(unique int id: @cil_parameter ref);
+
+cil_setter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+#keyset[id, modifier]
+cil_custom_modifiers(
+ int id: @cil_custom_modifier_receiver ref,
+ int modifier: @cil_type ref,
+ int kind: int ref); // modreq: 1, modopt: 0
+
+cil_type_annotation(
+ int id: @cil_has_type_annotation ref,
+ int annotation: int ref);
+
+cil_getter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+cil_adder(unique int event: @cil_event ref,
+ int method: @cil_method ref);
+
+cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_property(
+ unique int id: @cil_property,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int property_type: @cil_type ref);
+
+#keyset[parent, name]
+cil_event(unique int id: @cil_event,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int event_type: @cil_type ref);
+
+#keyset[impl, index]
+cil_local_variable(
+ unique int id: @cil_local_variable,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int var_type: @cil_type ref);
+
+cil_function_pointer_calling_conventions(
+ int id: @cil_function_pointer_type ref,
+ int kind: int ref);
+
+// CIL handlers (exception handlers etc).
+
+case @cil_handler.kind of
+ 0 = @cil_catch_handler
+| 1 = @cil_filter_handler
+| 2 = @cil_finally_handler
+| 4 = @cil_fault_handler
+;
+
+#keyset[impl, index]
+cil_handler(
+ unique int id: @cil_handler,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int kind: int ref,
+ int try_start: @cil_instruction ref,
+ int try_end: @cil_instruction ref,
+ int handler_start: @cil_instruction ref);
+
+cil_handler_filter(
+ unique int id: @cil_handler ref,
+ int filter_start: @cil_instruction ref);
+
+cil_handler_type(
+ unique int id: @cil_handler ref,
+ int catch_type: @cil_type ref);
+
+@cil_controlflow_node = @cil_entry_point | @cil_instruction;
+
+@cil_entry_point = @cil_method_implementation | @cil_handler;
+
+@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
+
+cil_method_stack_size(
+ unique int method: @cil_method_implementation ref,
+ int size: int ref);
+
+// CIL modifiers
+
+cil_public(int id: @cil_member ref);
+cil_private(int id: @cil_member ref);
+cil_protected(int id: @cil_member ref);
+cil_internal(int id: @cil_member ref);
+cil_static(int id: @cil_member ref);
+cil_sealed(int id: @cil_member ref);
+cil_virtual(int id: @cil_method ref);
+cil_abstract(int id: @cil_member ref);
+cil_class(int id: @cil_type ref);
+cil_interface(int id: @cil_type ref);
+cil_security(int id: @cil_member ref);
+cil_requiresecobject(int id: @cil_method ref);
+cil_specialname(int id: @cil_method ref);
+cil_newslot(int id: @cil_method ref);
+
+cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
+cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
+cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
+
+#keyset[unbound, index]
+cil_type_parameter(
+ int unbound: @cil_member ref,
+ int index: int ref,
+ int param: @cil_typeparameter ref);
+
+#keyset[bound, index]
+cil_type_argument(
+ int bound: @cil_member ref,
+ int index: int ref,
+ int t: @cil_type ref);
+
+// CIL type parameter constraints
+
+cil_typeparam_covariant(int tp: @cil_typeparameter ref);
+cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
+cil_typeparam_class(int tp: @cil_typeparameter ref);
+cil_typeparam_struct(int tp: @cil_typeparameter ref);
+cil_typeparam_new(int tp: @cil_typeparameter ref);
+cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
+
+// CIL attributes
+
+cil_attribute(
+ unique int attributeid: @cil_attribute,
+ int element: @cil_declaration ref,
+ int constructor: @cil_method ref);
+
+#keyset[attribute_id, param]
+cil_attribute_named_argument(
+ int attribute_id: @cil_attribute ref,
+ string param: string ref,
+ string value: string ref);
+
+#keyset[attribute_id, index]
+cil_attribute_positional_argument(
+ int attribute_id: @cil_attribute ref,
+ int index: int ref,
+ string value: string ref);
+
+
+// Common .Net data model covering both C# and CIL
+
+// Common elements
+@dotnet_element = @element | @cil_element;
+@dotnet_named_element = @named_element | @cil_named_element;
+@dotnet_callable = @callable | @cil_method;
+@dotnet_variable = @variable | @cil_variable;
+@dotnet_field = @field | @cil_field;
+@dotnet_parameter = @parameter | @cil_parameter;
+@dotnet_declaration = @declaration | @cil_declaration;
+@dotnet_member = @member | @cil_member;
+@dotnet_event = @event | @cil_event;
+@dotnet_property = @property | @cil_property | @indexer;
+@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
+
+// Common types
+@dotnet_type = @type | @cil_type;
+@dotnet_call = @call | @cil_call_any;
+@dotnet_throw = @throw_element | @cil_throw_any;
+@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
+@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
+@dotnet_array_type = @array_type | @cil_array_type;
+@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
+@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
+@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
+
+// Attributes
+@dotnet_attribute = @attribute | @cil_attribute;
+
+// Expressions
+@dotnet_expr = @expr | @cil_expr;
+
+// Literals
+@dotnet_literal = @literal_expr | @cil_literal;
+@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
+@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
+@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
+@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
+
+@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
+ @callable | @value_or_ref_type | @void_type;
+
+#keyset[entity, location]
+metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
diff --git a/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme
new file mode 100644
index 00000000000..ff083666c7f
--- /dev/null
+++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/semmlecode.csharp.dbscheme
@@ -0,0 +1,2098 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | --cil
+ * 3 | f1.cs
+ * 4 | f2.cs
+ * 5 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location_default ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+/*
+ * External artifacts
+ */
+
+externalDefects(
+ unique int id: @externalDefect,
+ string queryPath: string ref,
+ int location: @location ref,
+ string message: string ref,
+ float severity: float ref);
+
+externalMetrics(
+ unique int id: @externalMetric,
+ string queryPath: string ref,
+ int location: @location ref,
+ float value: float ref);
+
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+snapshotDate(
+ unique date snapshotDate: date ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * Duplicate code
+ */
+
+duplicateCode(
+ unique int id: @duplication,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+similarCode(
+ unique int id: @similarity,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+@duplication_or_similarity = @duplication | @similarity
+
+tokens(
+ int id: @duplication_or_similarity ref,
+ int offset: int ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @external_element
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@external_element = @externalMetric | @externalDefect | @externalDataElement;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ unique int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+compiler_generated(unique int id: @modifiable_direct ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_compiler_generated(
+ unique int id: @expr ref);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
+
+/* Common Intermediate Language - CIL */
+
+case @cil_instruction.opcode of
+ 0 = @cil_nop
+| 1 = @cil_break
+| 2 = @cil_ldarg_0
+| 3 = @cil_ldarg_1
+| 4 = @cil_ldarg_2
+| 5 = @cil_ldarg_3
+| 6 = @cil_ldloc_0
+| 7 = @cil_ldloc_1
+| 8 = @cil_ldloc_2
+| 9 = @cil_ldloc_3
+| 10 = @cil_stloc_0
+| 11 = @cil_stloc_1
+| 12 = @cil_stloc_2
+| 13 = @cil_stloc_3
+| 14 = @cil_ldarg_s
+| 15 = @cil_ldarga_s
+| 16 = @cil_starg_s
+| 17 = @cil_ldloc_s
+| 18 = @cil_ldloca_s
+| 19 = @cil_stloc_s
+| 20 = @cil_ldnull
+| 21 = @cil_ldc_i4_m1
+| 22 = @cil_ldc_i4_0
+| 23 = @cil_ldc_i4_1
+| 24 = @cil_ldc_i4_2
+| 25 = @cil_ldc_i4_3
+| 26 = @cil_ldc_i4_4
+| 27 = @cil_ldc_i4_5
+| 28 = @cil_ldc_i4_6
+| 29 = @cil_ldc_i4_7
+| 30 = @cil_ldc_i4_8
+| 31 = @cil_ldc_i4_s
+| 32 = @cil_ldc_i4
+| 33 = @cil_ldc_i8
+| 34 = @cil_ldc_r4
+| 35 = @cil_ldc_r8
+| 37 = @cil_dup
+| 38 = @cil_pop
+| 39 = @cil_jmp
+| 40 = @cil_call
+| 41 = @cil_calli
+| 42 = @cil_ret
+| 43 = @cil_br_s
+| 44 = @cil_brfalse_s
+| 45 = @cil_brtrue_s
+| 46 = @cil_beq_s
+| 47 = @cil_bge_s
+| 48 = @cil_bgt_s
+| 49 = @cil_ble_s
+| 50 = @cil_blt_s
+| 51 = @cil_bne_un_s
+| 52 = @cil_bge_un_s
+| 53 = @cil_bgt_un_s
+| 54 = @cil_ble_un_s
+| 55 = @cil_blt_un_s
+| 56 = @cil_br
+| 57 = @cil_brfalse
+| 58 = @cil_brtrue
+| 59 = @cil_beq
+| 60 = @cil_bge
+| 61 = @cil_bgt
+| 62 = @cil_ble
+| 63 = @cil_blt
+| 64 = @cil_bne_un
+| 65 = @cil_bge_un
+| 66 = @cil_bgt_un
+| 67 = @cil_ble_un
+| 68 = @cil_blt_un
+| 69 = @cil_switch
+| 70 = @cil_ldind_i1
+| 71 = @cil_ldind_u1
+| 72 = @cil_ldind_i2
+| 73 = @cil_ldind_u2
+| 74 = @cil_ldind_i4
+| 75 = @cil_ldind_u4
+| 76 = @cil_ldind_i8
+| 77 = @cil_ldind_i
+| 78 = @cil_ldind_r4
+| 79 = @cil_ldind_r8
+| 80 = @cil_ldind_ref
+| 81 = @cil_stind_ref
+| 82 = @cil_stind_i1
+| 83 = @cil_stind_i2
+| 84 = @cil_stind_i4
+| 85 = @cil_stind_i8
+| 86 = @cil_stind_r4
+| 87 = @cil_stind_r8
+| 88 = @cil_add
+| 89 = @cil_sub
+| 90 = @cil_mul
+| 91 = @cil_div
+| 92 = @cil_div_un
+| 93 = @cil_rem
+| 94 = @cil_rem_un
+| 95 = @cil_and
+| 96 = @cil_or
+| 97 = @cil_xor
+| 98 = @cil_shl
+| 99 = @cil_shr
+| 100 = @cil_shr_un
+| 101 = @cil_neg
+| 102 = @cil_not
+| 103 = @cil_conv_i1
+| 104 = @cil_conv_i2
+| 105 = @cil_conv_i4
+| 106 = @cil_conv_i8
+| 107 = @cil_conv_r4
+| 108 = @cil_conv_r8
+| 109 = @cil_conv_u4
+| 110 = @cil_conv_u8
+| 111 = @cil_callvirt
+| 112 = @cil_cpobj
+| 113 = @cil_ldobj
+| 114 = @cil_ldstr
+| 115 = @cil_newobj
+| 116 = @cil_castclass
+| 117 = @cil_isinst
+| 118 = @cil_conv_r_un
+| 121 = @cil_unbox
+| 122 = @cil_throw
+| 123 = @cil_ldfld
+| 124 = @cil_ldflda
+| 125 = @cil_stfld
+| 126 = @cil_ldsfld
+| 127 = @cil_ldsflda
+| 128 = @cil_stsfld
+| 129 = @cil_stobj
+| 130 = @cil_conv_ovf_i1_un
+| 131 = @cil_conv_ovf_i2_un
+| 132 = @cil_conv_ovf_i4_un
+| 133 = @cil_conv_ovf_i8_un
+| 134 = @cil_conv_ovf_u1_un
+| 135 = @cil_conv_ovf_u2_un
+| 136 = @cil_conv_ovf_u4_un
+| 137 = @cil_conv_ovf_u8_un
+| 138 = @cil_conv_ovf_i_un
+| 139 = @cil_conv_ovf_u_un
+| 140 = @cil_box
+| 141 = @cil_newarr
+| 142 = @cil_ldlen
+| 143 = @cil_ldelema
+| 144 = @cil_ldelem_i1
+| 145 = @cil_ldelem_u1
+| 146 = @cil_ldelem_i2
+| 147 = @cil_ldelem_u2
+| 148 = @cil_ldelem_i4
+| 149 = @cil_ldelem_u4
+| 150 = @cil_ldelem_i8
+| 151 = @cil_ldelem_i
+| 152 = @cil_ldelem_r4
+| 153 = @cil_ldelem_r8
+| 154 = @cil_ldelem_ref
+| 155 = @cil_stelem_i
+| 156 = @cil_stelem_i1
+| 157 = @cil_stelem_i2
+| 158 = @cil_stelem_i4
+| 159 = @cil_stelem_i8
+| 160 = @cil_stelem_r4
+| 161 = @cil_stelem_r8
+| 162 = @cil_stelem_ref
+| 163 = @cil_ldelem
+| 164 = @cil_stelem
+| 165 = @cil_unbox_any
+| 179 = @cil_conv_ovf_i1
+| 180 = @cil_conv_ovf_u1
+| 181 = @cil_conv_ovf_i2
+| 182 = @cil_conv_ovf_u2
+| 183 = @cil_conv_ovf_i4
+| 184 = @cil_conv_ovf_u4
+| 185 = @cil_conv_ovf_i8
+| 186 = @cil_conv_ovf_u8
+| 194 = @cil_refanyval
+| 195 = @cil_ckinfinite
+| 198 = @cil_mkrefany
+| 208 = @cil_ldtoken
+| 209 = @cil_conv_u2
+| 210 = @cil_conv_u1
+| 211 = @cil_conv_i
+| 212 = @cil_conv_ovf_i
+| 213 = @cil_conv_ovf_u
+| 214 = @cil_add_ovf
+| 215 = @cil_add_ovf_un
+| 216 = @cil_mul_ovf
+| 217 = @cil_mul_ovf_un
+| 218 = @cil_sub_ovf
+| 219 = @cil_sub_ovf_un
+| 220 = @cil_endfinally
+| 221 = @cil_leave
+| 222 = @cil_leave_s
+| 223 = @cil_stind_i
+| 224 = @cil_conv_u
+| 65024 = @cil_arglist
+| 65025 = @cil_ceq
+| 65026 = @cil_cgt
+| 65027 = @cil_cgt_un
+| 65028 = @cil_clt
+| 65029 = @cil_clt_un
+| 65030 = @cil_ldftn
+| 65031 = @cil_ldvirtftn
+| 65033 = @cil_ldarg
+| 65034 = @cil_ldarga
+| 65035 = @cil_starg
+| 65036 = @cil_ldloc
+| 65037 = @cil_ldloca
+| 65038 = @cil_stloc
+| 65039 = @cil_localloc
+| 65041 = @cil_endfilter
+| 65042 = @cil_unaligned
+| 65043 = @cil_volatile
+| 65044 = @cil_tail
+| 65045 = @cil_initobj
+| 65046 = @cil_constrained
+| 65047 = @cil_cpblk
+| 65048 = @cil_initblk
+| 65050 = @cil_rethrow
+| 65052 = @cil_sizeof
+| 65053 = @cil_refanytype
+| 65054 = @cil_readonly
+;
+
+// CIL ignored instructions
+
+@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
+
+// CIL local/parameter/field access
+
+@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
+@cil_starg_any = @cil_starg | @cil_starg_s;
+
+@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
+@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
+
+@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
+@cil_stfld_any = @cil_stfld | @cil_stsfld;
+
+@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
+@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
+@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
+@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
+
+@cil_stack_access = @cil_local_access | @cil_arg_access;
+@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
+
+@cil_access = @cil_read_access | @cil_write_access;
+
+// CIL constant/literal instructions
+
+@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
+
+@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
+ @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
+
+@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
+
+@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
+
+// Control flow
+
+@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
+@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
+ @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
+ @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
+ @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
+@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
+@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
+@cil_leave_any = @cil_leave | @cil_leave_s;
+@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
+
+// CIL call instructions
+
+@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
+
+// CIL expression instructions
+
+@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
+ @cil_newarr | @cil_ldtoken | @cil_sizeof |
+ @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
+
+@cil_unary_expr =
+ @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
+ @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
+ @cil_ldind | @cil_unbox;
+
+@cil_conversion_operation =
+ @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
+ @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
+ @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
+ @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
+ @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
+ @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
+ @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_i | @cil_conv_u | @cil_conv_r_un;
+
+@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
+ @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
+
+@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
+ @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
+
+@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
+
+@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
+
+@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
+ @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
+ @cil_sub_ovf | @cil_sub_ovf_un;
+
+@cil_unary_bitwise_operation = @cil_not;
+
+@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
+
+@cil_unary_arithmetic_operation = @cil_neg;
+
+@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
+
+// Elements that retrieve an address of something
+@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
+
+// CIL array instructions
+
+@cil_read_array =
+ @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
+ @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
+ @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
+
+@cil_write_array = @cil_stelem | @cil_stelem_ref |
+ @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
+ @cil_stelem_r4 | @cil_stelem_r8;
+
+@cil_throw_any = @cil_throw | @cil_rethrow;
+
+#keyset[impl, index]
+cil_instruction(
+ unique int id: @cil_instruction,
+ int opcode: int ref,
+ int index: int ref,
+ int impl: @cil_method_implementation ref);
+
+cil_jump(
+ unique int instruction: @cil_jump ref,
+ int target: @cil_instruction ref);
+
+cil_access(
+ unique int instruction: @cil_instruction ref,
+ int target: @cil_accessible ref);
+
+cil_value(
+ unique int instruction: @cil_literal ref,
+ string value: string ref);
+
+#keyset[instruction, index]
+cil_switch(
+ int instruction: @cil_switch ref,
+ int index: int ref,
+ int target: @cil_instruction ref);
+
+cil_instruction_location(
+ unique int id: @cil_instruction ref,
+ int loc: @location ref);
+
+cil_type_location(
+ int id: @cil_type ref,
+ int loc: @location ref);
+
+cil_method_location(
+ int id: @cil_method ref,
+ int loc: @location ref);
+
+@cil_namespace = @namespace;
+
+@cil_type_container = @cil_type | @cil_namespace | @cil_method;
+
+case @cil_type.kind of
+ 0 = @cil_valueorreftype
+| 1 = @cil_typeparameter
+| 2 = @cil_array_type
+| 3 = @cil_pointer_type
+| 4 = @cil_function_pointer_type
+;
+
+cil_type(
+ unique int id: @cil_type,
+ string name: string ref,
+ int kind: int ref,
+ int parent: @cil_type_container ref,
+ int sourceDecl: @cil_type ref);
+
+cil_pointer_type(
+ unique int id: @cil_pointer_type ref,
+ int pointee: @cil_type ref);
+
+cil_array_type(
+ unique int id: @cil_array_type ref,
+ int element_type: @cil_type ref,
+ int rank: int ref);
+
+cil_function_pointer_return_type(
+ unique int id: @cil_function_pointer_type ref,
+ int return_type: @cil_type ref);
+
+cil_method(
+ unique int id: @cil_method,
+ string name: string ref,
+ int parent: @cil_type ref,
+ int return_type: @cil_type ref);
+
+cil_method_source_declaration(
+ unique int method: @cil_method ref,
+ int source: @cil_method ref);
+
+cil_method_implementation(
+ unique int id: @cil_method_implementation,
+ int method: @cil_method ref,
+ int location: @assembly ref);
+
+cil_implements(
+ int id: @cil_method ref,
+ int decl: @cil_method ref);
+
+#keyset[parent, name]
+cil_field(
+ unique int id: @cil_field,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int field_type: @cil_type ref);
+
+@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
+@cil_named_element = @cil_declaration | @cil_namespace;
+@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
+@cil_accessible = @cil_declaration;
+@cil_variable = @cil_field | @cil_stack_variable;
+@cil_stack_variable = @cil_local_variable | @cil_parameter;
+@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
+@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
+@cil_parameterizable = @cil_method | @cil_function_pointer_type;
+@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
+
+#keyset[parameterizable, index]
+cil_parameter(
+ unique int id: @cil_parameter,
+ int parameterizable: @cil_parameterizable ref,
+ int index: int ref,
+ int param_type: @cil_type ref);
+
+cil_parameter_in(unique int id: @cil_parameter ref);
+cil_parameter_out(unique int id: @cil_parameter ref);
+
+cil_setter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+#keyset[id, modifier]
+cil_custom_modifiers(
+ int id: @cil_custom_modifier_receiver ref,
+ int modifier: @cil_type ref,
+ int kind: int ref); // modreq: 1, modopt: 0
+
+cil_type_annotation(
+ int id: @cil_has_type_annotation ref,
+ int annotation: int ref);
+
+cil_getter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+cil_adder(unique int event: @cil_event ref,
+ int method: @cil_method ref);
+
+cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_property(
+ unique int id: @cil_property,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int property_type: @cil_type ref);
+
+#keyset[parent, name]
+cil_event(unique int id: @cil_event,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int event_type: @cil_type ref);
+
+#keyset[impl, index]
+cil_local_variable(
+ unique int id: @cil_local_variable,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int var_type: @cil_type ref);
+
+cil_function_pointer_calling_conventions(
+ int id: @cil_function_pointer_type ref,
+ int kind: int ref);
+
+// CIL handlers (exception handlers etc).
+
+case @cil_handler.kind of
+ 0 = @cil_catch_handler
+| 1 = @cil_filter_handler
+| 2 = @cil_finally_handler
+| 4 = @cil_fault_handler
+;
+
+#keyset[impl, index]
+cil_handler(
+ unique int id: @cil_handler,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int kind: int ref,
+ int try_start: @cil_instruction ref,
+ int try_end: @cil_instruction ref,
+ int handler_start: @cil_instruction ref);
+
+cil_handler_filter(
+ unique int id: @cil_handler ref,
+ int filter_start: @cil_instruction ref);
+
+cil_handler_type(
+ unique int id: @cil_handler ref,
+ int catch_type: @cil_type ref);
+
+@cil_controlflow_node = @cil_entry_point | @cil_instruction;
+
+@cil_entry_point = @cil_method_implementation | @cil_handler;
+
+@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
+
+cil_method_stack_size(
+ unique int method: @cil_method_implementation ref,
+ int size: int ref);
+
+// CIL modifiers
+
+cil_public(int id: @cil_member ref);
+cil_private(int id: @cil_member ref);
+cil_protected(int id: @cil_member ref);
+cil_internal(int id: @cil_member ref);
+cil_static(int id: @cil_member ref);
+cil_sealed(int id: @cil_member ref);
+cil_virtual(int id: @cil_method ref);
+cil_abstract(int id: @cil_member ref);
+cil_class(int id: @cil_type ref);
+cil_interface(int id: @cil_type ref);
+cil_security(int id: @cil_member ref);
+cil_requiresecobject(int id: @cil_method ref);
+cil_specialname(int id: @cil_method ref);
+cil_newslot(int id: @cil_method ref);
+
+cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
+cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
+cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
+
+#keyset[unbound, index]
+cil_type_parameter(
+ int unbound: @cil_member ref,
+ int index: int ref,
+ int param: @cil_typeparameter ref);
+
+#keyset[bound, index]
+cil_type_argument(
+ int bound: @cil_member ref,
+ int index: int ref,
+ int t: @cil_type ref);
+
+// CIL type parameter constraints
+
+cil_typeparam_covariant(int tp: @cil_typeparameter ref);
+cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
+cil_typeparam_class(int tp: @cil_typeparameter ref);
+cil_typeparam_struct(int tp: @cil_typeparameter ref);
+cil_typeparam_new(int tp: @cil_typeparameter ref);
+cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
+
+// CIL attributes
+
+cil_attribute(
+ unique int attributeid: @cil_attribute,
+ int element: @cil_declaration ref,
+ int constructor: @cil_method ref);
+
+#keyset[attribute_id, param]
+cil_attribute_named_argument(
+ int attribute_id: @cil_attribute ref,
+ string param: string ref,
+ string value: string ref);
+
+#keyset[attribute_id, index]
+cil_attribute_positional_argument(
+ int attribute_id: @cil_attribute ref,
+ int index: int ref,
+ string value: string ref);
+
+
+// Common .Net data model covering both C# and CIL
+
+// Common elements
+@dotnet_element = @element | @cil_element;
+@dotnet_named_element = @named_element | @cil_named_element;
+@dotnet_callable = @callable | @cil_method;
+@dotnet_variable = @variable | @cil_variable;
+@dotnet_field = @field | @cil_field;
+@dotnet_parameter = @parameter | @cil_parameter;
+@dotnet_declaration = @declaration | @cil_declaration;
+@dotnet_member = @member | @cil_member;
+@dotnet_event = @event | @cil_event;
+@dotnet_property = @property | @cil_property | @indexer;
+@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
+
+// Common types
+@dotnet_type = @type | @cil_type;
+@dotnet_call = @call | @cil_call_any;
+@dotnet_throw = @throw_element | @cil_throw_any;
+@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
+@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
+@dotnet_array_type = @array_type | @cil_array_type;
+@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
+@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
+@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
+
+// Attributes
+@dotnet_attribute = @attribute | @cil_attribute;
+
+// Expressions
+@dotnet_expr = @expr | @cil_expr;
+
+// Literals
+@dotnet_literal = @literal_expr | @cil_literal;
+@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
+@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
+@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
+@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
+
+@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
+ @callable | @value_or_ref_type | @void_type;
+
+#keyset[entity, location]
+metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
diff --git a/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties
new file mode 100644
index 00000000000..31163274055
--- /dev/null
+++ b/csharp/ql/lib/upgrades/193c35b0e3776f8ee9a49e984e393974b4c670f6/upgrade.properties
@@ -0,0 +1,2 @@
+description: Add support for line span pragma.
+compatibility: backwards
From bf210267712183e0244bdbedbdf1d56757b1eb5c Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Mon, 17 Jan 2022 09:46:07 +0100
Subject: [PATCH 032/196] C#: Add downgrade scripts for the line span pragma.
---
.../old.dbscheme | 2098 +++++++++++++++++
.../semmlecode.csharp.dbscheme | 2088 ++++++++++++++++
.../upgrade.properties | 5 +
3 files changed, 4191 insertions(+)
create mode 100644 csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme
create mode 100644 csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme
create mode 100644 csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties
diff --git a/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme
new file mode 100644
index 00000000000..ff083666c7f
--- /dev/null
+++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/old.dbscheme
@@ -0,0 +1,2098 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | --cil
+ * 3 | f1.cs
+ * 4 | f2.cs
+ * 5 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location_default ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+/*
+ * External artifacts
+ */
+
+externalDefects(
+ unique int id: @externalDefect,
+ string queryPath: string ref,
+ int location: @location ref,
+ string message: string ref,
+ float severity: float ref);
+
+externalMetrics(
+ unique int id: @externalMetric,
+ string queryPath: string ref,
+ int location: @location ref,
+ float value: float ref);
+
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+snapshotDate(
+ unique date snapshotDate: date ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * Duplicate code
+ */
+
+duplicateCode(
+ unique int id: @duplication,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+similarCode(
+ unique int id: @similarity,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+@duplication_or_similarity = @duplication | @similarity
+
+tokens(
+ int id: @duplication_or_similarity ref,
+ int offset: int ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @external_element
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@external_element = @externalMetric | @externalDefect | @externalDataElement;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric, 3: span */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref);
+
+directive_line_offset(
+ unique int id: @directive_line ref,
+ int offset: int ref);
+
+directive_line_span(
+ unique int id: @directive_line ref,
+ int startLine: int ref,
+ int startColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ unique int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+compiler_generated(unique int id: @modifiable_direct ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_compiler_generated(
+ unique int id: @expr ref);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
+
+/* Common Intermediate Language - CIL */
+
+case @cil_instruction.opcode of
+ 0 = @cil_nop
+| 1 = @cil_break
+| 2 = @cil_ldarg_0
+| 3 = @cil_ldarg_1
+| 4 = @cil_ldarg_2
+| 5 = @cil_ldarg_3
+| 6 = @cil_ldloc_0
+| 7 = @cil_ldloc_1
+| 8 = @cil_ldloc_2
+| 9 = @cil_ldloc_3
+| 10 = @cil_stloc_0
+| 11 = @cil_stloc_1
+| 12 = @cil_stloc_2
+| 13 = @cil_stloc_3
+| 14 = @cil_ldarg_s
+| 15 = @cil_ldarga_s
+| 16 = @cil_starg_s
+| 17 = @cil_ldloc_s
+| 18 = @cil_ldloca_s
+| 19 = @cil_stloc_s
+| 20 = @cil_ldnull
+| 21 = @cil_ldc_i4_m1
+| 22 = @cil_ldc_i4_0
+| 23 = @cil_ldc_i4_1
+| 24 = @cil_ldc_i4_2
+| 25 = @cil_ldc_i4_3
+| 26 = @cil_ldc_i4_4
+| 27 = @cil_ldc_i4_5
+| 28 = @cil_ldc_i4_6
+| 29 = @cil_ldc_i4_7
+| 30 = @cil_ldc_i4_8
+| 31 = @cil_ldc_i4_s
+| 32 = @cil_ldc_i4
+| 33 = @cil_ldc_i8
+| 34 = @cil_ldc_r4
+| 35 = @cil_ldc_r8
+| 37 = @cil_dup
+| 38 = @cil_pop
+| 39 = @cil_jmp
+| 40 = @cil_call
+| 41 = @cil_calli
+| 42 = @cil_ret
+| 43 = @cil_br_s
+| 44 = @cil_brfalse_s
+| 45 = @cil_brtrue_s
+| 46 = @cil_beq_s
+| 47 = @cil_bge_s
+| 48 = @cil_bgt_s
+| 49 = @cil_ble_s
+| 50 = @cil_blt_s
+| 51 = @cil_bne_un_s
+| 52 = @cil_bge_un_s
+| 53 = @cil_bgt_un_s
+| 54 = @cil_ble_un_s
+| 55 = @cil_blt_un_s
+| 56 = @cil_br
+| 57 = @cil_brfalse
+| 58 = @cil_brtrue
+| 59 = @cil_beq
+| 60 = @cil_bge
+| 61 = @cil_bgt
+| 62 = @cil_ble
+| 63 = @cil_blt
+| 64 = @cil_bne_un
+| 65 = @cil_bge_un
+| 66 = @cil_bgt_un
+| 67 = @cil_ble_un
+| 68 = @cil_blt_un
+| 69 = @cil_switch
+| 70 = @cil_ldind_i1
+| 71 = @cil_ldind_u1
+| 72 = @cil_ldind_i2
+| 73 = @cil_ldind_u2
+| 74 = @cil_ldind_i4
+| 75 = @cil_ldind_u4
+| 76 = @cil_ldind_i8
+| 77 = @cil_ldind_i
+| 78 = @cil_ldind_r4
+| 79 = @cil_ldind_r8
+| 80 = @cil_ldind_ref
+| 81 = @cil_stind_ref
+| 82 = @cil_stind_i1
+| 83 = @cil_stind_i2
+| 84 = @cil_stind_i4
+| 85 = @cil_stind_i8
+| 86 = @cil_stind_r4
+| 87 = @cil_stind_r8
+| 88 = @cil_add
+| 89 = @cil_sub
+| 90 = @cil_mul
+| 91 = @cil_div
+| 92 = @cil_div_un
+| 93 = @cil_rem
+| 94 = @cil_rem_un
+| 95 = @cil_and
+| 96 = @cil_or
+| 97 = @cil_xor
+| 98 = @cil_shl
+| 99 = @cil_shr
+| 100 = @cil_shr_un
+| 101 = @cil_neg
+| 102 = @cil_not
+| 103 = @cil_conv_i1
+| 104 = @cil_conv_i2
+| 105 = @cil_conv_i4
+| 106 = @cil_conv_i8
+| 107 = @cil_conv_r4
+| 108 = @cil_conv_r8
+| 109 = @cil_conv_u4
+| 110 = @cil_conv_u8
+| 111 = @cil_callvirt
+| 112 = @cil_cpobj
+| 113 = @cil_ldobj
+| 114 = @cil_ldstr
+| 115 = @cil_newobj
+| 116 = @cil_castclass
+| 117 = @cil_isinst
+| 118 = @cil_conv_r_un
+| 121 = @cil_unbox
+| 122 = @cil_throw
+| 123 = @cil_ldfld
+| 124 = @cil_ldflda
+| 125 = @cil_stfld
+| 126 = @cil_ldsfld
+| 127 = @cil_ldsflda
+| 128 = @cil_stsfld
+| 129 = @cil_stobj
+| 130 = @cil_conv_ovf_i1_un
+| 131 = @cil_conv_ovf_i2_un
+| 132 = @cil_conv_ovf_i4_un
+| 133 = @cil_conv_ovf_i8_un
+| 134 = @cil_conv_ovf_u1_un
+| 135 = @cil_conv_ovf_u2_un
+| 136 = @cil_conv_ovf_u4_un
+| 137 = @cil_conv_ovf_u8_un
+| 138 = @cil_conv_ovf_i_un
+| 139 = @cil_conv_ovf_u_un
+| 140 = @cil_box
+| 141 = @cil_newarr
+| 142 = @cil_ldlen
+| 143 = @cil_ldelema
+| 144 = @cil_ldelem_i1
+| 145 = @cil_ldelem_u1
+| 146 = @cil_ldelem_i2
+| 147 = @cil_ldelem_u2
+| 148 = @cil_ldelem_i4
+| 149 = @cil_ldelem_u4
+| 150 = @cil_ldelem_i8
+| 151 = @cil_ldelem_i
+| 152 = @cil_ldelem_r4
+| 153 = @cil_ldelem_r8
+| 154 = @cil_ldelem_ref
+| 155 = @cil_stelem_i
+| 156 = @cil_stelem_i1
+| 157 = @cil_stelem_i2
+| 158 = @cil_stelem_i4
+| 159 = @cil_stelem_i8
+| 160 = @cil_stelem_r4
+| 161 = @cil_stelem_r8
+| 162 = @cil_stelem_ref
+| 163 = @cil_ldelem
+| 164 = @cil_stelem
+| 165 = @cil_unbox_any
+| 179 = @cil_conv_ovf_i1
+| 180 = @cil_conv_ovf_u1
+| 181 = @cil_conv_ovf_i2
+| 182 = @cil_conv_ovf_u2
+| 183 = @cil_conv_ovf_i4
+| 184 = @cil_conv_ovf_u4
+| 185 = @cil_conv_ovf_i8
+| 186 = @cil_conv_ovf_u8
+| 194 = @cil_refanyval
+| 195 = @cil_ckinfinite
+| 198 = @cil_mkrefany
+| 208 = @cil_ldtoken
+| 209 = @cil_conv_u2
+| 210 = @cil_conv_u1
+| 211 = @cil_conv_i
+| 212 = @cil_conv_ovf_i
+| 213 = @cil_conv_ovf_u
+| 214 = @cil_add_ovf
+| 215 = @cil_add_ovf_un
+| 216 = @cil_mul_ovf
+| 217 = @cil_mul_ovf_un
+| 218 = @cil_sub_ovf
+| 219 = @cil_sub_ovf_un
+| 220 = @cil_endfinally
+| 221 = @cil_leave
+| 222 = @cil_leave_s
+| 223 = @cil_stind_i
+| 224 = @cil_conv_u
+| 65024 = @cil_arglist
+| 65025 = @cil_ceq
+| 65026 = @cil_cgt
+| 65027 = @cil_cgt_un
+| 65028 = @cil_clt
+| 65029 = @cil_clt_un
+| 65030 = @cil_ldftn
+| 65031 = @cil_ldvirtftn
+| 65033 = @cil_ldarg
+| 65034 = @cil_ldarga
+| 65035 = @cil_starg
+| 65036 = @cil_ldloc
+| 65037 = @cil_ldloca
+| 65038 = @cil_stloc
+| 65039 = @cil_localloc
+| 65041 = @cil_endfilter
+| 65042 = @cil_unaligned
+| 65043 = @cil_volatile
+| 65044 = @cil_tail
+| 65045 = @cil_initobj
+| 65046 = @cil_constrained
+| 65047 = @cil_cpblk
+| 65048 = @cil_initblk
+| 65050 = @cil_rethrow
+| 65052 = @cil_sizeof
+| 65053 = @cil_refanytype
+| 65054 = @cil_readonly
+;
+
+// CIL ignored instructions
+
+@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
+
+// CIL local/parameter/field access
+
+@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
+@cil_starg_any = @cil_starg | @cil_starg_s;
+
+@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
+@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
+
+@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
+@cil_stfld_any = @cil_stfld | @cil_stsfld;
+
+@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
+@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
+@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
+@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
+
+@cil_stack_access = @cil_local_access | @cil_arg_access;
+@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
+
+@cil_access = @cil_read_access | @cil_write_access;
+
+// CIL constant/literal instructions
+
+@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
+
+@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
+ @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
+
+@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
+
+@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
+
+// Control flow
+
+@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
+@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
+ @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
+ @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
+ @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
+@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
+@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
+@cil_leave_any = @cil_leave | @cil_leave_s;
+@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
+
+// CIL call instructions
+
+@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
+
+// CIL expression instructions
+
+@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
+ @cil_newarr | @cil_ldtoken | @cil_sizeof |
+ @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
+
+@cil_unary_expr =
+ @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
+ @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
+ @cil_ldind | @cil_unbox;
+
+@cil_conversion_operation =
+ @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
+ @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
+ @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
+ @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
+ @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
+ @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
+ @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_i | @cil_conv_u | @cil_conv_r_un;
+
+@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
+ @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
+
+@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
+ @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
+
+@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
+
+@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
+
+@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
+ @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
+ @cil_sub_ovf | @cil_sub_ovf_un;
+
+@cil_unary_bitwise_operation = @cil_not;
+
+@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
+
+@cil_unary_arithmetic_operation = @cil_neg;
+
+@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
+
+// Elements that retrieve an address of something
+@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
+
+// CIL array instructions
+
+@cil_read_array =
+ @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
+ @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
+ @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
+
+@cil_write_array = @cil_stelem | @cil_stelem_ref |
+ @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
+ @cil_stelem_r4 | @cil_stelem_r8;
+
+@cil_throw_any = @cil_throw | @cil_rethrow;
+
+#keyset[impl, index]
+cil_instruction(
+ unique int id: @cil_instruction,
+ int opcode: int ref,
+ int index: int ref,
+ int impl: @cil_method_implementation ref);
+
+cil_jump(
+ unique int instruction: @cil_jump ref,
+ int target: @cil_instruction ref);
+
+cil_access(
+ unique int instruction: @cil_instruction ref,
+ int target: @cil_accessible ref);
+
+cil_value(
+ unique int instruction: @cil_literal ref,
+ string value: string ref);
+
+#keyset[instruction, index]
+cil_switch(
+ int instruction: @cil_switch ref,
+ int index: int ref,
+ int target: @cil_instruction ref);
+
+cil_instruction_location(
+ unique int id: @cil_instruction ref,
+ int loc: @location ref);
+
+cil_type_location(
+ int id: @cil_type ref,
+ int loc: @location ref);
+
+cil_method_location(
+ int id: @cil_method ref,
+ int loc: @location ref);
+
+@cil_namespace = @namespace;
+
+@cil_type_container = @cil_type | @cil_namespace | @cil_method;
+
+case @cil_type.kind of
+ 0 = @cil_valueorreftype
+| 1 = @cil_typeparameter
+| 2 = @cil_array_type
+| 3 = @cil_pointer_type
+| 4 = @cil_function_pointer_type
+;
+
+cil_type(
+ unique int id: @cil_type,
+ string name: string ref,
+ int kind: int ref,
+ int parent: @cil_type_container ref,
+ int sourceDecl: @cil_type ref);
+
+cil_pointer_type(
+ unique int id: @cil_pointer_type ref,
+ int pointee: @cil_type ref);
+
+cil_array_type(
+ unique int id: @cil_array_type ref,
+ int element_type: @cil_type ref,
+ int rank: int ref);
+
+cil_function_pointer_return_type(
+ unique int id: @cil_function_pointer_type ref,
+ int return_type: @cil_type ref);
+
+cil_method(
+ unique int id: @cil_method,
+ string name: string ref,
+ int parent: @cil_type ref,
+ int return_type: @cil_type ref);
+
+cil_method_source_declaration(
+ unique int method: @cil_method ref,
+ int source: @cil_method ref);
+
+cil_method_implementation(
+ unique int id: @cil_method_implementation,
+ int method: @cil_method ref,
+ int location: @assembly ref);
+
+cil_implements(
+ int id: @cil_method ref,
+ int decl: @cil_method ref);
+
+#keyset[parent, name]
+cil_field(
+ unique int id: @cil_field,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int field_type: @cil_type ref);
+
+@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
+@cil_named_element = @cil_declaration | @cil_namespace;
+@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
+@cil_accessible = @cil_declaration;
+@cil_variable = @cil_field | @cil_stack_variable;
+@cil_stack_variable = @cil_local_variable | @cil_parameter;
+@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
+@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
+@cil_parameterizable = @cil_method | @cil_function_pointer_type;
+@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
+
+#keyset[parameterizable, index]
+cil_parameter(
+ unique int id: @cil_parameter,
+ int parameterizable: @cil_parameterizable ref,
+ int index: int ref,
+ int param_type: @cil_type ref);
+
+cil_parameter_in(unique int id: @cil_parameter ref);
+cil_parameter_out(unique int id: @cil_parameter ref);
+
+cil_setter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+#keyset[id, modifier]
+cil_custom_modifiers(
+ int id: @cil_custom_modifier_receiver ref,
+ int modifier: @cil_type ref,
+ int kind: int ref); // modreq: 1, modopt: 0
+
+cil_type_annotation(
+ int id: @cil_has_type_annotation ref,
+ int annotation: int ref);
+
+cil_getter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+cil_adder(unique int event: @cil_event ref,
+ int method: @cil_method ref);
+
+cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_property(
+ unique int id: @cil_property,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int property_type: @cil_type ref);
+
+#keyset[parent, name]
+cil_event(unique int id: @cil_event,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int event_type: @cil_type ref);
+
+#keyset[impl, index]
+cil_local_variable(
+ unique int id: @cil_local_variable,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int var_type: @cil_type ref);
+
+cil_function_pointer_calling_conventions(
+ int id: @cil_function_pointer_type ref,
+ int kind: int ref);
+
+// CIL handlers (exception handlers etc).
+
+case @cil_handler.kind of
+ 0 = @cil_catch_handler
+| 1 = @cil_filter_handler
+| 2 = @cil_finally_handler
+| 4 = @cil_fault_handler
+;
+
+#keyset[impl, index]
+cil_handler(
+ unique int id: @cil_handler,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int kind: int ref,
+ int try_start: @cil_instruction ref,
+ int try_end: @cil_instruction ref,
+ int handler_start: @cil_instruction ref);
+
+cil_handler_filter(
+ unique int id: @cil_handler ref,
+ int filter_start: @cil_instruction ref);
+
+cil_handler_type(
+ unique int id: @cil_handler ref,
+ int catch_type: @cil_type ref);
+
+@cil_controlflow_node = @cil_entry_point | @cil_instruction;
+
+@cil_entry_point = @cil_method_implementation | @cil_handler;
+
+@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
+
+cil_method_stack_size(
+ unique int method: @cil_method_implementation ref,
+ int size: int ref);
+
+// CIL modifiers
+
+cil_public(int id: @cil_member ref);
+cil_private(int id: @cil_member ref);
+cil_protected(int id: @cil_member ref);
+cil_internal(int id: @cil_member ref);
+cil_static(int id: @cil_member ref);
+cil_sealed(int id: @cil_member ref);
+cil_virtual(int id: @cil_method ref);
+cil_abstract(int id: @cil_member ref);
+cil_class(int id: @cil_type ref);
+cil_interface(int id: @cil_type ref);
+cil_security(int id: @cil_member ref);
+cil_requiresecobject(int id: @cil_method ref);
+cil_specialname(int id: @cil_method ref);
+cil_newslot(int id: @cil_method ref);
+
+cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
+cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
+cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
+
+#keyset[unbound, index]
+cil_type_parameter(
+ int unbound: @cil_member ref,
+ int index: int ref,
+ int param: @cil_typeparameter ref);
+
+#keyset[bound, index]
+cil_type_argument(
+ int bound: @cil_member ref,
+ int index: int ref,
+ int t: @cil_type ref);
+
+// CIL type parameter constraints
+
+cil_typeparam_covariant(int tp: @cil_typeparameter ref);
+cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
+cil_typeparam_class(int tp: @cil_typeparameter ref);
+cil_typeparam_struct(int tp: @cil_typeparameter ref);
+cil_typeparam_new(int tp: @cil_typeparameter ref);
+cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
+
+// CIL attributes
+
+cil_attribute(
+ unique int attributeid: @cil_attribute,
+ int element: @cil_declaration ref,
+ int constructor: @cil_method ref);
+
+#keyset[attribute_id, param]
+cil_attribute_named_argument(
+ int attribute_id: @cil_attribute ref,
+ string param: string ref,
+ string value: string ref);
+
+#keyset[attribute_id, index]
+cil_attribute_positional_argument(
+ int attribute_id: @cil_attribute ref,
+ int index: int ref,
+ string value: string ref);
+
+
+// Common .Net data model covering both C# and CIL
+
+// Common elements
+@dotnet_element = @element | @cil_element;
+@dotnet_named_element = @named_element | @cil_named_element;
+@dotnet_callable = @callable | @cil_method;
+@dotnet_variable = @variable | @cil_variable;
+@dotnet_field = @field | @cil_field;
+@dotnet_parameter = @parameter | @cil_parameter;
+@dotnet_declaration = @declaration | @cil_declaration;
+@dotnet_member = @member | @cil_member;
+@dotnet_event = @event | @cil_event;
+@dotnet_property = @property | @cil_property | @indexer;
+@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
+
+// Common types
+@dotnet_type = @type | @cil_type;
+@dotnet_call = @call | @cil_call_any;
+@dotnet_throw = @throw_element | @cil_throw_any;
+@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
+@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
+@dotnet_array_type = @array_type | @cil_array_type;
+@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
+@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
+@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
+
+// Attributes
+@dotnet_attribute = @attribute | @cil_attribute;
+
+// Expressions
+@dotnet_expr = @expr | @cil_expr;
+
+// Literals
+@dotnet_literal = @literal_expr | @cil_literal;
+@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
+@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
+@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
+@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
+
+@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
+ @callable | @value_or_ref_type | @void_type;
+
+#keyset[entity, location]
+metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
diff --git a/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme
new file mode 100644
index 00000000000..193c35b0e37
--- /dev/null
+++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/semmlecode.csharp.dbscheme
@@ -0,0 +1,2088 @@
+/* This is a dummy line to alter the dbscheme, so we can make a database upgrade
+ * without actually changing any of the dbscheme predicates. It contains a date
+ * to allow for such updates in the future as well.
+ *
+ * 2021-07-14
+ *
+ * DO NOT remove this comment carelessly, since it can revert the dbscheme back to a
+ * previously seen state (matching a previously seen SHA), which would make the upgrade
+ * mechanism not work properly.
+ */
+
+/**
+ * An invocation of the compiler. Note that more than one file may be
+ * compiled per invocation. For example, this command compiles three
+ * source files:
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * The `id` simply identifies the invocation, while `cwd` is the working
+ * directory from which the compiler was invoked.
+ */
+compilations(
+ unique int id : @compilation,
+ string cwd : string ref
+);
+
+/**
+ * The arguments that were passed to the extractor for a compiler
+ * invocation. If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then typically there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | --compiler
+ * 1 | *path to compiler*
+ * 2 | --cil
+ * 3 | f1.cs
+ * 4 | f2.cs
+ * 5 | f3.cs
+ */
+#keyset[id, num]
+compilation_args(
+ int id : @compilation ref,
+ int num : int ref,
+ string arg : string ref
+);
+
+/**
+ * The source files that are compiled by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | f1.cs
+ * 1 | f2.cs
+ * 2 | f3.cs
+ */
+#keyset[id, num]
+compilation_compiling_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The references used by a compiler invocation.
+ * If `id` is for the compiler invocation
+ *
+ * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll
+ *
+ * then there will be rows for
+ *
+ * num | arg
+ * --- | ---
+ * 0 | ref1.dll
+ * 1 | ref2.dll
+ * 2 | ref3.dll
+ */
+#keyset[id, num]
+compilation_referencing_files(
+ int id : @compilation ref,
+ int num : int ref,
+ int file : @file ref
+);
+
+/**
+ * The time taken by the extractor for a compiler invocation.
+ *
+ * For each file `num`, there will be rows for
+ *
+ * kind | seconds
+ * ---- | ---
+ * 1 | CPU seconds used by the extractor frontend
+ * 2 | Elapsed seconds during the extractor frontend
+ * 3 | CPU seconds used by the extractor backend
+ * 4 | Elapsed seconds during the extractor backend
+ */
+#keyset[id, num, kind]
+compilation_time(
+ int id : @compilation ref,
+ int num : int ref,
+ /* kind:
+ 1 = frontend_cpu_seconds
+ 2 = frontend_elapsed_seconds
+ 3 = extractor_cpu_seconds
+ 4 = extractor_elapsed_seconds
+ */
+ int kind : int ref,
+ float seconds : float ref
+);
+
+/**
+ * An error or warning generated by the extractor.
+ * The diagnostic message `diagnostic` was generated during compiler
+ * invocation `compilation`, and is the `file_number_diagnostic_number`th
+ * message generated while extracting the `file_number`th file of that
+ * invocation.
+ */
+#keyset[compilation, file_number, file_number_diagnostic_number]
+diagnostic_for(
+ unique int diagnostic : @diagnostic ref,
+ int compilation : @compilation ref,
+ int file_number : int ref,
+ int file_number_diagnostic_number : int ref
+);
+
+diagnostics(
+ unique int id: @diagnostic,
+ int severity: int ref,
+ string error_tag: string ref,
+ string error_message: string ref,
+ string full_error_message: string ref,
+ int location: @location_default ref
+);
+
+extractor_messages(
+ unique int id: @extractor_message,
+ int severity: int ref,
+ string origin : string ref,
+ string text : string ref,
+ string entity : string ref,
+ int location: @location_default ref,
+ string stack_trace : string ref
+);
+
+/**
+ * If extraction was successful, then `cpu_seconds` and
+ * `elapsed_seconds` are the CPU time and elapsed time (respectively)
+ * that extraction took for compiler invocation `id`.
+ */
+compilation_finished(
+ unique int id : @compilation ref,
+ float cpu_seconds : float ref,
+ float elapsed_seconds : float ref
+);
+
+compilation_assembly(
+ unique int id : @compilation ref,
+ int assembly: @assembly ref
+)
+
+/*
+ * External artifacts
+ */
+
+externalDefects(
+ unique int id: @externalDefect,
+ string queryPath: string ref,
+ int location: @location ref,
+ string message: string ref,
+ float severity: float ref);
+
+externalMetrics(
+ unique int id: @externalMetric,
+ string queryPath: string ref,
+ int location: @location ref,
+ float value: float ref);
+
+externalData(
+ int id: @externalDataElement,
+ string path: string ref,
+ int column: int ref,
+ string value: string ref);
+
+snapshotDate(
+ unique date snapshotDate: date ref);
+
+sourceLocationPrefix(
+ string prefix: string ref);
+
+/*
+ * Duplicate code
+ */
+
+duplicateCode(
+ unique int id: @duplication,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+similarCode(
+ unique int id: @similarity,
+ string relativePath: string ref,
+ int equivClass: int ref);
+
+@duplication_or_similarity = @duplication | @similarity
+
+tokens(
+ int id: @duplication_or_similarity ref,
+ int offset: int ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+/*
+ * C# dbscheme
+ */
+
+/** ELEMENTS **/
+
+@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration
+ | @using_directive | @type_parameter_constraints | @external_element
+ | @xmllocatable | @asp_element | @namespace | @preprocessor_directive;
+
+@declaration = @callable | @generic | @assignable | @namespace;
+
+@named_element = @namespace | @declaration;
+
+@declaration_with_accessors = @property | @indexer | @event;
+
+@assignable = @variable | @assignable_with_accessors | @event;
+
+@assignable_with_accessors = @property | @indexer;
+
+@external_element = @externalMetric | @externalDefect | @externalDataElement;
+
+@attributable = @assembly | @field | @parameter | @operator | @method | @constructor
+ | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors
+ | @local_function;
+
+/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/
+
+@location = @location_default | @assembly;
+
+locations_default(
+ unique int id: @location_default,
+ int file: @file ref,
+ int beginLine: int ref,
+ int beginColumn: int ref,
+ int endLine: int ref,
+ int endColumn: int ref);
+
+locations_mapped(
+ unique int id: @location_default ref,
+ int mapped_to: @location_default ref);
+
+@sourceline = @file | @callable | @xmllocatable;
+
+numlines(
+ int element_id: @sourceline ref,
+ int num_lines: int ref,
+ int num_code: int ref,
+ int num_comment: int ref);
+
+assemblies(
+ unique int id: @assembly,
+ int file: @file ref,
+ string fullname: string ref,
+ string name: string ref,
+ string version: string ref);
+
+files(
+ unique int id: @file,
+ string name: string ref);
+
+folders(
+ unique int id: @folder,
+ string name: string ref);
+
+@container = @folder | @file ;
+
+containerparent(
+ int parent: @container ref,
+ unique int child: @container ref);
+
+file_extraction_mode(
+ unique int file: @file ref,
+ int mode: int ref
+ /* 0 = normal, 1 = standalone extractor */
+ );
+
+/** NAMESPACES **/
+
+@type_container = @namespace | @type;
+
+namespaces(
+ unique int id: @namespace,
+ string name: string ref);
+
+namespace_declarations(
+ unique int id: @namespace_declaration,
+ int namespace_id: @namespace ref);
+
+namespace_declaration_location(
+ unique int id: @namespace_declaration ref,
+ int loc: @location ref);
+
+parent_namespace(
+ unique int child_id: @type_container ref,
+ int namespace_id: @namespace ref);
+
+@declaration_or_directive = @namespace_declaration | @type | @using_directive;
+
+parent_namespace_declaration(
+ int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes
+ int namespace_id: @namespace_declaration ref);
+
+@using_directive = @using_namespace_directive | @using_static_directive;
+
+using_global(
+ unique int id: @using_directive ref
+);
+
+using_namespace_directives(
+ unique int id: @using_namespace_directive,
+ int namespace_id: @namespace ref);
+
+using_static_directives(
+ unique int id: @using_static_directive,
+ int type_id: @type_or_ref ref);
+
+using_directive_location(
+ unique int id: @using_directive ref,
+ int loc: @location ref);
+
+@preprocessor_directive = @pragma_warning | @pragma_checksum | @directive_define | @directive_undefine | @directive_warning
+ | @directive_error | @directive_nullable | @directive_line | @directive_region | @directive_endregion | @directive_if
+ | @directive_elif | @directive_else | @directive_endif;
+
+@conditional_directive = @directive_if | @directive_elif;
+@branch_directive = @directive_if | @directive_elif | @directive_else;
+
+directive_ifs(
+ unique int id: @directive_if,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref); /* 0: false, 1: true */
+
+directive_elifs(
+ unique int id: @directive_elif,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int conditionValue: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+directive_elses(
+ unique int id: @directive_else,
+ int branchTaken: int ref, /* 0: false, 1: true */
+ int parent: @directive_if ref,
+ int index: int ref);
+
+#keyset[id, start]
+directive_endifs(
+ unique int id: @directive_endif,
+ unique int start: @directive_if ref);
+
+directive_define_symbols(
+ unique int id: @define_symbol_expr ref,
+ string name: string ref);
+
+directive_regions(
+ unique int id: @directive_region,
+ string name: string ref);
+
+#keyset[id, start]
+directive_endregions(
+ unique int id: @directive_endregion,
+ unique int start: @directive_region ref);
+
+directive_lines(
+ unique int id: @directive_line,
+ int kind: int ref); /* 0: default, 1: hidden, 2: numeric */
+
+directive_line_value(
+ unique int id: @directive_line ref,
+ int line: int ref);
+
+directive_line_file(
+ unique int id: @directive_line ref,
+ int file: @file ref
+)
+
+directive_nullables(
+ unique int id: @directive_nullable,
+ int setting: int ref, /* 0: disable, 1: enable, 2: restore */
+ int target: int ref); /* 0: none, 1: annotations, 2: warnings */
+
+directive_warnings(
+ unique int id: @directive_warning,
+ string message: string ref);
+
+directive_errors(
+ unique int id: @directive_error,
+ string message: string ref);
+
+directive_undefines(
+ unique int id: @directive_undefine,
+ string name: string ref);
+
+directive_defines(
+ unique int id: @directive_define,
+ string name: string ref);
+
+pragma_checksums(
+ unique int id: @pragma_checksum,
+ int file: @file ref,
+ string guid: string ref,
+ string bytes: string ref);
+
+pragma_warnings(
+ unique int id: @pragma_warning,
+ int kind: int ref /* 0 = disable, 1 = restore */);
+
+#keyset[id, index]
+pragma_warning_error_codes(
+ int id: @pragma_warning ref,
+ string errorCode: string ref,
+ int index: int ref);
+
+preprocessor_directive_location(
+ unique int id: @preprocessor_directive ref,
+ int loc: @location ref);
+
+preprocessor_directive_compilation(
+ unique int id: @preprocessor_directive ref,
+ int compilation: @compilation ref);
+
+preprocessor_directive_active(
+ unique int id: @preprocessor_directive ref,
+ int active: int ref); /* 0: false, 1: true */
+
+/** TYPES **/
+
+types(
+ unique int id: @type,
+ int kind: int ref,
+ string name: string ref);
+
+case @type.kind of
+ 1 = @bool_type
+| 2 = @char_type
+| 3 = @decimal_type
+| 4 = @sbyte_type
+| 5 = @short_type
+| 6 = @int_type
+| 7 = @long_type
+| 8 = @byte_type
+| 9 = @ushort_type
+| 10 = @uint_type
+| 11 = @ulong_type
+| 12 = @float_type
+| 13 = @double_type
+| 14 = @enum_type
+| 15 = @struct_type
+| 17 = @class_type
+| 19 = @interface_type
+| 20 = @delegate_type
+| 21 = @null_type
+| 22 = @type_parameter
+| 23 = @pointer_type
+| 24 = @nullable_type
+| 25 = @array_type
+| 26 = @void_type
+| 27 = @int_ptr_type
+| 28 = @uint_ptr_type
+| 29 = @dynamic_type
+| 30 = @arglist_type
+| 31 = @unknown_type
+| 32 = @tuple_type
+| 33 = @function_pointer_type
+ ;
+
+@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type;
+@integral_type = @signed_integral_type | @unsigned_integral_type;
+@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type;
+@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type;
+@floating_point_type = @float_type | @double_type;
+@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type
+ | @uint_ptr_type | @tuple_type;
+@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type
+ | @dynamic_type;
+@value_or_ref_type = @value_type | @ref_type;
+
+typerefs(
+ unique int id: @typeref,
+ string name: string ref);
+
+typeref_type(
+ int id: @typeref ref,
+ unique int typeId: @type ref);
+
+@type_or_ref = @type | @typeref;
+
+array_element_type(
+ unique int array: @array_type ref,
+ int dimension: int ref,
+ int rank: int ref,
+ int element: @type_or_ref ref);
+
+nullable_underlying_type(
+ unique int nullable: @nullable_type ref,
+ int underlying: @type_or_ref ref);
+
+pointer_referent_type(
+ unique int pointer: @pointer_type ref,
+ int referent: @type_or_ref ref);
+
+enum_underlying_type(
+ unique int enum_id: @enum_type ref,
+ int underlying_type_id: @type_or_ref ref);
+
+delegate_return_type(
+ unique int delegate_id: @delegate_type ref,
+ int return_type_id: @type_or_ref ref);
+
+function_pointer_return_type(
+ unique int function_pointer_id: @function_pointer_type ref,
+ int return_type_id: @type_or_ref ref);
+
+extend(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+anonymous_types(
+ unique int id: @type ref);
+
+@interface_or_ref = @interface_type | @typeref;
+
+implement(
+ int sub: @type ref,
+ int super: @type_or_ref ref);
+
+type_location(
+ int id: @type ref,
+ int loc: @location ref);
+
+tuple_underlying_type(
+ unique int tuple: @tuple_type ref,
+ int struct: @type_or_ref ref);
+
+#keyset[tuple, index]
+tuple_element(
+ int tuple: @tuple_type ref,
+ int index: int ref,
+ unique int field: @field ref);
+
+attributes(
+ unique int id: @attribute,
+ int type_id: @type_or_ref ref,
+ int target: @attributable ref);
+
+attribute_location(
+ int id: @attribute ref,
+ int loc: @location ref);
+
+@type_mention_parent = @element | @type_mention;
+
+type_mention(
+ unique int id: @type_mention,
+ int type_id: @type_or_ref ref,
+ int parent: @type_mention_parent ref);
+
+type_mention_location(
+ unique int id: @type_mention ref,
+ int loc: @location ref);
+
+@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic | @function_pointer_type;
+
+/**
+ * A direct annotation on an entity, for example `string? x;`.
+ *
+ * Annotations:
+ * 2 = reftype is not annotated "!"
+ * 3 = reftype is annotated "?"
+ * 4 = readonly ref type / in parameter
+ * 5 = ref type parameter, return or local variable
+ * 6 = out parameter
+ *
+ * Note that the annotation depends on the element it annotates.
+ * @assignable: The annotation is on the type of the assignable, for example the variable type.
+ * @type_parameter: The annotation is on the reftype constraint
+ * @callable: The annotation is on the return type
+ * @array_type: The annotation is on the element type
+ */
+type_annotation(int id: @has_type_annotation ref, int annotation: int ref);
+
+nullability(unique int nullability: @nullability, int kind: int ref);
+
+case @nullability.kind of
+ 0 = @oblivious
+| 1 = @not_annotated
+| 2 = @annotated
+;
+
+#keyset[parent, index]
+nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref)
+
+type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref);
+
+/**
+ * The nullable flow state of an expression, as determined by Roslyn.
+ * 0 = none (default, not populated)
+ * 1 = not null
+ * 2 = maybe null
+ */
+expr_flowstate(unique int id: @expr ref, int state: int ref);
+
+/** GENERICS **/
+
+@generic = @type | @method | @local_function;
+
+type_parameters(
+ unique int id: @type_parameter ref,
+ int index: int ref,
+ int generic_id: @generic ref,
+ int variance: int ref /* none = 0, out = 1, in = 2 */);
+
+#keyset[constructed_id, index]
+type_arguments(
+ int id: @type_or_ref ref,
+ int index: int ref,
+ int constructed_id: @generic_or_ref ref);
+
+@generic_or_ref = @generic | @typeref;
+
+constructed_generic(
+ unique int constructed: @generic ref,
+ int generic: @generic_or_ref ref);
+
+type_parameter_constraints(
+ unique int id: @type_parameter_constraints,
+ int param_id: @type_parameter ref);
+
+type_parameter_constraints_location(
+ int id: @type_parameter_constraints ref,
+ int loc: @location ref);
+
+general_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int kind: int ref /* class = 1, struct = 2, new = 3 */);
+
+specific_type_parameter_constraints(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref);
+
+specific_type_parameter_nullability(
+ int id: @type_parameter_constraints ref,
+ int base_id: @type_or_ref ref,
+ int nullability: @nullability ref);
+
+/** FUNCTION POINTERS */
+
+function_pointer_calling_conventions(
+ int id: @function_pointer_type ref,
+ int kind: int ref);
+
+#keyset[id, index]
+has_unmanaged_calling_conventions(
+ int id: @function_pointer_type ref,
+ int index: int ref,
+ int conv_id: @type_or_ref ref);
+
+/** MODIFIERS */
+
+@modifiable = @modifiable_direct | @event_accessor;
+
+@modifiable_direct = @member | @accessor | @local_function | @anonymous_function_expr;
+
+modifiers(
+ unique int id: @modifier,
+ string name: string ref);
+
+has_modifiers(
+ int id: @modifiable_direct ref,
+ int mod_id: @modifier ref);
+
+compiler_generated(unique int id: @modifiable_direct ref);
+
+/** MEMBERS **/
+
+@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type;
+
+@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr;
+
+@virtualizable = @method | @property | @indexer | @event;
+
+exprorstmt_name(
+ unique int parent_id: @named_exprorstmt ref,
+ string name: string ref);
+
+nested_types(
+ unique int id: @type ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @type ref);
+
+properties(
+ unique int id: @property,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @property ref);
+
+property_location(
+ int id: @property ref,
+ int loc: @location ref);
+
+indexers(
+ unique int id: @indexer,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @indexer ref);
+
+indexer_location(
+ int id: @indexer ref,
+ int loc: @location ref);
+
+accessors(
+ unique int id: @accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_member_id: @member ref,
+ int unbound_id: @accessor ref);
+
+case @accessor.kind of
+ 1 = @getter
+| 2 = @setter
+ ;
+
+init_only_accessors(
+ unique int id: @accessor ref);
+
+accessor_location(
+ int id: @accessor ref,
+ int loc: @location ref);
+
+events(
+ unique int id: @event,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @event ref);
+
+event_location(
+ int id: @event ref,
+ int loc: @location ref);
+
+event_accessors(
+ unique int id: @event_accessor,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_event_id: @event ref,
+ int unbound_id: @event_accessor ref);
+
+case @event_accessor.kind of
+ 1 = @add_event_accessor
+| 2 = @remove_event_accessor
+ ;
+
+event_accessor_location(
+ int id: @event_accessor ref,
+ int loc: @location ref);
+
+operators(
+ unique int id: @operator,
+ string name: string ref,
+ string symbol: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @operator ref);
+
+operator_location(
+ int id: @operator ref,
+ int loc: @location ref);
+
+constant_value(
+ int id: @variable ref,
+ string value: string ref);
+
+/** CALLABLES **/
+
+@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function;
+
+@callable_accessor = @accessor | @event_accessor;
+
+methods(
+ unique int id: @method,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @method ref);
+
+method_location(
+ int id: @method ref,
+ int loc: @location ref);
+
+constructors(
+ unique int id: @constructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @constructor ref);
+
+constructor_location(
+ int id: @constructor ref,
+ int loc: @location ref);
+
+destructors(
+ unique int id: @destructor,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int unbound_id: @destructor ref);
+
+destructor_location(
+ int id: @destructor ref,
+ int loc: @location ref);
+
+overrides(
+ int id: @callable ref,
+ int base_id: @callable ref);
+
+explicitly_implements(
+ int id: @member ref,
+ int interface_id: @interface_or_ref ref);
+
+local_functions(
+ unique int id: @local_function,
+ string name: string ref,
+ int return_type: @type ref,
+ int unbound_id: @local_function ref);
+
+local_function_stmts(
+ unique int fn: @local_function_stmt ref,
+ int stmt: @local_function ref);
+
+/** VARIABLES **/
+
+@variable = @local_scope_variable | @field;
+
+@local_scope_variable = @local_variable | @parameter;
+
+fields(
+ unique int id: @field,
+ int kind: int ref,
+ string name: string ref,
+ int declaring_type_id: @type ref,
+ int type_id: @type_or_ref ref,
+ int unbound_id: @field ref);
+
+case @field.kind of
+ 1 = @addressable_field
+| 2 = @constant
+ ;
+
+field_location(
+ int id: @field ref,
+ int loc: @location ref);
+
+localvars(
+ unique int id: @local_variable,
+ int kind: int ref,
+ string name: string ref,
+ int implicitly_typed: int ref /* 0 = no, 1 = yes */,
+ int type_id: @type_or_ref ref,
+ int parent_id: @local_var_decl_expr ref);
+
+case @local_variable.kind of
+ 1 = @addressable_local_variable
+| 2 = @local_constant
+| 3 = @local_variable_ref
+ ;
+
+localvar_location(
+ unique int id: @local_variable ref,
+ int loc: @location ref);
+
+@parameterizable = @callable | @delegate_type | @indexer | @function_pointer_type;
+
+#keyset[name, parent_id]
+#keyset[index, parent_id]
+params(
+ unique int id: @parameter,
+ string name: string ref,
+ int type_id: @type_or_ref ref,
+ int index: int ref,
+ int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */
+ int parent_id: @parameterizable ref,
+ int unbound_id: @parameter ref);
+
+param_location(
+ int id: @parameter ref,
+ int loc: @location ref);
+
+/** STATEMENTS **/
+
+@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent;
+
+statements(
+ unique int id: @stmt,
+ int kind: int ref);
+
+#keyset[index, parent]
+stmt_parent(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_stmt_parent = @callable;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+stmt_parent_top_level(
+ unique int stmt: @stmt ref,
+ int index: int ref,
+ int parent: @top_level_stmt_parent ref);
+
+case @stmt.kind of
+ 1 = @block_stmt
+| 2 = @expr_stmt
+| 3 = @if_stmt
+| 4 = @switch_stmt
+| 5 = @while_stmt
+| 6 = @do_stmt
+| 7 = @for_stmt
+| 8 = @foreach_stmt
+| 9 = @break_stmt
+| 10 = @continue_stmt
+| 11 = @goto_stmt
+| 12 = @goto_case_stmt
+| 13 = @goto_default_stmt
+| 14 = @throw_stmt
+| 15 = @return_stmt
+| 16 = @yield_stmt
+| 17 = @try_stmt
+| 18 = @checked_stmt
+| 19 = @unchecked_stmt
+| 20 = @lock_stmt
+| 21 = @using_block_stmt
+| 22 = @var_decl_stmt
+| 23 = @const_decl_stmt
+| 24 = @empty_stmt
+| 25 = @unsafe_stmt
+| 26 = @fixed_stmt
+| 27 = @label_stmt
+| 28 = @catch
+| 29 = @case_stmt
+| 30 = @local_function_stmt
+| 31 = @using_decl_stmt
+ ;
+
+@using_stmt = @using_block_stmt | @using_decl_stmt;
+
+@labeled_stmt = @label_stmt | @case;
+
+@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt;
+
+@cond_stmt = @if_stmt | @switch_stmt;
+
+@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt;
+
+@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt
+ | @yield_stmt;
+
+@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt;
+
+
+stmt_location(
+ unique int id: @stmt ref,
+ int loc: @location ref);
+
+catch_type(
+ unique int catch_id: @catch ref,
+ int type_id: @type_or_ref ref,
+ int kind: int ref /* explicit = 1, implicit = 2 */);
+
+foreach_stmt_info(
+ unique int id: @foreach_stmt ref,
+ int kind: int ref /* non-async = 1, async = 2 */);
+
+@foreach_symbol = @method | @property | @type_or_ref;
+
+#keyset[id, kind]
+foreach_stmt_desugar(
+ int id: @foreach_stmt ref,
+ int symbol: @foreach_symbol ref,
+ int kind: int ref /* GetEnumeratorMethod = 1, CurrentProperty = 2, MoveNextMethod = 3, DisposeMethod = 4, ElementType = 5 */);
+
+/** EXPRESSIONS **/
+
+expressions(
+ unique int id: @expr,
+ int kind: int ref,
+ int type_id: @type_or_ref ref);
+
+#keyset[index, parent]
+expr_parent(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @control_flow_element ref);
+
+@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter | @directive_if | @directive_elif;
+
+@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent;
+
+// [index, parent] is not a keyset because the same parent may be compiled multiple times
+expr_parent_top_level(
+ unique int expr: @expr ref,
+ int index: int ref,
+ int parent: @top_level_exprorstmt_parent ref);
+
+case @expr.kind of
+/* literal */
+ 1 = @bool_literal_expr
+| 2 = @char_literal_expr
+| 3 = @decimal_literal_expr
+| 4 = @int_literal_expr
+| 5 = @long_literal_expr
+| 6 = @uint_literal_expr
+| 7 = @ulong_literal_expr
+| 8 = @float_literal_expr
+| 9 = @double_literal_expr
+| 10 = @string_literal_expr
+| 11 = @null_literal_expr
+/* primary & unary */
+| 12 = @this_access_expr
+| 13 = @base_access_expr
+| 14 = @local_variable_access_expr
+| 15 = @parameter_access_expr
+| 16 = @field_access_expr
+| 17 = @property_access_expr
+| 18 = @method_access_expr
+| 19 = @event_access_expr
+| 20 = @indexer_access_expr
+| 21 = @array_access_expr
+| 22 = @type_access_expr
+| 23 = @typeof_expr
+| 24 = @method_invocation_expr
+| 25 = @delegate_invocation_expr
+| 26 = @operator_invocation_expr
+| 27 = @cast_expr
+| 28 = @object_creation_expr
+| 29 = @explicit_delegate_creation_expr
+| 30 = @implicit_delegate_creation_expr
+| 31 = @array_creation_expr
+| 32 = @default_expr
+| 33 = @plus_expr
+| 34 = @minus_expr
+| 35 = @bit_not_expr
+| 36 = @log_not_expr
+| 37 = @post_incr_expr
+| 38 = @post_decr_expr
+| 39 = @pre_incr_expr
+| 40 = @pre_decr_expr
+/* multiplicative */
+| 41 = @mul_expr
+| 42 = @div_expr
+| 43 = @rem_expr
+/* additive */
+| 44 = @add_expr
+| 45 = @sub_expr
+/* shift */
+| 46 = @lshift_expr
+| 47 = @rshift_expr
+/* relational */
+| 48 = @lt_expr
+| 49 = @gt_expr
+| 50 = @le_expr
+| 51 = @ge_expr
+/* equality */
+| 52 = @eq_expr
+| 53 = @ne_expr
+/* logical */
+| 54 = @bit_and_expr
+| 55 = @bit_xor_expr
+| 56 = @bit_or_expr
+| 57 = @log_and_expr
+| 58 = @log_or_expr
+/* type testing */
+| 59 = @is_expr
+| 60 = @as_expr
+/* null coalescing */
+| 61 = @null_coalescing_expr
+/* conditional */
+| 62 = @conditional_expr
+/* assignment */
+| 63 = @simple_assign_expr
+| 64 = @assign_add_expr
+| 65 = @assign_sub_expr
+| 66 = @assign_mul_expr
+| 67 = @assign_div_expr
+| 68 = @assign_rem_expr
+| 69 = @assign_and_expr
+| 70 = @assign_xor_expr
+| 71 = @assign_or_expr
+| 72 = @assign_lshift_expr
+| 73 = @assign_rshift_expr
+/* more */
+| 74 = @object_init_expr
+| 75 = @collection_init_expr
+| 76 = @array_init_expr
+| 77 = @checked_expr
+| 78 = @unchecked_expr
+| 79 = @constructor_init_expr
+| 80 = @add_event_expr
+| 81 = @remove_event_expr
+| 82 = @par_expr
+| 83 = @local_var_decl_expr
+| 84 = @lambda_expr
+| 85 = @anonymous_method_expr
+| 86 = @namespace_expr
+/* dynamic */
+| 92 = @dynamic_element_access_expr
+| 93 = @dynamic_member_access_expr
+/* unsafe */
+| 100 = @pointer_indirection_expr
+| 101 = @address_of_expr
+| 102 = @sizeof_expr
+/* async */
+| 103 = @await_expr
+/* C# 6.0 */
+| 104 = @nameof_expr
+| 105 = @interpolated_string_expr
+| 106 = @unknown_expr
+/* C# 7.0 */
+| 107 = @throw_expr
+| 108 = @tuple_expr
+| 109 = @local_function_invocation_expr
+| 110 = @ref_expr
+| 111 = @discard_expr
+/* C# 8.0 */
+| 112 = @range_expr
+| 113 = @index_expr
+| 114 = @switch_expr
+| 115 = @recursive_pattern_expr
+| 116 = @property_pattern_expr
+| 117 = @positional_pattern_expr
+| 118 = @switch_case_expr
+| 119 = @assign_coalesce_expr
+| 120 = @suppress_nullable_warning_expr
+| 121 = @namespace_access_expr
+/* C# 9.0 */
+| 122 = @lt_pattern_expr
+| 123 = @gt_pattern_expr
+| 124 = @le_pattern_expr
+| 125 = @ge_pattern_expr
+| 126 = @not_pattern_expr
+| 127 = @and_pattern_expr
+| 128 = @or_pattern_expr
+| 129 = @function_pointer_invocation_expr
+| 130 = @with_expr
+/* Preprocessor */
+| 999 = @define_symbol_expr
+;
+
+@switch = @switch_stmt | @switch_expr;
+@case = @case_stmt | @switch_case_expr;
+@pattern_match = @case | @is_expr;
+@unary_pattern_expr = @not_pattern_expr;
+@relational_pattern_expr = @gt_pattern_expr | @lt_pattern_expr | @ge_pattern_expr | @le_pattern_expr;
+@binary_pattern_expr = @and_pattern_expr | @or_pattern_expr;
+
+@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr;
+@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr;
+@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr
+ | @string_literal_expr | @null_literal_expr;
+
+@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr;
+@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr;
+@assign_event_expr = @add_event_expr | @remove_event_expr;
+
+@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr
+ | @assign_rem_expr
+@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr
+ | @assign_lshift_expr | @assign_rshift_expr;
+
+@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr
+ | @method_access_expr | @type_access_expr | @dynamic_member_access_expr;
+@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr;
+@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr;
+
+@local_variable_access = @local_variable_access_expr | @local_var_decl_expr;
+@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access;
+@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr;
+
+@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr
+ | @event_access_expr | @dynamic_member_access_expr;
+
+@objectorcollection_init_expr = @object_init_expr | @collection_init_expr;
+
+@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr;
+
+@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr;
+@incr_op_expr = @pre_incr_expr | @post_incr_expr;
+@decr_op_expr = @pre_decr_expr | @post_decr_expr;
+@mut_op_expr = @incr_op_expr | @decr_op_expr;
+@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr;
+@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr;
+
+@ternary_log_op_expr = @conditional_expr;
+@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr;
+@un_log_op_expr = @log_not_expr;
+@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr;
+
+@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr
+ | @rshift_expr;
+@un_bit_op_expr = @bit_not_expr;
+@bit_expr = @un_bit_op_expr | @bin_bit_op_expr;
+
+@equality_op_expr = @eq_expr | @ne_expr;
+@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr;
+@comp_expr = @equality_op_expr | @rel_op_expr;
+
+@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op;
+
+@ternary_op = @ternary_log_op_expr;
+@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr;
+@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr
+ | @pointer_indirection_expr | @address_of_expr;
+
+@anonymous_function_expr = @lambda_expr | @anonymous_method_expr;
+
+@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr
+ | @delegate_invocation_expr | @object_creation_expr | @call_access_expr
+ | @local_function_invocation_expr | @function_pointer_invocation_expr;
+
+@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr;
+
+@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr
+ | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr;
+
+@throw_element = @throw_expr | @throw_stmt;
+
+@implicitly_typeable_object_creation_expr = @object_creation_expr | @explicit_delegate_creation_expr;
+
+implicitly_typed_array_creation(
+ unique int id: @array_creation_expr ref);
+
+explicitly_sized_array_creation(
+ unique int id: @array_creation_expr ref);
+
+stackalloc_array_creation(
+ unique int id: @array_creation_expr ref);
+
+implicitly_typed_object_creation(
+ unique int id: @implicitly_typeable_object_creation_expr ref);
+
+mutator_invocation_mode(
+ unique int id: @operator_invocation_expr ref,
+ int mode: int ref /* prefix = 1, postfix = 2*/);
+
+expr_compiler_generated(
+ unique int id: @expr ref);
+
+expr_value(
+ unique int id: @expr ref,
+ string value: string ref);
+
+expr_call(
+ unique int caller_id: @expr ref,
+ int target_id: @callable ref);
+
+expr_access(
+ unique int accesser_id: @access_expr ref,
+ int target_id: @accessible ref);
+
+@accessible = @method | @assignable | @local_function | @namespace;
+
+expr_location(
+ unique int id: @expr ref,
+ int loc: @location ref);
+
+dynamic_member_name(
+ unique int id: @late_bindable_expr ref,
+ string name: string ref);
+
+@qualifiable_expr = @member_access_expr
+ | @method_invocation_expr
+ | @element_access_expr;
+
+conditional_access(
+ unique int id: @qualifiable_expr ref);
+
+expr_argument(
+ unique int id: @expr ref,
+ int mode: int ref);
+ /* mode is the same as params: value = 0, ref = 1, out = 2 */
+
+expr_argument_name(
+ unique int id: @expr ref,
+ string name: string ref);
+
+/** CONTROL/DATA FLOW **/
+
+@control_flow_element = @stmt | @expr;
+
+/* XML Files */
+
+xmlEncoding (
+ unique int id: @file ref,
+ string encoding: string ref);
+
+xmlDTDs(
+ unique int id: @xmldtd,
+ string root: string ref,
+ string publicId: string ref,
+ string systemId: string ref,
+ int fileid: @file ref);
+
+xmlElements(
+ unique int id: @xmlelement,
+ string name: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlAttrs(
+ unique int id: @xmlattribute,
+ int elementid: @xmlelement ref,
+ string name: string ref,
+ string value: string ref,
+ int idx: int ref,
+ int fileid: @file ref);
+
+xmlNs(
+ int id: @xmlnamespace,
+ string prefixName: string ref,
+ string URI: string ref,
+ int fileid: @file ref);
+
+xmlHasNs(
+ int elementId: @xmlnamespaceable ref,
+ int nsId: @xmlnamespace ref,
+ int fileid: @file ref);
+
+xmlComments(
+ unique int id: @xmlcomment,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int fileid: @file ref);
+
+xmlChars(
+ unique int id: @xmlcharacters,
+ string text: string ref,
+ int parentid: @xmlparent ref,
+ int idx: int ref,
+ int isCDATA: int ref,
+ int fileid: @file ref);
+
+@xmlparent = @file | @xmlelement;
+@xmlnamespaceable = @xmlelement | @xmlattribute;
+
+xmllocations(
+ int xmlElement: @xmllocatable ref,
+ int location: @location_default ref);
+
+@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace;
+
+/* Comments */
+
+commentline(
+ unique int id: @commentline,
+ int kind: int ref,
+ string text: string ref,
+ string rawtext: string ref);
+
+case @commentline.kind of
+ 0 = @singlelinecomment
+| 1 = @xmldoccomment
+| 2 = @multilinecomment;
+
+commentline_location(
+ unique int id: @commentline ref,
+ int loc: @location ref);
+
+commentblock(
+ unique int id : @commentblock);
+
+commentblock_location(
+ unique int id: @commentblock ref,
+ int loc: @location ref);
+
+commentblock_binding(
+ int id: @commentblock ref,
+ int entity: @element ref,
+ int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */
+
+commentblock_child(
+ int id: @commentblock ref,
+ int commentline: @commentline ref,
+ int index: int ref);
+
+/* ASP.NET */
+
+case @asp_element.kind of
+ 0=@asp_close_tag
+| 1=@asp_code
+| 2=@asp_comment
+| 3=@asp_data_binding
+| 4=@asp_directive
+| 5=@asp_open_tag
+| 6=@asp_quoted_string
+| 7=@asp_text
+| 8=@asp_xml_directive;
+
+@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string;
+
+asp_elements(
+ unique int id: @asp_element,
+ int kind: int ref,
+ int loc: @location ref);
+
+asp_comment_server(unique int comment: @asp_comment ref);
+asp_code_inline(unique int code: @asp_code ref);
+asp_directive_attribute(
+ int directive: @asp_directive ref,
+ int index: int ref,
+ string name: string ref,
+ int value: @asp_quoted_string ref);
+asp_directive_name(
+ unique int directive: @asp_directive ref,
+ string name: string ref);
+asp_element_body(
+ unique int element: @asp_element ref,
+ string body: string ref);
+asp_tag_attribute(
+ int tag: @asp_open_tag ref,
+ int index: int ref,
+ string name: string ref,
+ int attribute: @asp_attribute ref);
+asp_tag_name(
+ unique int tag: @asp_open_tag ref,
+ string name: string ref);
+asp_tag_isempty(int tag: @asp_open_tag ref);
+
+/* Common Intermediate Language - CIL */
+
+case @cil_instruction.opcode of
+ 0 = @cil_nop
+| 1 = @cil_break
+| 2 = @cil_ldarg_0
+| 3 = @cil_ldarg_1
+| 4 = @cil_ldarg_2
+| 5 = @cil_ldarg_3
+| 6 = @cil_ldloc_0
+| 7 = @cil_ldloc_1
+| 8 = @cil_ldloc_2
+| 9 = @cil_ldloc_3
+| 10 = @cil_stloc_0
+| 11 = @cil_stloc_1
+| 12 = @cil_stloc_2
+| 13 = @cil_stloc_3
+| 14 = @cil_ldarg_s
+| 15 = @cil_ldarga_s
+| 16 = @cil_starg_s
+| 17 = @cil_ldloc_s
+| 18 = @cil_ldloca_s
+| 19 = @cil_stloc_s
+| 20 = @cil_ldnull
+| 21 = @cil_ldc_i4_m1
+| 22 = @cil_ldc_i4_0
+| 23 = @cil_ldc_i4_1
+| 24 = @cil_ldc_i4_2
+| 25 = @cil_ldc_i4_3
+| 26 = @cil_ldc_i4_4
+| 27 = @cil_ldc_i4_5
+| 28 = @cil_ldc_i4_6
+| 29 = @cil_ldc_i4_7
+| 30 = @cil_ldc_i4_8
+| 31 = @cil_ldc_i4_s
+| 32 = @cil_ldc_i4
+| 33 = @cil_ldc_i8
+| 34 = @cil_ldc_r4
+| 35 = @cil_ldc_r8
+| 37 = @cil_dup
+| 38 = @cil_pop
+| 39 = @cil_jmp
+| 40 = @cil_call
+| 41 = @cil_calli
+| 42 = @cil_ret
+| 43 = @cil_br_s
+| 44 = @cil_brfalse_s
+| 45 = @cil_brtrue_s
+| 46 = @cil_beq_s
+| 47 = @cil_bge_s
+| 48 = @cil_bgt_s
+| 49 = @cil_ble_s
+| 50 = @cil_blt_s
+| 51 = @cil_bne_un_s
+| 52 = @cil_bge_un_s
+| 53 = @cil_bgt_un_s
+| 54 = @cil_ble_un_s
+| 55 = @cil_blt_un_s
+| 56 = @cil_br
+| 57 = @cil_brfalse
+| 58 = @cil_brtrue
+| 59 = @cil_beq
+| 60 = @cil_bge
+| 61 = @cil_bgt
+| 62 = @cil_ble
+| 63 = @cil_blt
+| 64 = @cil_bne_un
+| 65 = @cil_bge_un
+| 66 = @cil_bgt_un
+| 67 = @cil_ble_un
+| 68 = @cil_blt_un
+| 69 = @cil_switch
+| 70 = @cil_ldind_i1
+| 71 = @cil_ldind_u1
+| 72 = @cil_ldind_i2
+| 73 = @cil_ldind_u2
+| 74 = @cil_ldind_i4
+| 75 = @cil_ldind_u4
+| 76 = @cil_ldind_i8
+| 77 = @cil_ldind_i
+| 78 = @cil_ldind_r4
+| 79 = @cil_ldind_r8
+| 80 = @cil_ldind_ref
+| 81 = @cil_stind_ref
+| 82 = @cil_stind_i1
+| 83 = @cil_stind_i2
+| 84 = @cil_stind_i4
+| 85 = @cil_stind_i8
+| 86 = @cil_stind_r4
+| 87 = @cil_stind_r8
+| 88 = @cil_add
+| 89 = @cil_sub
+| 90 = @cil_mul
+| 91 = @cil_div
+| 92 = @cil_div_un
+| 93 = @cil_rem
+| 94 = @cil_rem_un
+| 95 = @cil_and
+| 96 = @cil_or
+| 97 = @cil_xor
+| 98 = @cil_shl
+| 99 = @cil_shr
+| 100 = @cil_shr_un
+| 101 = @cil_neg
+| 102 = @cil_not
+| 103 = @cil_conv_i1
+| 104 = @cil_conv_i2
+| 105 = @cil_conv_i4
+| 106 = @cil_conv_i8
+| 107 = @cil_conv_r4
+| 108 = @cil_conv_r8
+| 109 = @cil_conv_u4
+| 110 = @cil_conv_u8
+| 111 = @cil_callvirt
+| 112 = @cil_cpobj
+| 113 = @cil_ldobj
+| 114 = @cil_ldstr
+| 115 = @cil_newobj
+| 116 = @cil_castclass
+| 117 = @cil_isinst
+| 118 = @cil_conv_r_un
+| 121 = @cil_unbox
+| 122 = @cil_throw
+| 123 = @cil_ldfld
+| 124 = @cil_ldflda
+| 125 = @cil_stfld
+| 126 = @cil_ldsfld
+| 127 = @cil_ldsflda
+| 128 = @cil_stsfld
+| 129 = @cil_stobj
+| 130 = @cil_conv_ovf_i1_un
+| 131 = @cil_conv_ovf_i2_un
+| 132 = @cil_conv_ovf_i4_un
+| 133 = @cil_conv_ovf_i8_un
+| 134 = @cil_conv_ovf_u1_un
+| 135 = @cil_conv_ovf_u2_un
+| 136 = @cil_conv_ovf_u4_un
+| 137 = @cil_conv_ovf_u8_un
+| 138 = @cil_conv_ovf_i_un
+| 139 = @cil_conv_ovf_u_un
+| 140 = @cil_box
+| 141 = @cil_newarr
+| 142 = @cil_ldlen
+| 143 = @cil_ldelema
+| 144 = @cil_ldelem_i1
+| 145 = @cil_ldelem_u1
+| 146 = @cil_ldelem_i2
+| 147 = @cil_ldelem_u2
+| 148 = @cil_ldelem_i4
+| 149 = @cil_ldelem_u4
+| 150 = @cil_ldelem_i8
+| 151 = @cil_ldelem_i
+| 152 = @cil_ldelem_r4
+| 153 = @cil_ldelem_r8
+| 154 = @cil_ldelem_ref
+| 155 = @cil_stelem_i
+| 156 = @cil_stelem_i1
+| 157 = @cil_stelem_i2
+| 158 = @cil_stelem_i4
+| 159 = @cil_stelem_i8
+| 160 = @cil_stelem_r4
+| 161 = @cil_stelem_r8
+| 162 = @cil_stelem_ref
+| 163 = @cil_ldelem
+| 164 = @cil_stelem
+| 165 = @cil_unbox_any
+| 179 = @cil_conv_ovf_i1
+| 180 = @cil_conv_ovf_u1
+| 181 = @cil_conv_ovf_i2
+| 182 = @cil_conv_ovf_u2
+| 183 = @cil_conv_ovf_i4
+| 184 = @cil_conv_ovf_u4
+| 185 = @cil_conv_ovf_i8
+| 186 = @cil_conv_ovf_u8
+| 194 = @cil_refanyval
+| 195 = @cil_ckinfinite
+| 198 = @cil_mkrefany
+| 208 = @cil_ldtoken
+| 209 = @cil_conv_u2
+| 210 = @cil_conv_u1
+| 211 = @cil_conv_i
+| 212 = @cil_conv_ovf_i
+| 213 = @cil_conv_ovf_u
+| 214 = @cil_add_ovf
+| 215 = @cil_add_ovf_un
+| 216 = @cil_mul_ovf
+| 217 = @cil_mul_ovf_un
+| 218 = @cil_sub_ovf
+| 219 = @cil_sub_ovf_un
+| 220 = @cil_endfinally
+| 221 = @cil_leave
+| 222 = @cil_leave_s
+| 223 = @cil_stind_i
+| 224 = @cil_conv_u
+| 65024 = @cil_arglist
+| 65025 = @cil_ceq
+| 65026 = @cil_cgt
+| 65027 = @cil_cgt_un
+| 65028 = @cil_clt
+| 65029 = @cil_clt_un
+| 65030 = @cil_ldftn
+| 65031 = @cil_ldvirtftn
+| 65033 = @cil_ldarg
+| 65034 = @cil_ldarga
+| 65035 = @cil_starg
+| 65036 = @cil_ldloc
+| 65037 = @cil_ldloca
+| 65038 = @cil_stloc
+| 65039 = @cil_localloc
+| 65041 = @cil_endfilter
+| 65042 = @cil_unaligned
+| 65043 = @cil_volatile
+| 65044 = @cil_tail
+| 65045 = @cil_initobj
+| 65046 = @cil_constrained
+| 65047 = @cil_cpblk
+| 65048 = @cil_initblk
+| 65050 = @cil_rethrow
+| 65052 = @cil_sizeof
+| 65053 = @cil_refanytype
+| 65054 = @cil_readonly
+;
+
+// CIL ignored instructions
+
+@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
+
+// CIL local/parameter/field access
+
+@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
+@cil_starg_any = @cil_starg | @cil_starg_s;
+
+@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
+@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
+
+@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
+@cil_stfld_any = @cil_stfld | @cil_stsfld;
+
+@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
+@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
+@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
+@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
+
+@cil_stack_access = @cil_local_access | @cil_arg_access;
+@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
+
+@cil_access = @cil_read_access | @cil_write_access;
+
+// CIL constant/literal instructions
+
+@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
+
+@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
+ @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
+
+@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
+
+@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
+
+// Control flow
+
+@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
+@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
+ @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
+ @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
+ @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
+@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
+@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
+@cil_leave_any = @cil_leave | @cil_leave_s;
+@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
+
+// CIL call instructions
+
+@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
+
+// CIL expression instructions
+
+@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
+ @cil_newarr | @cil_ldtoken | @cil_sizeof |
+ @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
+
+@cil_unary_expr =
+ @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
+ @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
+ @cil_ldind | @cil_unbox;
+
+@cil_conversion_operation =
+ @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
+ @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
+ @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
+ @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
+ @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
+ @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
+ @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
+ @cil_conv_i | @cil_conv_u | @cil_conv_r_un;
+
+@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
+ @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
+
+@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
+ @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
+
+@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
+
+@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
+
+@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
+ @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
+ @cil_sub_ovf | @cil_sub_ovf_un;
+
+@cil_unary_bitwise_operation = @cil_not;
+
+@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
+
+@cil_unary_arithmetic_operation = @cil_neg;
+
+@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
+
+// Elements that retrieve an address of something
+@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
+
+// CIL array instructions
+
+@cil_read_array =
+ @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
+ @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
+ @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
+
+@cil_write_array = @cil_stelem | @cil_stelem_ref |
+ @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
+ @cil_stelem_r4 | @cil_stelem_r8;
+
+@cil_throw_any = @cil_throw | @cil_rethrow;
+
+#keyset[impl, index]
+cil_instruction(
+ unique int id: @cil_instruction,
+ int opcode: int ref,
+ int index: int ref,
+ int impl: @cil_method_implementation ref);
+
+cil_jump(
+ unique int instruction: @cil_jump ref,
+ int target: @cil_instruction ref);
+
+cil_access(
+ unique int instruction: @cil_instruction ref,
+ int target: @cil_accessible ref);
+
+cil_value(
+ unique int instruction: @cil_literal ref,
+ string value: string ref);
+
+#keyset[instruction, index]
+cil_switch(
+ int instruction: @cil_switch ref,
+ int index: int ref,
+ int target: @cil_instruction ref);
+
+cil_instruction_location(
+ unique int id: @cil_instruction ref,
+ int loc: @location ref);
+
+cil_type_location(
+ int id: @cil_type ref,
+ int loc: @location ref);
+
+cil_method_location(
+ int id: @cil_method ref,
+ int loc: @location ref);
+
+@cil_namespace = @namespace;
+
+@cil_type_container = @cil_type | @cil_namespace | @cil_method;
+
+case @cil_type.kind of
+ 0 = @cil_valueorreftype
+| 1 = @cil_typeparameter
+| 2 = @cil_array_type
+| 3 = @cil_pointer_type
+| 4 = @cil_function_pointer_type
+;
+
+cil_type(
+ unique int id: @cil_type,
+ string name: string ref,
+ int kind: int ref,
+ int parent: @cil_type_container ref,
+ int sourceDecl: @cil_type ref);
+
+cil_pointer_type(
+ unique int id: @cil_pointer_type ref,
+ int pointee: @cil_type ref);
+
+cil_array_type(
+ unique int id: @cil_array_type ref,
+ int element_type: @cil_type ref,
+ int rank: int ref);
+
+cil_function_pointer_return_type(
+ unique int id: @cil_function_pointer_type ref,
+ int return_type: @cil_type ref);
+
+cil_method(
+ unique int id: @cil_method,
+ string name: string ref,
+ int parent: @cil_type ref,
+ int return_type: @cil_type ref);
+
+cil_method_source_declaration(
+ unique int method: @cil_method ref,
+ int source: @cil_method ref);
+
+cil_method_implementation(
+ unique int id: @cil_method_implementation,
+ int method: @cil_method ref,
+ int location: @assembly ref);
+
+cil_implements(
+ int id: @cil_method ref,
+ int decl: @cil_method ref);
+
+#keyset[parent, name]
+cil_field(
+ unique int id: @cil_field,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int field_type: @cil_type ref);
+
+@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
+@cil_named_element = @cil_declaration | @cil_namespace;
+@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
+@cil_accessible = @cil_declaration;
+@cil_variable = @cil_field | @cil_stack_variable;
+@cil_stack_variable = @cil_local_variable | @cil_parameter;
+@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
+@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field | @cil_function_pointer_type;
+@cil_parameterizable = @cil_method | @cil_function_pointer_type;
+@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_method | @cil_function_pointer_type;
+
+#keyset[parameterizable, index]
+cil_parameter(
+ unique int id: @cil_parameter,
+ int parameterizable: @cil_parameterizable ref,
+ int index: int ref,
+ int param_type: @cil_type ref);
+
+cil_parameter_in(unique int id: @cil_parameter ref);
+cil_parameter_out(unique int id: @cil_parameter ref);
+
+cil_setter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+#keyset[id, modifier]
+cil_custom_modifiers(
+ int id: @cil_custom_modifier_receiver ref,
+ int modifier: @cil_type ref,
+ int kind: int ref); // modreq: 1, modopt: 0
+
+cil_type_annotation(
+ int id: @cil_has_type_annotation ref,
+ int annotation: int ref);
+
+cil_getter(unique int prop: @cil_property ref,
+ int method: @cil_method ref);
+
+cil_adder(unique int event: @cil_event ref,
+ int method: @cil_method ref);
+
+cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
+
+cil_property(
+ unique int id: @cil_property,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int property_type: @cil_type ref);
+
+#keyset[parent, name]
+cil_event(unique int id: @cil_event,
+ int parent: @cil_type ref,
+ string name: string ref,
+ int event_type: @cil_type ref);
+
+#keyset[impl, index]
+cil_local_variable(
+ unique int id: @cil_local_variable,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int var_type: @cil_type ref);
+
+cil_function_pointer_calling_conventions(
+ int id: @cil_function_pointer_type ref,
+ int kind: int ref);
+
+// CIL handlers (exception handlers etc).
+
+case @cil_handler.kind of
+ 0 = @cil_catch_handler
+| 1 = @cil_filter_handler
+| 2 = @cil_finally_handler
+| 4 = @cil_fault_handler
+;
+
+#keyset[impl, index]
+cil_handler(
+ unique int id: @cil_handler,
+ int impl: @cil_method_implementation ref,
+ int index: int ref,
+ int kind: int ref,
+ int try_start: @cil_instruction ref,
+ int try_end: @cil_instruction ref,
+ int handler_start: @cil_instruction ref);
+
+cil_handler_filter(
+ unique int id: @cil_handler ref,
+ int filter_start: @cil_instruction ref);
+
+cil_handler_type(
+ unique int id: @cil_handler ref,
+ int catch_type: @cil_type ref);
+
+@cil_controlflow_node = @cil_entry_point | @cil_instruction;
+
+@cil_entry_point = @cil_method_implementation | @cil_handler;
+
+@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
+
+cil_method_stack_size(
+ unique int method: @cil_method_implementation ref,
+ int size: int ref);
+
+// CIL modifiers
+
+cil_public(int id: @cil_member ref);
+cil_private(int id: @cil_member ref);
+cil_protected(int id: @cil_member ref);
+cil_internal(int id: @cil_member ref);
+cil_static(int id: @cil_member ref);
+cil_sealed(int id: @cil_member ref);
+cil_virtual(int id: @cil_method ref);
+cil_abstract(int id: @cil_member ref);
+cil_class(int id: @cil_type ref);
+cil_interface(int id: @cil_type ref);
+cil_security(int id: @cil_member ref);
+cil_requiresecobject(int id: @cil_method ref);
+cil_specialname(int id: @cil_method ref);
+cil_newslot(int id: @cil_method ref);
+
+cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
+cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
+cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
+
+#keyset[unbound, index]
+cil_type_parameter(
+ int unbound: @cil_member ref,
+ int index: int ref,
+ int param: @cil_typeparameter ref);
+
+#keyset[bound, index]
+cil_type_argument(
+ int bound: @cil_member ref,
+ int index: int ref,
+ int t: @cil_type ref);
+
+// CIL type parameter constraints
+
+cil_typeparam_covariant(int tp: @cil_typeparameter ref);
+cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
+cil_typeparam_class(int tp: @cil_typeparameter ref);
+cil_typeparam_struct(int tp: @cil_typeparameter ref);
+cil_typeparam_new(int tp: @cil_typeparameter ref);
+cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
+
+// CIL attributes
+
+cil_attribute(
+ unique int attributeid: @cil_attribute,
+ int element: @cil_declaration ref,
+ int constructor: @cil_method ref);
+
+#keyset[attribute_id, param]
+cil_attribute_named_argument(
+ int attribute_id: @cil_attribute ref,
+ string param: string ref,
+ string value: string ref);
+
+#keyset[attribute_id, index]
+cil_attribute_positional_argument(
+ int attribute_id: @cil_attribute ref,
+ int index: int ref,
+ string value: string ref);
+
+
+// Common .Net data model covering both C# and CIL
+
+// Common elements
+@dotnet_element = @element | @cil_element;
+@dotnet_named_element = @named_element | @cil_named_element;
+@dotnet_callable = @callable | @cil_method;
+@dotnet_variable = @variable | @cil_variable;
+@dotnet_field = @field | @cil_field;
+@dotnet_parameter = @parameter | @cil_parameter;
+@dotnet_declaration = @declaration | @cil_declaration;
+@dotnet_member = @member | @cil_member;
+@dotnet_event = @event | @cil_event;
+@dotnet_property = @property | @cil_property | @indexer;
+@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
+
+// Common types
+@dotnet_type = @type | @cil_type;
+@dotnet_call = @call | @cil_call_any;
+@dotnet_throw = @throw_element | @cil_throw_any;
+@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
+@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
+@dotnet_array_type = @array_type | @cil_array_type;
+@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
+@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
+@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
+
+// Attributes
+@dotnet_attribute = @attribute | @cil_attribute;
+
+// Expressions
+@dotnet_expr = @expr | @cil_expr;
+
+// Literals
+@dotnet_literal = @literal_expr | @cil_literal;
+@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
+@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
+@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
+@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
+
+@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
+ @callable | @value_or_ref_type | @void_type;
+
+#keyset[entity, location]
+metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
diff --git a/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties
new file mode 100644
index 00000000000..47cd8720ce9
--- /dev/null
+++ b/csharp/downgrades/ff083666c7f75e0d039182cb6344a7be1a2f0421/upgrade.properties
@@ -0,0 +1,5 @@
+description: Remove support for line span pragma.
+compatibility: backwards
+directive_line_offset.rel: delete
+directive_line_span.rel: delete
+
From de3d62b3f4d6f9e50a4e4ff21f95fa754bc067b2 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 09:33:40 +0100
Subject: [PATCH 033/196] C#: Update stats file for the new relations (they are
unfortunately empty).
---
.../ql/lib/semmlecode.csharp.dbscheme.stats | 3403 +++++++++--------
1 file changed, 1851 insertions(+), 1552 deletions(-)
diff --git a/csharp/ql/lib/semmlecode.csharp.dbscheme.stats b/csharp/ql/lib/semmlecode.csharp.dbscheme.stats
index 46d7b963528..f458da72beb 100644
--- a/csharp/ql/lib/semmlecode.csharp.dbscheme.stats
+++ b/csharp/ql/lib/semmlecode.csharp.dbscheme.stats
@@ -42,11 +42,11 @@
@folder
- 484046
+ 484045
@namespace
- 367576
+ 367575
@namespace_declaration
@@ -174,19 +174,19 @@
@struct_type
- 1223176
+ 1223173
@class_type
- 3789357
+ 3789350
@interface_type
- 2384809
+ 2384805
@delegate_type
- 2249826
+ 2249822
@null_type
@@ -194,7 +194,7 @@
@type_parameter
- 831792
+ 831790
@pointer_type
@@ -242,23 +242,23 @@
@typeref
- 3537567
-
-
- @location_default
- 43578550
+ 3537560
@attribute
- 10551347
+ 10551328
@type_mention
- 4147997
+ 4147990
+
+
+ @location_default
+ 43578472
@oblivious
- 15642
+ 15641
@not_annotated
@@ -270,7 +270,7 @@
@type_parameter_constraints
- 1730282
+ 1730279
@modifier
@@ -278,7 +278,7 @@
@property
- 4879894
+ 4879885
@indexer
@@ -286,11 +286,11 @@
@getter
- 4950272
+ 4950263
@setter
- 864801
+ 864799
@event
@@ -306,15 +306,15 @@
@operator
- 807643
+ 807641
@method
- 15027131
+ 15027104
@constructor
- 4401500
+ 4401492
@destructor
@@ -326,15 +326,15 @@
@addressable_field
- 8156775
+ 8156760
@constant
- 2845825
+ 2845820
@addressable_local_variable
- 353480
+ 353479
@local_constant
@@ -346,15 +346,15 @@
@parameter
- 27466281
+ 27466231
@block_stmt
- 470421
+ 470420
@expr_stmt
- 493565
+ 493564
@if_stmt
@@ -382,7 +382,7 @@
@break_stmt
- 42189
+ 42188
@continue_stmt
@@ -390,7 +390,7 @@
@goto_stmt
- 3587
+ 3586
@goto_case_stmt
@@ -466,7 +466,7 @@
@local_function_stmt
- 3317
+ 3316
@using_decl_stmt
@@ -474,7 +474,7 @@
@bool_literal_expr
- 585969
+ 585968
@char_literal_expr
@@ -482,7 +482,7 @@
@int_literal_expr
- 3350910
+ 3350904
@long_literal_expr
@@ -506,11 +506,11 @@
@string_literal_expr
- 1548385
+ 1548382
@null_literal_expr
- 155827
+ 155826
@this_access_expr
@@ -522,11 +522,11 @@
@local_variable_access_expr
- 1030138
+ 1030136
@parameter_access_expr
- 969868
+ 969866
@field_access_expr
@@ -534,7 +534,7 @@
@property_access_expr
- 1360056
+ 1360054
@method_access_expr
@@ -554,15 +554,15 @@
@type_access_expr
- 919476
+ 919474
@typeof_expr
- 439082
+ 439081
@method_invocation_expr
- 832881
+ 832863
@delegate_invocation_expr
@@ -570,15 +570,15 @@
@operator_invocation_expr
- 778750
+ 778748
@cast_expr
- 540190
+ 540196
@object_creation_expr
- 438905
+ 438904
@explicit_delegate_creation_expr
@@ -590,11 +590,11 @@
@array_creation_expr
- 349824
+ 349823
@default_expr
- 790760
+ 790758
@minus_expr
@@ -710,7 +710,7 @@
@simple_assign_expr
- 1592072
+ 1592070
@assign_add_expr
@@ -730,7 +730,7 @@
@object_init_expr
- 383017
+ 383016
@collection_init_expr
@@ -762,11 +762,11 @@
@local_var_decl_expr
- 354491
+ 354490
@lambda_expr
- 733508
+ 733506
@anonymous_method_expr
@@ -802,7 +802,7 @@
@decimal_literal_expr
- 131181
+ 131180
@plus_expr
@@ -958,11 +958,11 @@
@xmlelement
- 1042734675
+ 1042732803
@xmlattribute
- 782957811
+ 782956405
@xmlnamespace
@@ -974,7 +974,7 @@
@xmlcharacters
- 808544061
+ 808542609
@singlelinecomment
@@ -982,7 +982,7 @@
@xmldoccomment
- 1212394
+ 1212392
@multilinecomment
@@ -990,7 +990,7 @@
@commentblock
- 412296
+ 412295
@asp_close_tag
@@ -1030,11 +1030,11 @@
@cil_valueorreftype
- 7660331
+ 7660317
@cil_typeparameter
- 1302994
+ 1302992
@cil_array_type
@@ -1050,11 +1050,11 @@
@cil_method
- 28926216
+ 28926164
@cil_ceq
- 683258
+ 683257
@cil_cgt
@@ -1062,11 +1062,11 @@
@cil_cgt_un
- 260989
+ 260988
@cil_clt
- 55669
+ 55668
@cil_clt_un
@@ -1074,7 +1074,7 @@
@cil_ldftn
- 2118027
+ 2118023
@cil_ldvirtftn
@@ -1110,11 +1110,11 @@
@cil_initobj
- 698444
+ 698443
@cil_constrained
- 557146
+ 557145
@cil_cpblk
@@ -1138,7 +1138,7 @@
@cil_stsfld
- 1909496
+ 1909493
@cil_stobj
@@ -1146,19 +1146,19 @@
@cil_box
- 1043089
+ 1043087
@cil_newarr
- 1178162
+ 1178159
@cil_ldlen
- 418971
+ 418970
@cil_ldelema
- 524864
+ 524863
@cil_ldelem_i1
@@ -1202,7 +1202,7 @@
@cil_ldelem_ref
- 253309
+ 253308
@cil_stelem_i
@@ -1230,7 +1230,7 @@
@cil_stelem_ref
- 3101391
+ 3101385
@cil_ldelem
@@ -1258,7 +1258,7 @@
@cil_ldtoken
- 749623
+ 749621
@cil_conv_u2
@@ -1266,7 +1266,7 @@
@cil_conv_u1
- 175034
+ 175033
@cil_conv_i
@@ -1290,15 +1290,15 @@
@cil_endfinally
- 1445725
+ 1445722
@cil_leave
- 508918
+ 508917
@cil_leave_s
- 2302564
+ 2302560
@cil_stind_i
@@ -1310,131 +1310,131 @@
@cil_nop
- 1547248
+ 1547241
@cil_ldarg_0
- 39364252
+ 39364181
@cil_ldarg_1
- 15405533
+ 15405506
@cil_ldarg_2
- 5488999
+ 5488989
@cil_ldarg_3
- 2376435
+ 2376431
@cil_ldloc_0
- 12928933
+ 12928909
@cil_ldloc_1
- 6975728
+ 6975715
@cil_ldloc_2
- 4951075
+ 4951066
@cil_ldloc_3
- 3108312
+ 3108306
@cil_stloc_0
- 6417366
+ 6417355
@cil_stloc_1
- 3676175
+ 3676168
@cil_stloc_2
- 2658099
+ 2658095
@cil_stloc_3
- 1822152
+ 1822149
@cil_ldarg_s
- 2508752
+ 2508747
@cil_ldarga_s
- 917085
+ 917084
@cil_starg_s
- 198638
+ 198637
@cil_ldloc_s
- 10621053
+ 10621034
@cil_ldloca_s
- 7189487
+ 7189474
@cil_stloc_s
- 6640346
+ 6640335
@cil_ldnull
- 5392406
+ 5392397
@cil_ldc_i4_m1
- 640280
+ 640279
@cil_ldc_i4_0
- 7980548
+ 7980533
@cil_ldc_i4_1
- 6322972
+ 6322961
@cil_ldc_i4_2
- 1431536
+ 1431534
@cil_ldc_i4_3
- 788673
+ 788672
@cil_ldc_i4_4
- 724283
+ 724282
@cil_ldc_i4_5
- 424937
+ 424936
@cil_ldc_i4_6
- 245434
+ 245433
@cil_ldc_i4_7
- 218055
+ 218054
@cil_ldc_i4_8
- 326616
+ 326615
@cil_ldc_i4_s
- 3951635
+ 3951628
@cil_ldc_i4
- 2083966
+ 2083962
@cil_ldc_i8
@@ -1442,7 +1442,7 @@
@cil_ldc_r4
- 22823
+ 22822
@cil_ldc_r8
@@ -1450,15 +1450,15 @@
@cil_dup
- 6812192
+ 6812179
@cil_pop
- 2850598
+ 2850593
@cil_call
- 35891791
+ 35891726
@cil_calli
@@ -1466,23 +1466,23 @@
@cil_ret
- 23260143
+ 23260101
@cil_br_s
- 4244082
+ 4244074
@cil_brfalse_s
- 7354021
+ 7354008
@cil_brtrue_s
- 6868468
+ 6868456
@cil_beq_s
- 1166967
+ 1166965
@cil_bge_s
@@ -1494,15 +1494,15 @@
@cil_ble_s
- 251335
+ 251334
@cil_blt_s
- 426846
+ 426845
@cil_bne_un_s
- 1697190
+ 1697187
@cil_bge_un_s
@@ -1522,19 +1522,19 @@
@cil_br
- 1052158
+ 1052156
@cil_brfalse
- 700831
+ 700830
@cil_brtrue
- 590512
+ 590511
@cil_beq
- 308566
+ 308565
@cil_bge
@@ -1542,7 +1542,7 @@
@cil_bgt
- 26164
+ 26163
@cil_ble
@@ -1626,7 +1626,7 @@
@cil_stind_i4
- 324338
+ 324337
@cil_stind_i8
@@ -1642,15 +1642,15 @@
@cil_add
- 1977553
+ 1977549
@cil_sub
- 739882
+ 739880
@cil_mul
- 313317
+ 313316
@cil_div
@@ -1670,11 +1670,11 @@
@cil_and
- 371763
+ 371762
@cil_or
- 165879
+ 165878
@cil_xor
@@ -1710,7 +1710,7 @@
@cil_conv_i4
- 392308
+ 392307
@cil_conv_i8
@@ -1734,7 +1734,7 @@
@cil_callvirt
- 30280801
+ 30280746
@cil_cpobj
@@ -1746,19 +1746,19 @@
@cil_ldstr
- 8268547
+ 8268532
@cil_newobj
- 9351013
+ 9350996
@cil_castclass
- 1325296
+ 1325294
@cil_isinst
- 2016430
+ 2016426
@cil_conv_r_un
@@ -1770,23 +1770,23 @@
@cil_throw
- 5164351
+ 5164341
@cil_ldfld
- 16903695
+ 16903665
@cil_ldflda
- 1433641
+ 1433638
@cil_stfld
- 8348623
+ 8348608
@cil_ldsfld
- 7724179
+ 7724165
@cil_ldsflda
@@ -1926,19 +1926,19 @@
@cil_method_implementation
- 19889366
+ 19889330
@cil_field
- 11684992
+ 11684971
@cil_parameter
- 55186717
+ 55186618
@cil_property
- 4409961
+ 4409953
@cil_event
@@ -1946,7 +1946,7 @@
@cil_local_variable
- 16916582
+ 16916551
@cil_catch_handler
@@ -1958,15 +1958,15 @@
@cil_finally_handler
- 1221334
+ 1221332
@cil_fault_handler
- 224390
+ 224389
@cil_attribute
- 4315762
+ 4315754
@@ -2677,7 +2677,7 @@
compilation_referencing_files
- 523639
+ 523638
id
@@ -2921,57 +2921,57 @@
5
6
- 1143
+ 774
6
7
- 497
+ 866
7
16
- 304
+ 322
16
20
- 451
+ 433
20
- 24
- 424
+ 25
+ 442
- 24
- 30
- 451
+ 25
+ 29
+ 433
- 30
+ 29
46
- 460
+ 424
46
- 55
- 387
-
-
- 55
- 58
- 507
-
-
- 58
- 63
+ 56
424
+
+ 56
+ 59
+ 451
+
+
+ 59
+ 63
+ 405
+
63
- 65
- 64
+ 66
+ 138
@@ -3048,62 +3048,67 @@
2
5
- 460
+ 451
5
6
- 294
+ 350
6
7
- 755
+ 691
7
10
- 488
+ 497
10
15
- 479
+ 516
15
20
- 516
+ 507
20
- 26
- 433
+ 25
+ 451
- 26
- 31
+ 25
+ 35
460
- 31
- 57
- 553
+ 35
+ 58
+ 387
- 57
+ 58
59
- 414
+ 276
59
- 61
+ 60
+ 350
+
+
+ 60
+ 63
460
- 61
- 68
- 175
+ 63
+ 67
+ 92
@@ -3129,7 +3134,7 @@
seconds
- 7817
+ 8333
@@ -3172,15 +3177,10 @@
12
-
- 6
- 7
- 9
-
7
8
- 1613
+ 1622
@@ -3226,8 +3226,8 @@
12
- 848
- 849
+ 904
+ 905
9
@@ -3273,24 +3273,24 @@
12
-
- 116
- 117
- 9
-
-
- 118
- 119
- 9
-
125
126
9
- 135
- 136
+ 130
+ 131
+ 9
+
+
+ 140
+ 141
+ 9
+
+
+ 144
+ 145
9
@@ -3312,22 +3312,22 @@
1
2
- 6102
+ 6664
2
3
- 700
+ 912
3
- 4
- 488
+ 6
+ 728
- 4
+ 6
8
- 525
+ 27
@@ -3343,7 +3343,7 @@
1
2
- 7817
+ 8333
@@ -3359,17 +3359,17 @@
1
2
- 6416
+ 6996
2
3
- 1198
+ 1179
3
- 4
- 202
+ 5
+ 156
@@ -5493,7 +5493,7 @@
cpu_seconds
- 1364
+ 1438
elapsed_seconds
@@ -5543,17 +5543,17 @@
1
2
- 1143
+ 1272
2
3
- 184
+ 147
3
4
- 36
+ 18
@@ -5569,17 +5569,17 @@
1
2
- 1143
+ 1272
2
3
- 184
+ 147
3
4
- 36
+ 18
@@ -6765,11 +6765,11 @@
locations_default
- 43578550
+ 43578472
id
- 43578550
+ 43578472
file
@@ -6777,7 +6777,7 @@
beginLine
- 2347256
+ 2347252
beginColumn
@@ -6785,7 +6785,7 @@
endLine
- 2511837
+ 2511832
endColumn
@@ -6803,7 +6803,7 @@
1
2
- 43578550
+ 43578472
@@ -6819,7 +6819,7 @@
1
2
- 43578550
+ 43578472
@@ -6835,7 +6835,7 @@
1
2
- 43578550
+ 43578472
@@ -6851,7 +6851,7 @@
1
2
- 43578550
+ 43578472
@@ -6867,7 +6867,7 @@
1
2
- 43578550
+ 43578472
@@ -7283,7 +7283,7 @@
2
3
- 443707
+ 443706
3
@@ -7298,12 +7298,12 @@
5
6
- 177016
+ 177015
6
7
- 184061
+ 184060
7
@@ -7328,12 +7328,12 @@
24
92
- 176252
+ 176251
92
759
- 128380
+ 128379
@@ -7349,22 +7349,22 @@
1
2
- 1044823
+ 1044821
2
3
- 387177
+ 387176
3
4
- 354923
+ 354922
4
6
- 187923
+ 187922
6
@@ -7395,7 +7395,7 @@
1
2
- 333364
+ 333363
2
@@ -7425,22 +7425,22 @@
7
9
- 173833
+ 173832
9
13
- 185037
+ 185036
13
24
- 183000
+ 182999
24
98
- 176252
+ 176251
98
@@ -7461,12 +7461,12 @@
1
2
- 1025258
+ 1025256
2
3
- 731193
+ 731192
3
@@ -7476,7 +7476,7 @@
4
6
- 188984
+ 188983
6
@@ -7502,7 +7502,7 @@
2
3
- 443919
+ 443918
3
@@ -7512,7 +7512,7 @@
4
5
- 278574
+ 278573
5
@@ -7527,17 +7527,17 @@
7
8
- 134067
+ 134066
8
10
- 178289
+ 178288
10
14
- 184740
+ 184739
14
@@ -7903,7 +7903,7 @@
3
4
- 280187
+ 280186
4
@@ -7959,7 +7959,7 @@
1
2
- 1096387
+ 1096385
2
@@ -7969,12 +7969,12 @@
3
4
- 490560
+ 490559
4
6
- 207700
+ 207699
6
@@ -7984,7 +7984,7 @@
12
61
- 189748
+ 189747
61
@@ -8005,12 +8005,12 @@
1
2
- 1365582
+ 1365580
2
3
- 545987
+ 545986
3
@@ -8041,17 +8041,17 @@
1
2
- 483133
+ 483132
2
3
- 397193
+ 397192
3
4
- 212156
+ 212155
4
@@ -8071,22 +8071,22 @@
7
9
- 200952
+ 200951
9
13
- 204814
+ 204813
13
24
- 191106
+ 191105
24
126
- 188517
+ 188516
128
@@ -8107,7 +8107,7 @@
1
2
- 440948
+ 440947
2
@@ -8127,7 +8127,7 @@
5
6
- 219583
+ 219582
6
@@ -8244,7 +8244,7 @@
1
2
- 14769
+ 14768
2
@@ -8264,7 +8264,7 @@
6
11
- 4923
+ 4922
11
@@ -8555,11 +8555,11 @@
numlines
- 1043663828
+ 1043661954
element_id
- 1043663828
+ 1043661954
num_lines
@@ -8567,7 +8567,7 @@
num_code
- 243293
+ 243292
num_comment
@@ -8585,7 +8585,7 @@
1
2
- 1043663828
+ 1043661954
@@ -8601,7 +8601,7 @@
1
2
- 1043663828
+ 1043661954
@@ -8617,7 +8617,7 @@
1
2
- 1043663828
+ 1043661954
@@ -9492,15 +9492,15 @@
folders
- 484046
+ 484045
id
- 484046
+ 484045
name
- 484046
+ 484045
@@ -9514,7 +9514,7 @@
1
2
- 484046
+ 484045
@@ -9530,7 +9530,7 @@
1
2
- 484046
+ 484045
@@ -9540,15 +9540,15 @@
containerparent
- 992135
+ 992133
parent
- 484046
+ 484045
child
- 992135
+ 992133
@@ -9562,7 +9562,7 @@
1
2
- 379754
+ 379753
2
@@ -9593,7 +9593,7 @@
1
2
- 992135
+ 992133
@@ -9651,11 +9651,11 @@
namespaces
- 367576
+ 367575
id
- 367576
+ 367575
name
@@ -9673,7 +9673,7 @@
1
2
- 367576
+ 367575
@@ -9870,15 +9870,15 @@
parent_namespace
- 7241099
+ 7241086
child_id
- 7241099
+ 7241086
namespace_id
- 231289
+ 231288
@@ -9892,7 +9892,7 @@
1
2
- 7241099
+ 7241086
@@ -9933,7 +9933,7 @@
6
8
- 17703
+ 17702
8
@@ -9953,7 +9953,7 @@
44
84811
- 13082
+ 13081
@@ -11615,6 +11615,300 @@
+
+ directive_line_offset
+ 0
+
+
+ id
+ 0
+
+
+ offset
+ 0
+
+
+
+
+ id
+ offset
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ offset
+ id
+
+
+ 12
+
+
+
+
+
+
+
+ directive_line_span
+ 0
+
+
+ id
+ 0
+
+
+ startLine
+ 0
+
+
+ startColumn
+ 0
+
+
+ endLine
+ 0
+
+
+ endColumn
+ 0
+
+
+
+
+ id
+ startLine
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ id
+ startColumn
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ id
+ endLine
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ id
+ endColumn
+
+
+ 12
+
+
+ 1
+ 2
+ 14
+
+
+
+
+
+
+ startLine
+ id
+
+
+ 12
+
+
+
+
+
+ startLine
+ startColumn
+
+
+ 12
+
+
+
+
+
+ startLine
+ endLine
+
+
+ 12
+
+
+
+
+
+ startLine
+ endColumn
+
+
+ 12
+
+
+
+
+
+ startColumn
+ id
+
+
+ 12
+
+
+
+
+
+ startColumn
+ startLine
+
+
+ 12
+
+
+
+
+
+ startColumn
+ endLine
+
+
+ 12
+
+
+
+
+
+ startColumn
+ endColumn
+
+
+ 12
+
+
+
+
+
+ endLine
+ id
+
+
+ 12
+
+
+
+
+
+ endLine
+ startLine
+
+
+ 12
+
+
+
+
+
+ endLine
+ startColumn
+
+
+ 12
+
+
+
+
+
+ endLine
+ endColumn
+
+
+ 12
+
+
+
+
+
+ endColumn
+ id
+
+
+ 12
+
+
+
+
+
+ endColumn
+ startLine
+
+
+ 12
+
+
+
+
+
+ endColumn
+ startColumn
+
+
+ 12
+
+
+
+
+
+ endColumn
+ endLine
+
+
+ 12
+
+
+
+
+
+
directive_nullables
3382
@@ -12590,11 +12884,11 @@
types
- 8463411
+ 8463395
id
- 8463411
+ 8463395
kind
@@ -12602,7 +12896,7 @@
name
- 2569129
+ 2569124
@@ -12616,7 +12910,7 @@
1
2
- 8463411
+ 8463395
@@ -12632,7 +12926,7 @@
1
2
- 8463411
+ 8463395
@@ -12735,7 +13029,7 @@
1
2
- 2307988
+ 2307983
2
@@ -12761,7 +13055,7 @@
1
2
- 2548128
+ 2548124
2
@@ -12776,15 +13070,15 @@
typerefs
- 3537567
+ 3537560
id
- 3537567
+ 3537560
name
- 2476079
+ 2476075
@@ -12798,7 +13092,7 @@
1
2
- 3537567
+ 3537560
@@ -12814,7 +13108,7 @@
1
2
- 2298312
+ 2298307
2
@@ -12829,15 +13123,15 @@
typeref_type
- 3508083
+ 3508077
id
- 3508083
+ 3508077
typeId
- 3508083
+ 3508077
@@ -12851,7 +13145,7 @@
1
2
- 3508083
+ 3508077
@@ -12867,7 +13161,7 @@
1
2
- 3508083
+ 3508077
@@ -13332,15 +13626,15 @@
delegate_return_type
- 2249826
+ 2249822
delegate_id
- 2249826
+ 2249822
return_type_id
- 801531
+ 801529
@@ -13354,7 +13648,7 @@
1
2
- 2249826
+ 2249822
@@ -13370,7 +13664,7 @@
1
2
- 730409
+ 730408
2
@@ -13458,11 +13752,11 @@
extend
- 3548527
+ 3548520
sub
- 3547415
+ 3547409
super
@@ -13480,7 +13774,7 @@
1
2
- 3546304
+ 3546298
2
@@ -13552,15 +13846,15 @@
implement
- 9498668
+ 9498651
sub
- 3317494
+ 3317488
super
- 2026887
+ 2026883
@@ -13574,27 +13868,27 @@
1
2
- 1125942
+ 1125940
2
3
- 905522
+ 905520
3
4
- 620560
+ 620559
4
6
- 270036
+ 270035
6
9
- 249057
+ 249056
9
@@ -13615,12 +13909,12 @@
1
2
- 973058
+ 973056
2
3
- 598995
+ 598994
3
@@ -13635,7 +13929,7 @@
6
90747
- 122923
+ 122922
@@ -13645,11 +13939,11 @@
type_location
- 4526766
+ 4526758
id
- 4460402
+ 4460394
loc
@@ -13667,7 +13961,7 @@
1
2
- 4438121
+ 4438113
2
@@ -13796,7 +14090,7 @@
tuple_element
- 149836
+ 149835
tuple
@@ -13808,7 +14102,7 @@
field
- 149836
+ 149835
@@ -14186,7 +14480,7 @@
1
2
- 149836
+ 149835
@@ -14202,7 +14496,7 @@
1
2
- 149836
+ 149835
@@ -14212,11 +14506,11 @@
attributes
- 10551347
+ 10551328
id
- 10551347
+ 10551328
type_id
@@ -14224,7 +14518,7 @@
target
- 9250913
+ 9250896
@@ -14238,7 +14532,7 @@
1
2
- 10551347
+ 10551328
@@ -14254,7 +14548,7 @@
1
2
- 10551347
+ 10551328
@@ -14422,12 +14716,12 @@
1
2
- 8608463
+ 8608447
2
3520
- 642450
+ 642449
@@ -14443,12 +14737,12 @@
1
2
- 8733902
+ 8733887
2
29
- 517010
+ 517009
@@ -14458,11 +14752,11 @@
attribute_location
- 10552714
+ 10552695
id
- 10551347
+ 10551328
loc
@@ -14480,7 +14774,7 @@
1
2
- 10550263
+ 10550244
2
@@ -14571,11 +14865,11 @@
type_mention
- 4147997
+ 4147990
id
- 4147997
+ 4147990
type_id
@@ -14583,7 +14877,7 @@
parent
- 1453787
+ 1453785
@@ -14597,7 +14891,7 @@
1
2
- 4147997
+ 4147990
@@ -14613,7 +14907,7 @@
1
2
- 4147997
+ 4147990
@@ -14670,7 +14964,7 @@
1
2
- 69690
+ 69689
2
@@ -14711,12 +15005,12 @@
1
2
- 1183982
+ 1183979
2
3
- 142436
+ 142435
3
@@ -14742,7 +15036,7 @@
1
2
- 1271409
+ 1271407
2
@@ -14762,15 +15056,15 @@
type_mention_location
- 4147997
+ 4147990
id
- 4147997
+ 4147990
loc
- 3077665
+ 3077659
@@ -14784,7 +15078,7 @@
1
2
- 4147997
+ 4147990
@@ -14800,12 +15094,12 @@
1
2
- 2705130
+ 2705125
2
3
- 359178
+ 359177
3
@@ -14820,11 +15114,11 @@
type_annotation
- 1491207
+ 1491205
id
- 1491207
+ 1491205
annotation
@@ -14842,7 +15136,7 @@
1
2
- 1491207
+ 1491205
@@ -15207,11 +15501,11 @@
type_nullability
- 32568461
+ 32568402
id
- 32566139
+ 32566081
nullability
@@ -15229,7 +15523,7 @@
1
2
- 32563905
+ 32563846
2
@@ -15300,11 +15594,11 @@
expr_flowstate
- 3848490
+ 3848496
id
- 3848490
+ 3848496
state
@@ -15322,7 +15616,7 @@
1
2
- 3848490
+ 3848496
@@ -15336,13 +15630,13 @@
12
- 210405
- 210406
+ 210406
+ 210407
1
- 2276574
- 2276575
+ 2276592
+ 2276593
1
@@ -15353,11 +15647,11 @@
type_parameters
- 830424
+ 830422
id
- 830424
+ 830422
index
@@ -15365,7 +15659,7 @@
generic_id
- 796402
+ 796400
variance
@@ -15383,7 +15677,7 @@
1
2
- 830424
+ 830422
@@ -15399,7 +15693,7 @@
1
2
- 830424
+ 830422
@@ -15415,7 +15709,7 @@
1
2
- 830424
+ 830422
@@ -15639,7 +15933,7 @@
1
2
- 789862
+ 789861
2
@@ -15660,7 +15954,7 @@
1
2
- 789862
+ 789861
2
@@ -15681,7 +15975,7 @@
1
2
- 796038
+ 796037
2
@@ -15774,11 +16068,11 @@
type_arguments
- 32946682
+ 32946623
id
- 851709
+ 851708
index
@@ -15786,7 +16080,7 @@
constructed_id
- 3572654
+ 3572648
@@ -15805,7 +16099,7 @@
2
3
- 720386
+ 720385
3
@@ -15831,7 +16125,7 @@
2
3
- 721262
+ 721261
3
@@ -16044,7 +16338,7 @@
2
3
- 2211295
+ 2211291
3
@@ -16054,17 +16348,17 @@
20
25
- 281239
+ 281238
25
29
- 321416
+ 321415
29
32
- 283718
+ 283717
32
@@ -16090,27 +16384,27 @@
2
3
- 2211338
+ 2211334
3
20
- 305986
+ 305985
20
25
- 281239
+ 281238
25
29
- 321416
+ 321415
29
32
- 283718
+ 283717
32
@@ -16125,11 +16419,11 @@
constructed_generic
- 3862925
+ 3862918
constructed
- 3862925
+ 3862918
generic
@@ -16147,7 +16441,7 @@
1
2
- 3862925
+ 3862918
@@ -16213,15 +16507,15 @@
type_parameter_constraints
- 1730282
+ 1730279
id
- 1730282
+ 1730279
param_id
- 831792
+ 831790
@@ -16235,7 +16529,7 @@
1
2
- 1730282
+ 1730279
@@ -16256,7 +16550,7 @@
2
3
- 777766
+ 777765
3
@@ -16384,7 +16678,7 @@
id
- 254828
+ 254827
base_id
@@ -16402,7 +16696,7 @@
1
2
- 250207
+ 250206
2
@@ -16463,11 +16757,11 @@
specific_type_parameter_nullability
- 48893
+ 48843
id
- 48656
+ 48606
base_id
@@ -16489,7 +16783,7 @@
1
2
- 48418
+ 48369
2
@@ -16510,7 +16804,7 @@
1
2
- 48656
+ 48606
@@ -16686,8 +16980,8 @@
1
- 35929
- 35930
+ 35892
+ 35893
1
@@ -16935,11 +17229,11 @@
has_modifiers
- 74006635
+ 74006502
id
- 48974345
+ 48974257
mod_id
@@ -16957,17 +17251,17 @@
1
2
- 25150157
+ 25150112
2
3
- 22619211
+ 22619170
3
5
- 1204976
+ 1204974
@@ -17058,11 +17352,11 @@
compiler_generated
- 786251
+ 786249
id
- 786251
+ 786249
@@ -17157,19 +17451,19 @@
nested_types
- 1588195
+ 1588192
id
- 1588195
+ 1588192
declaring_type_id
- 637373
+ 637372
unbound_id
- 1331870
+ 1331867
@@ -17183,7 +17477,7 @@
1
2
- 1588195
+ 1588192
@@ -17199,7 +17493,7 @@
1
2
- 1588195
+ 1588192
@@ -17215,7 +17509,7 @@
1
2
- 373000
+ 372999
2
@@ -17235,7 +17529,7 @@
6
22
- 47989
+ 47988
22
@@ -17256,7 +17550,7 @@
1
2
- 374540
+ 374539
2
@@ -17297,7 +17591,7 @@
1
2
- 1283295
+ 1283293
2
@@ -17318,7 +17612,7 @@
1
2
- 1291083
+ 1291081
2
@@ -17333,27 +17627,27 @@
properties
- 4879894
+ 4879885
id
- 4879894
+ 4879885
name
- 1131843
+ 1131841
declaring_type_id
- 1362395
+ 1362392
type_id
- 541612
+ 541611
unbound_id
- 4365920
+ 4365913
@@ -17367,7 +17661,7 @@
1
2
- 4879894
+ 4879885
@@ -17383,7 +17677,7 @@
1
2
- 4879894
+ 4879885
@@ -17399,7 +17693,7 @@
1
2
- 4879894
+ 4879885
@@ -17415,7 +17709,7 @@
1
2
- 4879894
+ 4879885
@@ -17431,7 +17725,7 @@
1
2
- 714282
+ 714280
2
@@ -17467,7 +17761,7 @@
1
2
- 714282
+ 714280
2
@@ -17503,7 +17797,7 @@
1
2
- 989546
+ 989545
2
@@ -17529,12 +17823,12 @@
1
2
- 720508
+ 720507
2
3
- 186641
+ 186640
3
@@ -17565,12 +17859,12 @@
1
2
- 484967
+ 484966
2
3
- 319782
+ 319781
3
@@ -17585,7 +17879,7 @@
5
7
- 114614
+ 114613
7
@@ -17611,12 +17905,12 @@
1
2
- 560096
+ 560095
2
3
- 245846
+ 245845
3
@@ -17657,7 +17951,7 @@
1
2
- 562005
+ 562004
2
@@ -17667,7 +17961,7 @@
3
4
- 167788
+ 167787
4
@@ -17698,12 +17992,12 @@
1
2
- 484967
+ 484966
2
3
- 319782
+ 319781
3
@@ -17718,7 +18012,7 @@
5
7
- 114614
+ 114613
7
@@ -17790,7 +18084,7 @@
2
3
- 60572
+ 60571
3
@@ -17816,7 +18110,7 @@
1
2
- 309846
+ 309845
2
@@ -17857,12 +18151,12 @@
1
2
- 297480
+ 297479
2
3
- 113334
+ 113333
3
@@ -17898,7 +18192,7 @@
1
2
- 4291398
+ 4291391
2
@@ -17919,7 +18213,7 @@
1
2
- 4365920
+ 4365913
@@ -17935,7 +18229,7 @@
1
2
- 4291398
+ 4291391
2
@@ -17956,7 +18250,7 @@
1
2
- 4349931
+ 4349923
2
@@ -17971,15 +18265,15 @@
property_location
- 4890676
+ 4890667
id
- 4879894
+ 4879885
loc
- 8048
+ 8027
@@ -17993,7 +18287,7 @@
1
2
- 4872127
+ 4872118
2
@@ -18014,67 +18308,72 @@
1
5
- 694
+ 650
5
- 11
- 737
-
-
- 11
- 22
+ 10
607
- 22
- 37
- 607
-
-
- 37
- 53
+ 10
+ 18
629
- 53
- 96
+ 18
+ 34
607
- 96
- 139
+ 34
+ 49
607
- 141
- 214
+ 49
+ 81
607
- 214
- 291
+ 82
+ 126
607
- 292
- 393
+ 127
+ 187
607
- 409
- 912
+ 188
+ 272
607
- 921
- 2270
+ 272
+ 359
607
- 2333
+ 369
+ 750
+ 607
+
+
+ 759
+ 1795
+ 607
+
+
+ 1886
+ 9614
+ 607
+
+
+ 9940
12699
- 520
+ 65
@@ -18333,7 +18632,7 @@
1
2
- 72463
+ 72462
2
@@ -18695,11 +18994,11 @@
accessors
- 5815073
+ 5815063
id
- 5815073
+ 5815063
kind
@@ -18707,15 +19006,15 @@
name
- 1544393
+ 1544390
declaring_member_id
- 4956672
+ 4956663
unbound_id
- 5171668
+ 5171659
@@ -18729,7 +19028,7 @@
1
2
- 5815073
+ 5815063
@@ -18745,7 +19044,7 @@
1
2
- 5815073
+ 5815063
@@ -18761,7 +19060,7 @@
1
2
- 5815073
+ 5815063
@@ -18777,7 +19076,7 @@
1
2
- 5815073
+ 5815063
@@ -18877,7 +19176,7 @@
1
2
- 1004407
+ 1004406
2
@@ -18913,7 +19212,7 @@
1
2
- 1544393
+ 1544390
@@ -18929,7 +19228,7 @@
1
2
- 1004407
+ 1004406
2
@@ -18965,12 +19264,12 @@
1
2
- 1015298
+ 1015296
2
3
- 249556
+ 249555
3
@@ -19001,12 +19300,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19022,12 +19321,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19043,12 +19342,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19064,12 +19363,12 @@
1
2
- 4098271
+ 4098263
2
3
- 858401
+ 858399
@@ -19085,12 +19384,12 @@
1
2
- 5083717
+ 5083708
2
1206
- 87951
+ 87950
@@ -19106,7 +19405,7 @@
1
2
- 5171668
+ 5171659
@@ -19122,7 +19421,7 @@
1
2
- 5171668
+ 5171659
@@ -19138,12 +19437,12 @@
1
2
- 5083717
+ 5083708
2
1206
- 87951
+ 87950
@@ -19164,15 +19463,15 @@
accessor_location
- 5828090
+ 5828080
id
- 5815073
+ 5815063
loc
- 8048
+ 8027
@@ -19186,7 +19485,7 @@
1
2
- 5805202
+ 5805192
2
@@ -19207,67 +19506,67 @@
1
6
- 694
+ 650
6
- 13
- 715
-
-
- 13
- 26
- 629
-
-
- 26
- 43
+ 12
607
- 44
- 68
+ 12
+ 22
607
- 68
- 106
+ 22
+ 38
+ 650
+
+
+ 38
+ 66
+ 672
+
+
+ 67
+ 105
607
- 116
- 167
+ 105
+ 161
607
- 168
- 273
- 629
-
-
- 275
- 373
+ 164
+ 269
607
- 373
- 492
+ 269
+ 361
607
- 517
- 1154
+ 364
+ 464
607
- 1167
- 2661
+ 477
+ 1105
607
- 2853
+ 1105
+ 2387
+ 607
+
+
+ 2455
13984
- 520
+ 585
@@ -19802,7 +20101,7 @@
1
2
- 50050
+ 50049
2
@@ -19839,7 +20138,7 @@
1
2
- 50050
+ 50049
2
@@ -19860,7 +20159,7 @@
1
2
- 51547
+ 51546
2
@@ -20318,7 +20617,7 @@
1
2
- 100100
+ 100099
2
@@ -20371,7 +20670,7 @@
1
2
- 100100
+ 100099
2
@@ -20479,11 +20778,11 @@
operators
- 807643
+ 807641
id
- 807643
+ 807641
name
@@ -20495,7 +20794,7 @@
declaring_type_id
- 94480
+ 94479
type_id
@@ -20517,7 +20816,7 @@
1
2
- 807643
+ 807641
@@ -20533,7 +20832,7 @@
1
2
- 807643
+ 807641
@@ -20549,7 +20848,7 @@
1
2
- 807643
+ 807641
@@ -20565,7 +20864,7 @@
1
2
- 807643
+ 807641
@@ -20581,7 +20880,7 @@
1
2
- 807643
+ 807641
@@ -21148,7 +21447,7 @@
1
2
- 92172
+ 92171
2
@@ -21169,7 +21468,7 @@
1
2
- 92172
+ 92171
2
@@ -21606,11 +21905,11 @@
operator_location
- 1510292
+ 1510289
id
- 751074
+ 751073
loc
@@ -21633,7 +21932,7 @@
2
3
- 740026
+ 740024
3
@@ -21672,9 +21971,9 @@
1880
- 63
+ 62
73
- 1859
+ 1880
75
@@ -21688,8 +21987,8 @@
96
- 20093
- 897
+ 18513
+ 876
@@ -21699,15 +21998,15 @@
constant_value
- 2847105
+ 2847100
id
- 2845825
+ 2845820
value
- 965573
+ 965572
@@ -21721,7 +22020,7 @@
1
2
- 2844979
+ 2844974
2
@@ -21742,7 +22041,7 @@
1
2
- 780581
+ 780580
2
@@ -21767,27 +22066,27 @@
methods
- 15027131
+ 15027104
id
- 15027131
+ 15027104
name
- 4232388
+ 4232381
declaring_type_id
- 3140811
+ 3140805
type_id
- 999548
+ 999546
unbound_id
- 12416413
+ 12416391
@@ -21801,7 +22100,7 @@
1
2
- 15027131
+ 15027104
@@ -21817,7 +22116,7 @@
1
2
- 15027131
+ 15027104
@@ -21833,7 +22132,7 @@
1
2
- 15027131
+ 15027104
@@ -21849,7 +22148,7 @@
1
2
- 15027131
+ 15027104
@@ -21865,22 +22164,22 @@
1
2
- 3032748
+ 3032743
2
3
- 495706
+ 495705
3
5
- 336878
+ 336877
5
26
- 319392
+ 319391
26
@@ -21901,17 +22200,17 @@
1
2
- 3164935
+ 3164930
2
3
- 431663
+ 431662
3
6
- 378510
+ 378509
6
@@ -21932,12 +22231,12 @@
1
2
- 3856394
+ 3856388
2
7
- 323514
+ 323513
7
@@ -21958,22 +22257,22 @@
1
2
- 3079284
+ 3079278
2
3
- 510241
+ 510240
3
5
- 336444
+ 336443
5
8458
- 306418
+ 306417
@@ -21989,12 +22288,12 @@
1
2
- 1095786
+ 1095784
2
3
- 701525
+ 701524
3
@@ -22014,12 +22313,12 @@
6
9
- 274635
+ 274634
9
18
- 241659
+ 241658
18
@@ -22040,17 +22339,17 @@
1
2
- 1137440
+ 1137438
2
3
- 725802
+ 725800
3
4
- 320845
+ 320844
4
@@ -22065,12 +22364,12 @@
6
10
- 265567
+ 265566
10
70
- 235693
+ 235692
70
@@ -22091,12 +22390,12 @@
1
2
- 1500895
+ 1500892
2
3
- 768953
+ 768951
3
@@ -22106,7 +22405,7 @@
4
5
- 257670
+ 257669
5
@@ -22116,7 +22415,7 @@
10
848
- 62351
+ 62350
@@ -22132,12 +22431,12 @@
1
2
- 1095808
+ 1095806
2
3
- 701503
+ 701502
3
@@ -22157,12 +22456,12 @@
6
9
- 274635
+ 274634
9
18
- 241659
+ 241658
18
@@ -22183,7 +22482,7 @@
1
2
- 566843
+ 566842
2
@@ -22224,7 +22523,7 @@
1
2
- 697078
+ 697076
2
@@ -22260,7 +22559,7 @@
1
2
- 648915
+ 648914
2
@@ -22296,7 +22595,7 @@
1
2
- 568861
+ 568860
2
@@ -22337,12 +22636,12 @@
1
2
- 12025102
+ 12025081
2
3017
- 391310
+ 391309
@@ -22358,7 +22657,7 @@
1
2
- 12416413
+ 12416391
@@ -22374,7 +22673,7 @@
1
2
- 12025189
+ 12025167
2
@@ -22395,12 +22694,12 @@
1
2
- 12291928
+ 12291906
2
1636
- 124485
+ 124484
@@ -22410,15 +22709,15 @@
method_location
- 15099549
+ 15099522
id
- 15027131
+ 15027104
loc
- 8526
+ 8504
@@ -22432,7 +22731,7 @@
1
2
- 14977211
+ 14977184
2
@@ -22458,7 +22757,7 @@
6
22
- 672
+ 650
23
@@ -22523,23 +22822,23 @@
constructors
- 4401500
+ 4401492
id
- 4401500
+ 4401492
name
- 2051728
+ 2051724
declaring_type_id
- 3294779
+ 3294773
unbound_id
- 4086621
+ 4086613
@@ -22553,7 +22852,7 @@
1
2
- 4401500
+ 4401492
@@ -22569,7 +22868,7 @@
1
2
- 4401500
+ 4401492
@@ -22585,7 +22884,7 @@
1
2
- 4401500
+ 4401492
@@ -22601,17 +22900,17 @@
1
2
- 1486728
+ 1486725
2
3
- 373000
+ 372999
3
7
- 156767
+ 156766
7
@@ -22632,7 +22931,7 @@
1
2
- 1877995
+ 1877992
2
@@ -22658,12 +22957,12 @@
1
2
- 1508922
+ 1508919
2
3
- 374193
+ 374192
3
@@ -22689,17 +22988,17 @@
1
2
- 2455035
+ 2455031
2
3
- 711700
+ 711699
3
55
- 128043
+ 128042
@@ -22715,7 +23014,7 @@
1
2
- 3294779
+ 3294773
@@ -22731,17 +23030,17 @@
1
2
- 2455035
+ 2455031
2
3
- 711700
+ 711699
3
55
- 128043
+ 128042
@@ -22757,7 +23056,7 @@
1
2
- 4045053
+ 4045046
2
@@ -22778,7 +23077,7 @@
1
2
- 4086621
+ 4086613
@@ -22794,7 +23093,7 @@
1
2
- 4045053
+ 4045046
2
@@ -22809,11 +23108,11 @@
constructor_location
- 4437817
+ 4437809
id
- 4401500
+ 4401492
loc
@@ -22831,7 +23130,7 @@
1
2
- 4386878
+ 4386870
2
@@ -23226,15 +23525,15 @@
overrides
- 3549976
+ 3549970
id
- 3549976
+ 3549970
base_id
- 1153191
+ 1153189
@@ -23248,7 +23547,7 @@
1
2
- 3549976
+ 3549970
@@ -23264,12 +23563,12 @@
1
2
- 787090
+ 787088
2
3
- 181586
+ 181585
3
@@ -23294,11 +23593,11 @@
explicitly_implements
- 1340287
+ 1340285
id
- 1339875
+ 1339873
interface_id
@@ -23316,7 +23615,7 @@
1
2
- 1339463
+ 1339461
2
@@ -23668,15 +23967,15 @@
local_function_stmts
- 3317
+ 3316
fn
- 3317
+ 3316
stmt
- 3317
+ 3316
@@ -23690,7 +23989,7 @@
1
2
- 3317
+ 3316
@@ -23706,7 +24005,7 @@
1
2
- 3317
+ 3316
@@ -23716,11 +24015,11 @@
fields
- 11002601
+ 11002581
id
- 11002601
+ 11002581
kind
@@ -23728,19 +24027,19 @@
name
- 4569136
+ 4569128
declaring_type_id
- 2488012
+ 2488007
type_id
- 2180552
+ 2180548
unbound_id
- 10641880
+ 10641861
@@ -23754,7 +24053,7 @@
1
2
- 11002601
+ 11002581
@@ -23770,7 +24069,7 @@
1
2
- 11002601
+ 11002581
@@ -23786,7 +24085,7 @@
1
2
- 11002601
+ 11002581
@@ -23802,7 +24101,7 @@
1
2
- 11002601
+ 11002581
@@ -23818,7 +24117,7 @@
1
2
- 11002601
+ 11002581
@@ -23939,17 +24238,17 @@
1
2
- 3598616
+ 3598609
2
3
- 510458
+ 510457
3
8
- 343495
+ 343494
8
@@ -23970,7 +24269,7 @@
1
2
- 4464307
+ 4464299
2
@@ -23991,17 +24290,17 @@
1
2
- 3598616
+ 3598609
2
3
- 510480
+ 510479
3
8
- 343473
+ 343472
8
@@ -24022,7 +24321,7 @@
1
2
- 4006545
+ 4006538
2
@@ -24048,17 +24347,17 @@
1
2
- 3622827
+ 3622821
2
3
- 511717
+ 511716
3
10
- 352368
+ 352367
10
@@ -24079,12 +24378,12 @@
1
2
- 686274
+ 686272
2
3
- 636267
+ 636266
3
@@ -24094,7 +24393,7 @@
4
5
- 217773
+ 217772
5
@@ -24104,17 +24403,17 @@
6
8
- 181803
+ 181802
8
15
- 193670
+ 193669
15
6823
- 72873
+ 72872
@@ -24130,7 +24429,7 @@
1
2
- 2338469
+ 2338465
2
@@ -24151,22 +24450,22 @@
1
2
- 686274
+ 686272
2
3
- 636289
+ 636287
3
4
- 353236
+ 353235
4
5
- 217773
+ 217772
5
@@ -24176,17 +24475,17 @@
6
8
- 181803
+ 181802
8
15
- 193670
+ 193669
15
6823
- 72873
+ 72872
@@ -24202,12 +24501,12 @@
1
2
- 948001
+ 947999
2
3
- 690981
+ 690980
3
@@ -24222,7 +24521,7 @@
5
8
- 228447
+ 228446
8
@@ -24243,12 +24542,12 @@
1
2
- 686274
+ 686272
2
3
- 636267
+ 636266
3
@@ -24258,7 +24557,7 @@
4
5
- 217773
+ 217772
5
@@ -24268,17 +24567,17 @@
6
8
- 181803
+ 181802
8
15
- 193670
+ 193669
15
6823
- 72873
+ 72872
@@ -24294,7 +24593,7 @@
1
2
- 1482497
+ 1482495
2
@@ -24330,7 +24629,7 @@
1
2
- 2117246
+ 2117242
2
@@ -24351,12 +24650,12 @@
1
2
- 1587652
+ 1587650
2
3
- 258950
+ 258949
3
@@ -24382,7 +24681,7 @@
1
2
- 1645773
+ 1645770
2
@@ -24413,17 +24712,17 @@
1
2
- 1486142
+ 1486139
2
3
- 270687
+ 270686
3
5
- 199354
+ 199353
5
@@ -24449,7 +24748,7 @@
1
2
- 10580071
+ 10580052
2
@@ -24470,7 +24769,7 @@
1
2
- 10641880
+ 10641861
@@ -24486,7 +24785,7 @@
1
2
- 10641880
+ 10641861
@@ -24502,7 +24801,7 @@
1
2
- 10580071
+ 10580052
2
@@ -24523,7 +24822,7 @@
1
2
- 10622637
+ 10622618
2
@@ -24538,15 +24837,15 @@
field_location
- 10994335
+ 10994315
id
- 10929771
+ 10929752
loc
- 8265
+ 8244
@@ -24560,7 +24859,7 @@
1
2
- 10890872
+ 10890853
2
@@ -24581,7 +24880,7 @@
1
10
- 650
+ 629
10
@@ -24656,11 +24955,11 @@
localvars
- 354447
+ 354446
id
- 354447
+ 354446
kind
@@ -24680,7 +24979,7 @@
parent_id
- 354447
+ 354446
@@ -24694,7 +24993,7 @@
1
2
- 354447
+ 354446
@@ -24710,7 +25009,7 @@
1
2
- 354447
+ 354446
@@ -24726,7 +25025,7 @@
1
2
- 354447
+ 354446
@@ -24742,7 +25041,7 @@
1
2
- 354447
+ 354446
@@ -24758,7 +25057,7 @@
1
2
- 354447
+ 354446
@@ -25299,7 +25598,7 @@
1
2
- 354447
+ 354446
@@ -25315,7 +25614,7 @@
1
2
- 354447
+ 354446
@@ -25331,7 +25630,7 @@
1
2
- 354447
+ 354446
@@ -25347,7 +25646,7 @@
1
2
- 354447
+ 354446
@@ -25363,7 +25662,7 @@
1
2
- 354447
+ 354446
@@ -25373,15 +25672,15 @@
localvar_location
- 354447
+ 354446
id
- 354447
+ 354446
loc
- 354447
+ 354446
@@ -25395,7 +25694,7 @@
1
2
- 354447
+ 354446
@@ -25411,7 +25710,7 @@
1
2
- 354447
+ 354446
@@ -25421,19 +25720,19 @@
params
- 27466281
+ 27466231
id
- 27466281
+ 27466231
name
- 1613730
+ 1613727
type_id
- 2077566
+ 2077562
index
@@ -25445,11 +25744,11 @@
parent_id
- 15223817
+ 15223790
unbound_id
- 22123570
+ 22123530
@@ -25463,7 +25762,7 @@
1
2
- 27466281
+ 27466231
@@ -25479,7 +25778,7 @@
1
2
- 27466281
+ 27466231
@@ -25495,7 +25794,7 @@
1
2
- 27466281
+ 27466231
@@ -25511,7 +25810,7 @@
1
2
- 27466281
+ 27466231
@@ -25527,7 +25826,7 @@
1
2
- 27466281
+ 27466231
@@ -25543,7 +25842,7 @@
1
2
- 27466281
+ 27466231
@@ -25559,7 +25858,7 @@
1
2
- 721137
+ 721136
2
@@ -25605,12 +25904,12 @@
1
2
- 1310934
+ 1310932
2
3
- 157331
+ 157330
3
@@ -25636,7 +25935,7 @@
1
2
- 1115941
+ 1115939
2
@@ -25651,7 +25950,7 @@
4
21
- 115113
+ 115112
@@ -25667,7 +25966,7 @@
1
2
- 1492260
+ 1492257
2
@@ -25693,7 +25992,7 @@
1
2
- 721137
+ 721136
2
@@ -25739,7 +26038,7 @@
1
2
- 736237
+ 736236
2
@@ -25749,12 +26048,12 @@
3
4
- 146896
+ 146895
4
6
- 147742
+ 147741
6
@@ -25785,22 +26084,22 @@
1
2
- 1018379
+ 1018377
2
3
- 301667
+ 301666
3
4
- 173277
+ 173276
4
5
- 129106
+ 129105
5
@@ -25810,7 +26109,7 @@
8
19
- 161171
+ 161170
19
@@ -25831,7 +26130,7 @@
1
2
- 1396976
+ 1396974
2
@@ -25841,7 +26140,7 @@
3
4
- 149456
+ 149455
4
@@ -25867,7 +26166,7 @@
1
2
- 1515539
+ 1515536
2
@@ -25898,7 +26197,7 @@
1
2
- 1956596
+ 1956592
2
@@ -25919,17 +26218,17 @@
1
2
- 1049359
+ 1049357
2
3
- 281903
+ 281902
3
4
- 174123
+ 174122
4
@@ -25939,17 +26238,17 @@
5
9
- 182085
+ 182084
9
24
- 157483
+ 157482
24
74138
- 105220
+ 105219
@@ -25965,12 +26264,12 @@
1
2
- 1024605
+ 1024603
2
3
- 302795
+ 302794
3
@@ -26603,22 +26902,22 @@
1
2
- 8608267
+ 8608252
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153842
+ 1153840
8
@@ -26639,22 +26938,22 @@
1
2
- 8608246
+ 8608230
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153863
+ 1153861
8
@@ -26675,22 +26974,22 @@
1
2
- 9102195
+ 9102178
2
3
- 3783500
+ 3783493
3
4
- 1384350
+ 1384347
4
43
- 953771
+ 953770
@@ -26706,22 +27005,22 @@
1
2
- 8608267
+ 8608252
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153842
+ 1153840
8
@@ -26742,12 +27041,12 @@
1
2
- 14543531
+ 14543505
2
5
- 680286
+ 680285
@@ -26763,22 +27062,22 @@
1
2
- 8608267
+ 8608252
2
3
- 3845113
+ 3845106
3
4
- 1492846
+ 1492843
4
8
- 1153842
+ 1153840
8
@@ -26799,12 +27098,12 @@
1
2
- 21382863
+ 21382825
2
17584
- 740706
+ 740705
@@ -26820,7 +27119,7 @@
1
2
- 22123505
+ 22123465
2
@@ -26841,12 +27140,12 @@
1
2
- 21899331
+ 21899292
2
9835
- 224238
+ 224237
@@ -26862,7 +27161,7 @@
1
2
- 22123570
+ 22123530
@@ -26878,7 +27177,7 @@
1
2
- 22123570
+ 22123530
@@ -26894,12 +27193,12 @@
1
2
- 21382863
+ 21382825
2
17584
- 740706
+ 740705
@@ -26909,11 +27208,11 @@
param_location
- 27592957
+ 27592908
id
- 27465934
+ 27465884
loc
@@ -26931,7 +27230,7 @@
1
2
- 27379957
+ 27379908
2
@@ -27376,11 +27675,11 @@
stmt_parent_top_level
- 249938
+ 249937
stmt
- 249938
+ 249937
index
@@ -27388,7 +27687,7 @@
parent
- 171227
+ 171226
@@ -27402,7 +27701,7 @@
1
2
- 249938
+ 249937
@@ -27418,7 +27717,7 @@
1
2
- 249938
+ 249937
@@ -27466,7 +27765,7 @@
1
2
- 106304
+ 106303
2
@@ -27497,7 +27796,7 @@
1
2
- 171227
+ 171226
@@ -27965,11 +28264,11 @@
expressions
- 6684214
+ 6684202
id
- 6684214
+ 6684202
kind
@@ -27991,7 +28290,7 @@
1
2
- 6684214
+ 6684202
@@ -28007,7 +28306,7 @@
1
2
- 6684214
+ 6684202
@@ -28256,11 +28555,11 @@
expr_parent
- 6472330
+ 6472322
expr
- 6472330
+ 6472322
index
@@ -28268,7 +28567,7 @@
parent
- 4333969
+ 4333965
@@ -28282,7 +28581,7 @@
1
2
- 6472330
+ 6472322
@@ -28298,7 +28597,7 @@
1
2
- 6472330
+ 6472322
@@ -28343,7 +28642,7 @@
66
- 3205676
+ 3205672
489
@@ -28389,7 +28688,7 @@
66
- 3205676
+ 3205672
489
@@ -28411,7 +28710,7 @@
2
3
- 1302939
+ 1302935
3
@@ -28437,7 +28736,7 @@
2
3
- 1302939
+ 1302935
3
@@ -28452,11 +28751,11 @@
expr_parent_top_level
- 4527928
+ 4527920
expr
- 4527928
+ 4527920
index
@@ -28464,7 +28763,7 @@
parent
- 4069954
+ 4069947
@@ -28478,7 +28777,7 @@
1
2
- 4527928
+ 4527920
@@ -28494,7 +28793,7 @@
1
2
- 4527928
+ 4527920
@@ -28562,7 +28861,7 @@
1
2
- 3716443
+ 3716436
2
@@ -28588,7 +28887,7 @@
1
2
- 3726770
+ 3726764
2
@@ -28603,11 +28902,11 @@
implicitly_typed_array_creation
- 19612
+ 19611
id
- 19612
+ 19611
@@ -28695,26 +28994,26 @@
expr_compiler_generated
- 6677184
+ 6677172
id
- 6677184
+ 6677172
expr_value
- 5479091
+ 5479081
id
- 5479091
+ 5479081
value
- 203506
+ 203505
@@ -28728,7 +29027,7 @@
1
2
- 5479091
+ 5479081
@@ -28779,15 +29078,15 @@
expr_call
- 1125746
+ 1125744
caller_id
- 1125746
+ 1125744
target_id
- 895583
+ 895582
@@ -28801,7 +29100,7 @@
1
2
- 1125746
+ 1125744
@@ -28817,7 +29116,7 @@
1
2
- 893788
+ 893787
2
@@ -28910,15 +29209,15 @@
expr_location
- 6684214
+ 6684202
id
- 6684214
+ 6684202
loc
- 5325109
+ 5325100
@@ -28932,7 +29231,7 @@
1
2
- 6684214
+ 6684202
@@ -28948,12 +29247,12 @@
1
2
- 4609547
+ 4609539
2
3
- 691472
+ 691471
3
@@ -29057,11 +29356,11 @@
expr_argument
- 1381112
+ 1381083
id
- 1381112
+ 1381083
mode
@@ -29079,7 +29378,7 @@
1
2
- 1381112
+ 1381083
@@ -29120,11 +29419,11 @@
expr_argument_name
- 537620
+ 537619
id
- 537620
+ 537619
name
@@ -29142,7 +29441,7 @@
1
2
- 537620
+ 537619
@@ -29223,11 +29522,11 @@
xmlEncoding
- 476428
+ 476427
id
- 476428
+ 476427
encoding
@@ -29245,7 +29544,7 @@
1
2
- 476428
+ 476427
@@ -29739,11 +30038,11 @@
xmlElements
- 1042734675
+ 1042732803
id
- 1042734675
+ 1042732803
name
@@ -29751,15 +30050,15 @@
parentid
- 385731802
+ 385731109
idx
- 1630081
+ 1630078
fileid
- 476089
+ 476088
@@ -29773,7 +30072,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29789,7 +30088,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29805,7 +30104,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29821,7 +30120,7 @@
1
2
- 1042734675
+ 1042732803
@@ -29919,7 +30218,7 @@
1
2
- 180311
+ 180310
2
@@ -29950,7 +30249,7 @@
1
2
- 171338
+ 171337
2
@@ -29991,32 +30290,32 @@
1
2
- 187348969
+ 187348633
2
3
- 87399822
+ 87399665
3
4
- 39675923
+ 39675851
4
5
- 25725419
+ 25725373
5
8
- 33529933
+ 33529873
8
9629
- 12051732
+ 12051711
@@ -30032,27 +30331,27 @@
1
2
- 244194247
+ 244193809
2
3
- 69983618
+ 69983493
3
4
- 32247777
+ 32247719
4
5
- 25493131
+ 25493085
5
110
- 13813026
+ 13813001
@@ -30068,32 +30367,32 @@
1
2
- 187348969
+ 187348633
2
3
- 87399822
+ 87399665
3
4
- 39675923
+ 39675851
4
5
- 25725419
+ 25725373
5
8
- 33529933
+ 33529873
8
9629
- 12051732
+ 12051711
@@ -30109,7 +30408,7 @@
1
2
- 385731802
+ 385731109
@@ -30130,12 +30429,12 @@
3
4
- 626602
+ 626601
4
5
- 217897
+ 217896
6
@@ -30160,7 +30459,7 @@
141
322
- 123255
+ 123254
322
@@ -30181,7 +30480,7 @@
1
2
- 1566422
+ 1566419
2
@@ -30207,12 +30506,12 @@
3
4
- 626602
+ 626601
4
5
- 217897
+ 217896
6
@@ -30237,7 +30536,7 @@
141
322
- 123255
+ 123254
322
@@ -30263,12 +30562,12 @@
3
4
- 626602
+ 626601
4
5
- 217897
+ 217896
6
@@ -30293,7 +30592,7 @@
141
322
- 123255
+ 123254
322
@@ -30405,12 +30704,12 @@
7
9
- 24888
+ 24887
9
11
- 43681
+ 43680
11
@@ -30557,7 +30856,7 @@
51
101
- 39279
+ 39278
102
@@ -30602,15 +30901,15 @@
xmlAttrs
- 782957811
+ 782956405
id
- 782957811
+ 782956405
elementid
- 772812975
+ 772811588
name
@@ -30618,7 +30917,7 @@
value
- 16557651
+ 16557621
idx
@@ -30626,7 +30925,7 @@
fileid
- 469994
+ 469993
@@ -30640,7 +30939,7 @@
1
2
- 782957811
+ 782956405
@@ -30656,7 +30955,7 @@
1
2
- 782957811
+ 782956405
@@ -30672,7 +30971,7 @@
1
2
- 782957811
+ 782956405
@@ -30688,7 +30987,7 @@
1
2
- 782957811
+ 782956405
@@ -30704,7 +31003,7 @@
1
2
- 782957811
+ 782956405
@@ -30720,12 +31019,12 @@
1
2
- 767714315
+ 767712937
2
13
- 5098660
+ 5098651
@@ -30741,12 +31040,12 @@
1
2
- 767714315
+ 767712937
2
13
- 5098660
+ 5098651
@@ -30762,12 +31061,12 @@
1
2
- 767717701
+ 767716323
2
13
- 5095274
+ 5095264
@@ -30783,12 +31082,12 @@
1
2
- 767714315
+ 767712937
2
13
- 5098660
+ 5098651
@@ -30804,7 +31103,7 @@
1
2
- 772812975
+ 772811588
@@ -31105,42 +31404,42 @@
1
2
- 4011882
+ 4011875
2
3
- 1419294
+ 1419292
3
4
- 5374629
+ 5374619
4
6
- 795909
+ 795907
6
8
- 1488541
+ 1488538
8
27
- 1245586
+ 1245584
27
90
- 1243047
+ 1243044
90
214809
- 978759
+ 978758
@@ -31156,42 +31455,42 @@
1
2
- 4012898
+ 4012891
2
3
- 1419125
+ 1419123
3
4
- 5374968
+ 5374958
4
6
- 797094
+ 797092
6
8
- 1488033
+ 1488030
8
27
- 1244062
+ 1244060
27
90
- 1242877
+ 1242875
90
214809
- 978590
+ 978588
@@ -31207,12 +31506,12 @@
1
2
- 14765543
+ 14765517
2
3
- 1766203
+ 1766200
3
@@ -31233,7 +31532,7 @@
1
2
- 16464702
+ 16464672
2
@@ -31254,37 +31553,37 @@
1
2
- 4652030
+ 4652021
2
3
- 1284019
+ 1284016
3
4
- 6041188
+ 6041177
4
6
- 779994
+ 779992
6
8
- 1312293
+ 1312291
8
44
- 1256930
+ 1256927
44
1527
- 1231195
+ 1231193
@@ -31685,7 +31984,7 @@
711
1058
- 35385
+ 35384
1065
@@ -31741,7 +32040,7 @@
12
44
- 35385
+ 35384
44
@@ -31807,7 +32106,7 @@
2
3
- 196226
+ 196225
3
@@ -31817,12 +32116,12 @@
4
5
- 24888
+ 24887
5
6
- 45882
+ 45881
6
@@ -31858,7 +32157,7 @@
4
7
- 35385
+ 35384
7
@@ -31883,7 +32182,7 @@
131
209
- 35385
+ 35384
210
@@ -31929,12 +32228,12 @@
1
2
- 300857
+ 300856
2
3
- 35385
+ 35384
3
@@ -31959,7 +32258,7 @@
xmlNs
- 27089
+ 27088
id
@@ -32345,11 +32644,11 @@
xmlHasNs
- 513336
+ 513335
elementId
- 513336
+ 513335
nsId
@@ -32371,7 +32670,7 @@
1
2
- 513336
+ 513335
@@ -32387,7 +32686,7 @@
1
2
- 513336
+ 513335
@@ -32756,7 +33055,7 @@
1
2
- 133244
+ 133243
2
@@ -32818,7 +33117,7 @@
1
2
- 74664
+ 74663
2
@@ -32921,7 +33220,7 @@
2
3
- 8296
+ 8295
3
@@ -32992,19 +33291,19 @@
xmlChars
- 808544061
+ 808542609
id
- 808544061
+ 808542609
text
- 49726793
+ 49726704
parentid
- 487106000
+ 487105125
idx
@@ -33016,7 +33315,7 @@
fileid
- 448831
+ 448830
@@ -33030,7 +33329,7 @@
1
2
- 808544061
+ 808542609
@@ -33046,7 +33345,7 @@
1
2
- 808544061
+ 808542609
@@ -33062,7 +33361,7 @@
1
2
- 808544061
+ 808542609
@@ -33078,7 +33377,7 @@
1
2
- 808544061
+ 808542609
@@ -33094,7 +33393,7 @@
1
2
- 808544061
+ 808542609
@@ -33110,57 +33409,57 @@
1
2
- 6839129
+ 6839117
2
3
- 2738529
+ 2738525
3
4
- 10689155
+ 10689136
4
6
- 3529021
+ 3529014
6
7
- 4911407
+ 4911398
7
9
- 3937218
+ 3937211
9
10
- 893260
+ 893258
10
11
- 7086485
+ 7086473
11
20
- 3458928
+ 3458922
20
49
- 3805837
+ 3805830
49
250680
- 1837820
+ 1837816
@@ -33176,57 +33475,57 @@
1
2
- 6839975
+ 6839963
2
3
- 2739545
+ 2739540
3
4
- 10692880
+ 10692860
4
6
- 3530375
+ 3530369
6
7
- 4916317
+ 4916308
7
9
- 3942128
+ 3942121
9
10
- 893937
+ 893935
10
11
- 7101554
+ 7101541
11
20
- 3452833
+ 3452827
20
49
- 3788737
+ 3788730
49
249267
- 1828508
+ 1828505
@@ -33242,12 +33541,12 @@
1
2
- 48571955
+ 48571867
2
32
- 1154838
+ 1154836
@@ -33263,7 +33562,7 @@
1
2
- 49726793
+ 49726704
@@ -33279,47 +33578,47 @@
1
2
- 8926168
+ 8926152
2
3
- 2072309
+ 2072305
3
4
- 13690110
+ 13690085
4
5
- 3843761
+ 3843754
5
7
- 4406535
+ 4406528
7
9
- 4286497
+ 4286490
9
10
- 688060
+ 688059
10
11
- 9242432
+ 9242416
11
1537
- 2570916
+ 2570912
@@ -33335,22 +33634,22 @@
1
2
- 285652797
+ 285652284
2
3
- 137381760
+ 137381514
3
4
- 41081842
+ 41081769
4
38
- 22989598
+ 22989557
@@ -33366,22 +33665,22 @@
1
2
- 285652797
+ 285652284
2
3
- 137537861
+ 137537614
3
4
- 41794961
+ 41794886
4
28
- 22120380
+ 22120340
@@ -33397,22 +33696,22 @@
1
2
- 285652797
+ 285652284
2
3
- 137381760
+ 137381514
3
4
- 41081842
+ 41081769
4
38
- 22989598
+ 22989557
@@ -33428,7 +33727,7 @@
1
2
- 487104984
+ 487104109
2
@@ -33449,7 +33748,7 @@
1
2
- 487106000
+ 487105125
@@ -33966,7 +34265,7 @@
7
37
- 35385
+ 35384
37
@@ -34082,7 +34381,7 @@
1453
1973
- 39279
+ 39278
1995
@@ -34174,7 +34473,7 @@
1
2
- 447815
+ 447814
2
@@ -34189,15 +34488,15 @@
xmllocations
- 46972752
+ 46972668
xmlElement
- 46970079
+ 46969994
location
- 39595243
+ 39595172
@@ -34211,7 +34510,7 @@
1
2
- 46969994
+ 46969909
29
@@ -34232,12 +34531,12 @@
1
2
- 32374506
+ 32374448
2
3
- 7172695
+ 7172682
3
@@ -34252,11 +34551,11 @@
commentline
- 1227120
+ 1227125
id
- 1227120
+ 1227125
kind
@@ -34264,11 +34563,11 @@
text
- 47656
+ 47658
rawtext
- 47745
+ 47747
@@ -34282,7 +34581,7 @@
1
2
- 1227120
+ 1227125
@@ -34298,7 +34597,7 @@
1
2
- 1227120
+ 1227125
@@ -34314,7 +34613,7 @@
1
2
- 1227120
+ 1227125
@@ -34333,8 +34632,8 @@
2
- 6150
- 6151
+ 6153
+ 6154
2
@@ -34359,8 +34658,8 @@
2
- 660
- 661
+ 661
+ 662
2
@@ -34385,8 +34684,8 @@
2
- 663
- 664
+ 664
+ 665
2
@@ -34418,7 +34717,7 @@
3
5
- 4088
+ 4091
5
@@ -34444,7 +34743,7 @@
1
2
- 47649
+ 47651
2
@@ -34465,7 +34764,7 @@
1
2
- 47593
+ 47595
2
@@ -34496,7 +34795,7 @@
3
5
- 4065
+ 4067
5
@@ -34522,7 +34821,7 @@
1
2
- 47745
+ 47747
@@ -34538,7 +34837,7 @@
1
2
- 47745
+ 47747
@@ -34548,15 +34847,15 @@
commentline_location
- 1227120
+ 1227125
id
- 1227120
+ 1227125
loc
- 1227120
+ 1227125
@@ -34570,7 +34869,7 @@
1
2
- 1227120
+ 1227125
@@ -34586,7 +34885,7 @@
1
2
- 1227120
+ 1227125
@@ -34596,26 +34895,26 @@
commentblock
- 412296
+ 412295
id
- 412296
+ 412295
commentblock_location
- 412296
+ 412295
id
- 412296
+ 412295
loc
- 412296
+ 412295
@@ -34629,7 +34928,7 @@
1
2
- 412296
+ 412295
@@ -34645,7 +34944,7 @@
1
2
- 412296
+ 412295
@@ -34655,15 +34954,15 @@
commentblock_binding
- 1601079
+ 1601076
id
- 412296
+ 412295
entity
- 415904
+ 415903
bindtype
@@ -34728,7 +35027,7 @@
2
3
- 379365
+ 379364
3
@@ -34759,7 +35058,7 @@
3
4
- 345375
+ 345374
4
@@ -34836,15 +35135,15 @@
commentblock_child
- 1631666
+ 1631670
id
- 412296
+ 412295
commentline
- 1227120
+ 1227125
index
@@ -34893,7 +35192,7 @@
4
5
- 393790
+ 393789
5
@@ -34914,7 +35213,7 @@
1
2
- 1227120
+ 1227125
@@ -34930,12 +35229,12 @@
1
2
- 822573
+ 822579
2
3
- 404546
+ 404545
@@ -34985,7 +35284,7 @@
110
- 177
+ 180
7
@@ -35051,7 +35350,7 @@
110
- 177
+ 180
7
@@ -36712,11 +37011,11 @@
cil_instruction
- 370458591
+ 370457925
id
- 370458591
+ 370457925
opcode
@@ -36724,11 +37023,11 @@
index
- 1246869
+ 1246867
impl
- 17616263
+ 17616232
@@ -36742,7 +37041,7 @@
1
2
- 370458591
+ 370457925
@@ -36758,7 +37057,7 @@
1
2
- 370458591
+ 370457925
@@ -36774,7 +37073,7 @@
1
2
- 370458591
+ 370457925
@@ -37028,7 +37327,7 @@
3
4
- 343039
+ 343038
4
@@ -37048,7 +37347,7 @@
15
16
- 106652
+ 106651
16
@@ -37079,7 +37378,7 @@
1
2
- 523931
+ 523930
2
@@ -37140,7 +37439,7 @@
3
4
- 343039
+ 343038
4
@@ -37160,7 +37459,7 @@
15
16
- 106652
+ 106651
16
@@ -37191,57 +37490,57 @@
1
3
- 1299002
+ 1299000
3
4
- 3887982
+ 3887975
4
5
- 1827121
+ 1827117
5
6
- 1190311
+ 1190309
6
8
- 1392724
+ 1392721
8
11
- 1390272
+ 1390270
11
16
- 1446289
+ 1446286
16
23
- 1331978
+ 1331976
23
35
- 1364217
+ 1364214
35
67
- 1341329
+ 1341326
67
57474
- 1145034
+ 1145031
@@ -37257,52 +37556,52 @@
1
3
- 1301671
+ 1301668
3
4
- 4029628
+ 4029621
4
5
- 2083923
+ 2083919
5
6
- 1825211
+ 1825208
6
7
- 1176166
+ 1176164
7
9
- 1560903
+ 1560900
9
12
- 1593163
+ 1593160
12
16
- 1494538
+ 1494535
16
24
- 1379837
+ 1379835
24
77
- 1171219
+ 1171217
@@ -37318,57 +37617,57 @@
1
3
- 1299002
+ 1299000
3
4
- 3887982
+ 3887975
4
5
- 1827121
+ 1827117
5
6
- 1190311
+ 1190309
6
8
- 1392724
+ 1392721
8
11
- 1390272
+ 1390270
11
16
- 1446289
+ 1446286
16
23
- 1331978
+ 1331976
23
35
- 1364217
+ 1364214
35
67
- 1341329
+ 1341326
67
57474
- 1145034
+ 1145031
@@ -37378,15 +37677,15 @@
cil_jump
- 28397577
+ 28397526
instruction
- 28397577
+ 28397526
target
- 21559112
+ 21559074
@@ -37400,7 +37699,7 @@
1
2
- 28397577
+ 28397526
@@ -37416,17 +37715,17 @@
1
2
- 17986226
+ 17986194
2
3
- 2350922
+ 2350917
3
473
- 1221964
+ 1221961
@@ -37436,15 +37735,15 @@
cil_access
- 150867340
+ 150867069
instruction
- 150867340
+ 150867069
target
- 35942622
+ 35942557
@@ -37458,7 +37757,7 @@
1
2
- 150867340
+ 150867069
@@ -37474,32 +37773,32 @@
1
2
- 14815628
+ 14815601
2
3
- 9023572
+ 9023556
3
4
- 4374403
+ 4374395
4
5
- 2253837
+ 2253833
5
8
- 3030514
+ 3030508
8
72956
- 2444665
+ 2444661
@@ -37509,15 +37808,15 @@
cil_value
- 14528539
+ 14528513
instruction
- 14528539
+ 14528513
value
- 3617230
+ 3617224
@@ -37531,7 +37830,7 @@
1
2
- 14528539
+ 14528513
@@ -37547,22 +37846,22 @@
1
2
- 2708887
+ 2708882
2
3
- 497181
+ 497180
3
7
- 273507
+ 273506
7
182148
- 137654
+ 137653
@@ -37572,7 +37871,7 @@
cil_switch
- 2990400
+ 2990395
instruction
@@ -37584,7 +37883,7 @@
target
- 1319005
+ 1319002
@@ -37792,7 +38091,7 @@
1
2
- 1301584
+ 1301581
2
@@ -37813,7 +38112,7 @@
1
2
- 1172673
+ 1172671
2
@@ -37875,11 +38174,11 @@
cil_type_location
- 3557547
+ 3557541
id
- 3557547
+ 3557541
loc
@@ -37897,7 +38196,7 @@
1
2
- 3557547
+ 3557541
@@ -37973,11 +38272,11 @@
cil_method_location
- 21566771
+ 21566732
id
- 21566771
+ 21566732
loc
@@ -37995,7 +38294,7 @@
1
2
- 21566771
+ 21566732
@@ -38086,15 +38385,15 @@
cil_type
- 9109571
+ 9109554
id
- 9109571
+ 9109554
name
- 2569541
+ 2569536
kind
@@ -38102,11 +38401,11 @@
parent
- 1843609
+ 1843605
sourceDecl
- 5094760
+ 5094751
@@ -38120,7 +38419,7 @@
1
2
- 9109571
+ 9109554
@@ -38136,7 +38435,7 @@
1
2
- 9109571
+ 9109554
@@ -38152,7 +38451,7 @@
1
2
- 9109571
+ 9109554
@@ -38168,7 +38467,7 @@
1
2
- 9109571
+ 9109554
@@ -38184,12 +38483,12 @@
1
2
- 2257721
+ 2257716
2
4
- 215148
+ 215147
4
@@ -38210,7 +38509,7 @@
1
2
- 2569541
+ 2569536
@@ -38226,7 +38525,7 @@
1
2
- 2374656
+ 2374652
2
@@ -38252,12 +38551,12 @@
1
2
- 2346604
+ 2346600
2
5
- 199788
+ 199787
5
@@ -38417,7 +38716,7 @@
1
2
- 1199271
+ 1199269
2
@@ -38453,7 +38752,7 @@
1
2
- 1205692
+ 1205690
2
@@ -38489,7 +38788,7 @@
1
2
- 1815145
+ 1815142
2
@@ -38510,7 +38809,7 @@
1
2
- 1205302
+ 1205300
2
@@ -38546,7 +38845,7 @@
1
2
- 4875229
+ 4875221
2
@@ -38567,7 +38866,7 @@
1
2
- 5094760
+ 5094751
@@ -38583,7 +38882,7 @@
1
2
- 5094760
+ 5094751
@@ -38599,7 +38898,7 @@
1
2
- 5022820
+ 5022811
2
@@ -38881,23 +39180,23 @@
cil_method
- 28926216
+ 28926164
id
- 28926216
+ 28926164
name
- 5796090
+ 5796080
parent
- 5584869
+ 5584859
return_type
- 2472804
+ 2472799
@@ -38911,7 +39210,7 @@
1
2
- 28926216
+ 28926164
@@ -38927,7 +39226,7 @@
1
2
- 28926216
+ 28926164
@@ -38943,7 +39242,7 @@
1
2
- 28926216
+ 28926164
@@ -38959,22 +39258,22 @@
1
2
- 3864986
+ 3864979
2
3
- 884652
+ 884650
3
5
- 510719
+ 510718
5
19
- 435546
+ 435545
19
@@ -38995,17 +39294,17 @@
1
2
- 4034878
+ 4034871
2
3
- 825143
+ 825141
3
5
- 474033
+ 474032
5
@@ -39031,7 +39330,7 @@
1
2
- 5227663
+ 5227653
2
@@ -39057,37 +39356,37 @@
1
2
- 1766158
+ 1766155
2
3
- 1281082
+ 1281080
3
4
- 640779
+ 640778
4
5
- 458716
+ 458715
5
7
- 476614
+ 476613
7
11
- 481235
+ 481234
11
39
- 420880
+ 420879
39
@@ -39108,17 +39407,17 @@
1
2
- 1806055
+ 1806052
2
3
- 1302170
+ 1302167
3
4
- 656703
+ 656702
4
@@ -39133,7 +39432,7 @@
7
11
- 440384
+ 440383
11
@@ -39154,17 +39453,17 @@
1
2
- 2382488
+ 2382483
2
3
- 1477464
+ 1477462
3
4
- 630605
+ 630603
4
@@ -39174,12 +39473,12 @@
5
7
- 451123
+ 451122
7
12757
- 307503
+ 307502
@@ -39195,7 +39494,7 @@
1
2
- 1493649
+ 1493646
2
@@ -39215,7 +39514,7 @@
8
508819
- 175251
+ 175250
@@ -39231,17 +39530,17 @@
1
2
- 1692439
+ 1692436
2
3
- 398621
+ 398620
3
5
- 201133
+ 201132
5
@@ -39262,12 +39561,12 @@
1
2
- 1616680
+ 1616677
2
3
- 413309
+ 413308
3
@@ -39292,15 +39591,15 @@
cil_method_source_declaration
- 25660941
+ 25660895
method
- 25660941
+ 25660895
source
- 22347808
+ 22347768
@@ -39314,7 +39613,7 @@
1
2
- 25660941
+ 25660895
@@ -39330,12 +39629,12 @@
1
2
- 21046744
+ 21046706
2
981
- 1301063
+ 1301061
@@ -39345,15 +39644,15 @@
cil_method_implementation
- 19889366
+ 19889330
id
- 19889366
+ 19889330
method
- 19872444
+ 19872408
location
@@ -39371,7 +39670,7 @@
1
2
- 19889366
+ 19889330
@@ -39387,7 +39686,7 @@
1
2
- 19889366
+ 19889330
@@ -39403,7 +39702,7 @@
1
2
- 19870318
+ 19870282
2
@@ -39424,7 +39723,7 @@
1
2
- 19872444
+ 19872408
@@ -39586,15 +39885,15 @@
cil_implements
- 1031396
+ 1031394
id
- 1030962
+ 1030960
decl
- 190676
+ 190675
@@ -39608,7 +39907,7 @@
1
2
- 1030528
+ 1030526
2
@@ -39659,23 +39958,23 @@
cil_field
- 11684992
+ 11684971
id
- 11684992
+ 11684971
parent
- 2707933
+ 2707928
name
- 4586883
+ 4586875
field_type
- 2250192
+ 2250188
@@ -39689,7 +39988,7 @@
1
2
- 11684992
+ 11684971
@@ -39705,7 +40004,7 @@
1
2
- 11684992
+ 11684971
@@ -39721,7 +40020,7 @@
1
2
- 11684992
+ 11684971
@@ -39737,12 +40036,12 @@
1
2
- 796245
+ 796244
2
3
- 671000
+ 670999
3
@@ -39752,7 +40051,7 @@
4
5
- 241095
+ 241094
5
@@ -39762,12 +40061,12 @@
6
8
- 192889
+ 192888
8
15
- 209963
+ 209962
15
@@ -39788,12 +40087,12 @@
1
2
- 796245
+ 796244
2
3
- 671000
+ 670999
3
@@ -39803,7 +40102,7 @@
4
5
- 241095
+ 241094
5
@@ -39813,12 +40112,12 @@
6
8
- 192889
+ 192888
8
15
- 209963
+ 209962
15
@@ -39839,12 +40138,12 @@
1
2
- 917302
+ 917301
2
3
- 895521
+ 895519
3
@@ -39859,7 +40158,7 @@
5
8
- 237971
+ 237970
8
@@ -39880,12 +40179,12 @@
1
2
- 3517998
+ 3517991
2
3
- 582507
+ 582506
3
@@ -39911,12 +40210,12 @@
1
2
- 3517998
+ 3517991
2
3
- 582507
+ 582506
3
@@ -39942,7 +40241,7 @@
1
2
- 4006631
+ 4006624
2
@@ -39968,12 +40267,12 @@
1
2
- 1354823
+ 1354821
2
3
- 434331
+ 434330
3
@@ -39988,7 +40287,7 @@
7
58308
- 155422
+ 155421
@@ -40004,22 +40303,22 @@
1
2
- 1515669
+ 1515666
2
3
- 436132
+ 436131
3
6
- 184992
+ 184991
6
22697
- 113399
+ 113398
@@ -40035,22 +40334,22 @@
1
2
- 1648572
+ 1648569
2
3
- 261770
+ 261769
3
5
- 174839
+ 174838
5
33056
- 165011
+ 165010
@@ -40060,15 +40359,15 @@
cil_parameter
- 55186717
+ 55186618
id
- 55186717
+ 55186618
parameterizable
- 27728463
+ 27728414
index
@@ -40076,7 +40375,7 @@
param_type
- 7131258
+ 7131245
@@ -40090,7 +40389,7 @@
1
2
- 55186717
+ 55186618
@@ -40106,7 +40405,7 @@
1
2
- 55186717
+ 55186618
@@ -40122,7 +40421,7 @@
1
2
- 55186717
+ 55186618
@@ -40138,22 +40437,22 @@
1
2
- 12120712
+ 12120690
2
3
- 8866306
+ 8866290
3
4
- 4255190
+ 4255182
4
7
- 2154041
+ 2154037
7
@@ -40174,22 +40473,22 @@
1
2
- 12120712
+ 12120690
2
3
- 8866306
+ 8866290
3
4
- 4255190
+ 4255182
4
7
- 2154041
+ 2154037
7
@@ -40210,22 +40509,22 @@
1
2
- 12478872
+ 12478850
2
3
- 9036481
+ 9036465
3
4
- 4177088
+ 4177081
4
43
- 2036021
+ 2036017
@@ -40424,42 +40723,42 @@
1
2
- 2005301
+ 2005297
2
3
- 2103427
+ 2103423
3
4
- 781427
+ 781426
4
5
- 480433
+ 480432
5
7
- 544237
+ 544236
7
11
- 540137
+ 540136
11
36
- 538857
+ 538856
36
108909
- 137437
+ 137436
@@ -40475,37 +40774,37 @@
1
2
- 2033873
+ 2033869
2
3
- 2102125
+ 2102121
3
4
- 775331
+ 775330
4
5
- 473924
+ 473923
5
7
- 543586
+ 543585
7
11
- 537707
+ 537706
11
37
- 535321
+ 535320
37
@@ -40526,17 +40825,17 @@
1
2
- 5015009
+ 5015000
2
3
- 1530486
+ 1530484
3
6
- 535646
+ 535645
6
@@ -40551,37 +40850,37 @@
cil_parameter_in
- 263267
+ 263266
id
- 263267
+ 263266
cil_parameter_out
- 502431
+ 502430
id
- 502431
+ 502430
cil_setter
- 789281
+ 789279
prop
- 789281
+ 789279
method
- 789281
+ 789279
@@ -40595,7 +40894,7 @@
1
2
- 789281
+ 789279
@@ -40611,7 +40910,7 @@
1
2
- 789281
+ 789279
@@ -40668,7 +40967,7 @@
1
2
- 144249
+ 144248
2
@@ -40837,11 +41136,11 @@
cil_type_annotation
- 1287048
+ 1287046
id
- 1287048
+ 1287046
annotation
@@ -40859,7 +41158,7 @@
1
2
- 1287048
+ 1287046
@@ -40885,15 +41184,15 @@
cil_getter
- 4403800
+ 4403792
prop
- 4403800
+ 4403792
method
- 4403800
+ 4403792
@@ -40907,7 +41206,7 @@
1
2
- 4403800
+ 4403792
@@ -40923,7 +41222,7 @@
1
2
- 4403800
+ 4403792
@@ -41077,23 +41376,23 @@
cil_property
- 4409961
+ 4409953
id
- 4409961
+ 4409953
parent
- 1169158
+ 1169156
name
- 1132082
+ 1132080
property_type
- 519158
+ 519157
@@ -41107,7 +41406,7 @@
1
2
- 4409961
+ 4409953
@@ -41123,7 +41422,7 @@
1
2
- 4409961
+ 4409953
@@ -41139,7 +41438,7 @@
1
2
- 4409961
+ 4409953
@@ -41155,7 +41454,7 @@
1
2
- 383218
+ 383217
2
@@ -41206,7 +41505,7 @@
2
3
- 214085
+ 214084
3
@@ -41221,7 +41520,7 @@
5
7
- 102660
+ 102659
7
@@ -41247,12 +41546,12 @@
1
2
- 452273
+ 452272
2
3
- 353995
+ 353994
3
@@ -41288,7 +41587,7 @@
1
2
- 719380
+ 719379
2
@@ -41324,12 +41623,12 @@
1
2
- 719380
+ 719379
2
3
- 187487
+ 187486
3
@@ -41344,7 +41643,7 @@
8
3695
- 66972
+ 66971
@@ -41360,7 +41659,7 @@
1
2
- 989481
+ 989479
2
@@ -41427,7 +41726,7 @@
1
2
- 316029
+ 316028
2
@@ -41874,15 +42173,15 @@
cil_local_variable
- 16916582
+ 16916551
id
- 16916582
+ 16916551
impl
- 4885274
+ 4885265
index
@@ -41890,7 +42189,7 @@
var_type
- 2173089
+ 2173085
@@ -41904,7 +42203,7 @@
1
2
- 16916582
+ 16916551
@@ -41920,7 +42219,7 @@
1
2
- 16916582
+ 16916551
@@ -41936,7 +42235,7 @@
1
2
- 16916582
+ 16916551
@@ -41952,37 +42251,37 @@
1
2
- 1994583
+ 1994580
2
3
- 848508
+ 848506
3
4
- 575586
+ 575585
4
5
- 385691
+ 385690
5
6
- 282988
+ 282987
6
9
- 410510
+ 410509
9
29
- 366448
+ 366447
29
@@ -42003,37 +42302,37 @@
1
2
- 1994583
+ 1994580
2
3
- 848508
+ 848506
3
4
- 575586
+ 575585
4
5
- 385691
+ 385690
5
6
- 282988
+ 282987
6
9
- 410510
+ 410509
9
29
- 366448
+ 366447
29
@@ -42054,27 +42353,27 @@
1
2
- 2184197
+ 2184193
2
3
- 934203
+ 934201
3
4
- 601577
+ 601576
4
5
- 367424
+ 367423
5
7
- 394760
+ 394759
7
@@ -42258,7 +42557,7 @@
1
2
- 1379208
+ 1379206
2
@@ -42273,12 +42572,12 @@
4
7
- 171064
+ 171063
7
29
- 164317
+ 164316
29
@@ -42299,12 +42598,12 @@
1
2
- 1439672
+ 1439669
2
3
- 263506
+ 263505
3
@@ -42319,7 +42618,7 @@
12
44190
- 110058
+ 110057
@@ -42335,7 +42634,7 @@
1
2
- 1482931
+ 1482929
2
@@ -42350,7 +42649,7 @@
4
8
- 175902
+ 175901
8
@@ -42418,15 +42717,15 @@
cil_handler
- 1747392
+ 1747389
id
- 1747392
+ 1747389
impl
- 1140478
+ 1140476
index
@@ -42438,15 +42737,15 @@
try_start
- 1706714
+ 1706711
try_end
- 1726066
+ 1726063
handler_start
- 1747392
+ 1747389
@@ -42460,7 +42759,7 @@
1
2
- 1747392
+ 1747389
@@ -42476,7 +42775,7 @@
1
2
- 1747392
+ 1747389
@@ -42492,7 +42791,7 @@
1
2
- 1747392
+ 1747389
@@ -42508,7 +42807,7 @@
1
2
- 1747392
+ 1747389
@@ -42524,7 +42823,7 @@
1
2
- 1747392
+ 1747389
@@ -42540,7 +42839,7 @@
1
2
- 1747392
+ 1747389
@@ -42556,7 +42855,7 @@
1
2
- 839570
+ 839568
2
@@ -42587,7 +42886,7 @@
1
2
- 839570
+ 839568
2
@@ -42618,7 +42917,7 @@
1
2
- 1067865
+ 1067863
2
@@ -42639,7 +42938,7 @@
1
2
- 853172
+ 853171
2
@@ -42670,12 +42969,12 @@
1
2
- 847185
+ 847183
2
3
- 179308
+ 179307
3
@@ -42701,7 +43000,7 @@
1
2
- 839570
+ 839568
2
@@ -43254,7 +43553,7 @@
1
2
- 1674736
+ 1674733
2
@@ -43275,7 +43574,7 @@
1
2
- 1706714
+ 1706711
@@ -43291,7 +43590,7 @@
1
2
- 1674736
+ 1674733
2
@@ -43312,7 +43611,7 @@
1
2
- 1694109
+ 1694106
2
@@ -43333,7 +43632,7 @@
1
2
- 1689510
+ 1689507
2
@@ -43354,7 +43653,7 @@
1
2
- 1674736
+ 1674733
2
@@ -43375,7 +43674,7 @@
1
2
- 1709426
+ 1709423
2
@@ -43396,7 +43695,7 @@
1
2
- 1726066
+ 1726063
@@ -43412,7 +43711,7 @@
1
2
- 1709426
+ 1709423
2
@@ -43433,7 +43732,7 @@
1
2
- 1724634
+ 1724631
2
@@ -43454,7 +43753,7 @@
1
2
- 1726066
+ 1726063
@@ -43470,7 +43769,7 @@
1
2
- 1709426
+ 1709423
2
@@ -43491,7 +43790,7 @@
1
2
- 1747392
+ 1747389
@@ -43507,7 +43806,7 @@
1
2
- 1747392
+ 1747389
@@ -43523,7 +43822,7 @@
1
2
- 1747392
+ 1747389
@@ -43539,7 +43838,7 @@
1
2
- 1747392
+ 1747389
@@ -43555,7 +43854,7 @@
1
2
- 1747392
+ 1747389
@@ -43571,7 +43870,7 @@
1
2
- 1747392
+ 1747389
@@ -43712,11 +44011,11 @@
cil_method_stack_size
- 19888845
+ 19888809
method
- 19888845
+ 19888809
size
@@ -43734,7 +44033,7 @@
1
2
- 19888845
+ 19888809
@@ -43805,110 +44104,110 @@
cil_public
- 22449297
+ 22449256
id
- 22449297
+ 22449256
cil_private
- 11386275
+ 11386254
id
- 11386275
+ 11386254
cil_protected
- 21117144
+ 21117106
id
- 21117144
+ 21117106
cil_internal
- 725021
+ 725019
id
- 725021
+ 725019
cil_static
- 10668456
+ 10668437
id
- 10668456
+ 10668437
cil_sealed
- 4672361
+ 4672352
id
- 4672361
+ 4672352
cil_virtual
- 8620980
+ 8620965
id
- 8620980
+ 8620965
cil_abstract
- 2076286
+ 2076282
id
- 2076286
+ 2076282
cil_class
- 3287620
+ 3287614
id
- 3287620
+ 3287614
cil_interface
- 269971
+ 269970
id
- 269971
+ 269970
@@ -43937,33 +44236,33 @@
cil_specialname
- 9198303
+ 9198286
id
- 9198303
+ 9198286
cil_newslot
- 5415106
+ 5415097
id
- 5415106
+ 5415097
cil_base_class
- 3276881
+ 3276875
id
- 3276881
+ 3276875
base
@@ -43981,7 +44280,7 @@
1
2
- 3276881
+ 3276875
@@ -44027,15 +44326,15 @@
cil_base_interface
- 2149528
+ 2149524
id
- 914265
+ 914263
base
- 395714
+ 395713
@@ -44049,7 +44348,7 @@
1
2
- 516815
+ 516814
2
@@ -44090,7 +44389,7 @@
1
2
- 263484
+ 263483
2
@@ -44208,11 +44507,11 @@
cil_type_parameter
- 1302994
+ 1302992
unbound
- 978091
+ 978090
index
@@ -44220,7 +44519,7 @@
param
- 1302994
+ 1302992
@@ -44234,7 +44533,7 @@
1
2
- 730575
+ 730573
2
@@ -44260,7 +44559,7 @@
1
2
- 730575
+ 730573
2
@@ -44408,7 +44707,7 @@
1
2
- 1302994
+ 1302992
@@ -44424,7 +44723,7 @@
1
2
- 1302994
+ 1302992
@@ -44434,11 +44733,11 @@
cil_type_argument
- 8232620
+ 8232606
bound
- 6158785
+ 6158774
index
@@ -44446,7 +44745,7 @@
t
- 2057108
+ 2057104
@@ -44460,17 +44759,17 @@
1
2
- 4348543
+ 4348535
2
3
- 1618416
+ 1618413
3
43
- 191826
+ 191825
@@ -44486,17 +44785,17 @@
1
2
- 4430311
+ 4430303
2
3
- 1586134
+ 1586131
3
43
- 142340
+ 142339
@@ -44629,12 +44928,12 @@
1
2
- 889077
+ 889076
2
3
- 538076
+ 538075
3
@@ -44670,12 +44969,12 @@
1
2
- 1655948
+ 1655945
2
3
- 368856
+ 368855
3
@@ -44781,15 +45080,15 @@
cil_attribute
- 4315762
+ 4315754
attributeid
- 4315762
+ 4315754
element
- 3808557
+ 3808550
constructor
@@ -44807,7 +45106,7 @@
1
2
- 4315762
+ 4315754
@@ -44823,7 +45122,7 @@
1
2
- 4315762
+ 4315754
@@ -44839,12 +45138,12 @@
1
2
- 3532186
+ 3532180
2
3520
- 276371
+ 276370
@@ -44860,7 +45159,7 @@
1
2
- 3535506
+ 3535499
2
@@ -45017,7 +45316,7 @@
cil_attribute_named_argument
- 221114
+ 221113
attribute_id
@@ -45064,7 +45363,7 @@
1
2
- 104462
+ 104461
2
@@ -45233,11 +45532,11 @@
cil_attribute_positional_argument
- 1300780
+ 1300778
attribute_id
- 1270982
+ 1270980
index
@@ -45259,7 +45558,7 @@
1
2
- 1243724
+ 1243722
2
@@ -45280,12 +45579,12 @@
1
2
- 1243893
+ 1243891
2
4
- 27089
+ 27088
@@ -45409,11 +45708,11 @@
metadata_handle
- 80614656
+ 80614512
entity
- 80367053
+ 80366908
location
@@ -45421,7 +45720,7 @@
handle
- 2025043
+ 2025039
@@ -45435,7 +45734,7 @@
1
2
- 80240940
+ 80240796
2
@@ -45456,7 +45755,7 @@
1
2
- 80243283
+ 80243139
2
@@ -45634,7 +45933,7 @@
4
5
- 264981
+ 264980
5
@@ -45649,7 +45948,7 @@
11
15
- 171194
+ 171193
15
@@ -45664,7 +45963,7 @@
25
39
- 158763
+ 158762
39
@@ -45700,12 +45999,12 @@
1
2
- 274505
+ 274504
2
3
- 266044
+ 266043
3
@@ -45720,7 +46019,7 @@
6
8
- 171194
+ 171193
8
@@ -45750,7 +46049,7 @@
37
70
- 154207
+ 154206
70
@@ -45764,4 +46063,4 @@
-
+
\ No newline at end of file
From 548a62d1ab27ffd71dde73e8e40a115109720a11 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 17 Jan 2022 16:48:11 +0000
Subject: [PATCH 034/196] C++: Fix branch related FPs in
cpp/improper-null-termination.
---
.../ImproperNullTermination.ql | 46 +++++++++++++++++--
.../ImproperNullTermination.expected | 4 --
.../ImproperNullTermination/test.cpp | 8 ++--
3 files changed, 45 insertions(+), 13 deletions(-)
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
index ed378dce60a..f51c47cf70e 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
+++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
@@ -23,6 +23,10 @@ DeclStmt declWithNoInit(LocalVariable v) {
not exists(v.getInitializer())
}
+/**
+ * Flow from a buffer that is not not null terminated to a sink that requires
+ * null termination.
+ */
class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment {
ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" }
@@ -52,12 +56,44 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
exprDefinition(v, node, _) or
- mayAddNullTerminator(node, v.getAnAccess()) or
- node.(AddressOfExpr).getOperand() = v.getAnAccess() or // address taken
isSinkActual(node, v) // only report first use
}
}
-from ImproperNullTerminationReachability r, LocalVariable v, VariableAccess va
-where r.reaches(_, v, va)
-select va, "Variable $@ may not be null terminated.", v, v.getName()
+/**
+ * Flow from a place where null termination is added, to a sink of
+ * `ImproperNullTerminationReachability`. This was previously implemented as a
+ * simple barrier in `ImproperNullTerminationReachability`, but there were
+ * false positive results involving multiple paths from source to sink. We'd
+ * prefer to report only the results we are sure of.
+ */
+class NullTerminationReachability extends StackVariableReachabilityWithReassignment {
+ NullTerminationReachability() { this = "NullTerminationReachability" }
+
+ override predicate isSourceActual(ControlFlowNode node, StackVariable v) {
+ mayAddNullTerminator(node, v.getAnAccess()) or // null termination
+ node.(AddressOfExpr).getOperand() = v.getAnAccess() // address taken (possible null termination)
+ }
+
+ override predicate isSinkActual(ControlFlowNode node, StackVariable v) {
+ // have the same sinks as `ImproperNullTerminationReachability`.
+ exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v))
+ }
+
+ override predicate isBarrier(ControlFlowNode node, StackVariable v) {
+ // don't look further back than the source, or further forward than the sink
+ exists(ImproperNullTerminationReachability r | r.isSourceActual(node, v)) or
+ exists(ImproperNullTerminationReachability r | r.isSinkActual(node, v))
+ }
+}
+
+from
+ ImproperNullTerminationReachability reaches, NullTerminationReachability nullTermReaches,
+ ControlFlowNode source, LocalVariable v, VariableAccess sink
+where
+ reaches.reaches(source, v, sink) and
+ not exists(ControlFlowNode termination |
+ nullTermReaches.reaches(termination, _, sink) and
+ termination != source
+ )
+select sink, "Variable $@ may not be null terminated.", v, v.getName()
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected
index 0325ba89a22..beaa1033eb2 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected
+++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/ImproperNullTermination.expected
@@ -18,10 +18,6 @@
| test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 |
| test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer |
| test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer |
-| test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer |
-| test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer |
-| test.cpp:392:11:392:16 | buffer | Variable $@ may not be null terminated. | test.cpp:381:8:381:13 | buffer | buffer |
-| test.cpp:410:11:410:16 | buffer | Variable $@ may not be null terminated. | test.cpp:397:8:397:13 | buffer | buffer |
| test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 |
| test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer |
| test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer |
diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp
index 88fbc46119b..49dc01a40df 100644
--- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp
+++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/ImproperNullTermination/test.cpp
@@ -352,7 +352,7 @@ void test_strlen(bool cond1, bool cond2)
if (cond1)
buffer[0] = 0;
if (cond1)
- strlen(buffer); // GOOD [FALSE POSITIVE]
+ strlen(buffer); // GOOD
}
{
@@ -361,7 +361,7 @@ void test_strlen(bool cond1, bool cond2)
if (cond1)
buffer[0] = 0;
if (cond2)
- strlen(buffer); // BAD
+ strlen(buffer); // BAD [NOT DETECTED]
}
{
@@ -389,7 +389,7 @@ void test_strlen(bool cond1, bool cond2)
if (init != 0)
{
- strlen(buffer); // GOOD [FALSE POSITIVE]
+ strlen(buffer); // GOOD
}
}
@@ -407,7 +407,7 @@ void test_strlen(bool cond1, bool cond2)
{
// ...
} else {
- strlen(buffer); // GOOD [FALSE POSITIVE]
+ strlen(buffer); // GOOD
}
}
}
From ea7945bac10055da69d6968a0ddb2b987ff6d7e8 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:21:07 +0100
Subject: [PATCH 035/196] QL: show recommendation queries by default, and
remove the MissingQLDoc query
---
ql/ql/src/codeql-suites/ql-code-scanning.qls | 1 +
ql/ql/src/queries/style/docs/MissingQLDoc.ql | 25 --------------------
2 files changed, 1 insertion(+), 25 deletions(-)
delete mode 100644 ql/ql/src/queries/style/docs/MissingQLDoc.ql
diff --git a/ql/ql/src/codeql-suites/ql-code-scanning.qls b/ql/ql/src/codeql-suites/ql-code-scanning.qls
index f6b2a097b0a..f9e4f729d3e 100644
--- a/ql/ql/src/codeql-suites/ql-code-scanning.qls
+++ b/ql/ql/src/codeql-suites/ql-code-scanning.qls
@@ -12,6 +12,7 @@
problem.severity:
- error
- warning
+ - recommendation
- exclude:
deprecated: //
- exclude:
diff --git a/ql/ql/src/queries/style/docs/MissingQLDoc.ql b/ql/ql/src/queries/style/docs/MissingQLDoc.ql
deleted file mode 100644
index c7da02073a3..00000000000
--- a/ql/ql/src/queries/style/docs/MissingQLDoc.ql
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- * @name Missing QLDoc.
- * @description Library classes should have QLDoc.
- * @kind problem
- * @problem.severity recommendation
- * @id ql/missing-qldoc
- * @tags maintainability
- * @precision high
- */
-
-import ql
-
-from File f, Class c
-where
- f = c.getLocation().getFile() and
- not exists(c.getQLDoc()) and // no QLDoc
- f.getExtension() = "qll" and // in a library
- not c.isPrivate() and // class is public
- not exists(Module m |
- m.getAMember*() = c and
- m.isPrivate() // modules containing the class are public
- ) and
- not exists(c.getAliasType()) and // class is not just an alias
- not f.getParentContainer*().getBaseName().toLowerCase() = ["internal", "experimental", "test"] // exclusions
-select c, "This library class should have QLDoc."
From 95ae1139943770cb5410d01f3d87db537e4a730b Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:22:01 +0100
Subject: [PATCH 036/196] QL: downgrade redundant-inline-cast to a warning
query
---
ql/ql/src/queries/style/RedundantInlineCast.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ql/ql/src/queries/style/RedundantInlineCast.ql b/ql/ql/src/queries/style/RedundantInlineCast.ql
index 29dc83e52de..ae307b408b8 100644
--- a/ql/ql/src/queries/style/RedundantInlineCast.ql
+++ b/ql/ql/src/queries/style/RedundantInlineCast.ql
@@ -2,7 +2,7 @@
* @name Redundant inline cast
* @description Redundant inline casts
* @kind problem
- * @problem.severity error
+ * @problem.severity warning
* @id ql/redundant-inline-cast
* @tags maintainability
* @precision high
From 1ec868eeaea162ccdf41a3958beb281ce7385407 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:23:33 +0100
Subject: [PATCH 037/196] QL: various improvements to Ast.qll
---
ql/ql/src/codeql_ql/ast/Ast.qll | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll
index f0821d063fa..be2973d5ddf 100644
--- a/ql/ql/src/codeql_ql/ast/Ast.qll
+++ b/ql/ql/src/codeql_ql/ast/Ast.qll
@@ -63,6 +63,9 @@ class AstNode extends TAstNode {
pred = directMember("getQLDoc") and result = this.getQLDoc()
}
+ /** Gets any child of this node. */
+ AstNode getAChild() { result = this.getAChild(_) }
+
/**
* Gets the primary QL class for the ast node.
*/
@@ -1238,14 +1241,7 @@ class Boolean extends Literal {
/** A comparison symbol, such as `"<"` or `"="`. */
class ComparisonSymbol extends string {
- ComparisonSymbol() {
- this = "=" or
- this = "!=" or
- this = "<" or
- this = ">" or
- this = "<=" or
- this = ">="
- }
+ ComparisonSymbol() { this = ["=", "!=", "<", ">", "<=", ">="] }
}
/** A comparison formula, such as `x < 3` or `y = true`. */
@@ -1287,10 +1283,7 @@ class Quantifier extends TQuantifier, Formula {
}
/** Gets the ith variable declaration of this quantifier. */
- VarDecl getArgument(int i) {
- i >= 1 and
- toQL(result) = quant.getChild(i - 1)
- }
+ VarDecl getArgument(int i) { toQL(result) = quant.getChild(i + 1) }
/** Gets an argument of this quantifier. */
VarDecl getAnArgument() { result = this.getArgument(_) }
@@ -1661,6 +1654,15 @@ class FullAggregate extends TFullAggregate, Aggregate {
}
}
+/**
+ * A "any" expression, such as `any(int i | i > 0).toString()`.
+ */
+class Any extends FullAggregate {
+ Any() { this.getKind() = "any" }
+
+ override string getAPrimaryQlClass() { result = "Any" }
+}
+
/**
* A "rank" expression, such as `rank[4](int i | i = [5 .. 15] | i)`.
*/
@@ -1855,7 +1857,7 @@ class ExprAnnotation extends TExprAnnotation, Expr {
/** A function symbol, such as `+` or `*`. */
class FunctionSymbol extends string {
- FunctionSymbol() { this = "+" or this = "-" or this = "*" or this = "/" or this = "%" }
+ FunctionSymbol() { this = ["+", "-", "*", "/", "%"] }
}
/**
From a1f4c85deaeb8dfe6534bc679527b38544f545db Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:37:04 +0100
Subject: [PATCH 038/196] QL: update expected output for the printAst test
---
ql/ql/test/printAst/printAst.expected | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/ql/ql/test/printAst/printAst.expected b/ql/ql/test/printAst/printAst.expected
index 45e8497dfad..3d1e86a7c92 100644
--- a/ql/ql/test/printAst/printAst.expected
+++ b/ql/ql/test/printAst/printAst.expected
@@ -121,8 +121,8 @@ nodes
| Foo.qll:22:3:22:3 | f | semmle.order | 60 |
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.label | [ComparisonFormula] ComparisonFormula |
| Foo.qll:22:3:22:16 | ComparisonFormula | semmle.order | 60 |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.label | [FullAggregate[any]] FullAggregate[any] |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 62 |
+| Foo.qll:22:7:22:16 | Any | semmle.label | [Any] Any |
+| Foo.qll:22:7:22:16 | Any | semmle.order | 62 |
| Foo.qll:22:11:22:13 | TypeExpr | semmle.label | [TypeExpr] TypeExpr |
| Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 63 |
| Foo.qll:22:11:22:15 | f | semmle.label | [VarDecl] f |
@@ -363,10 +363,10 @@ edges
| Foo.qll:20:3:20:13 | ComparisonFormula | Foo.qll:20:13:20:13 | f | semmle.order | 59 |
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.label | getLeftOperand() |
| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:3:22:3 | f | semmle.order | 60 |
-| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.label | getRightOperand() |
-| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | FullAggregate[any] | semmle.order | 62 |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.label | getArgument(_) |
-| Foo.qll:22:7:22:16 | FullAggregate[any] | Foo.qll:22:11:22:15 | f | semmle.order | 63 |
+| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | Any | semmle.label | getRightOperand() |
+| Foo.qll:22:3:22:16 | ComparisonFormula | Foo.qll:22:7:22:16 | Any | semmle.order | 62 |
+| Foo.qll:22:7:22:16 | Any | Foo.qll:22:11:22:15 | f | semmle.label | getArgument(_) |
+| Foo.qll:22:7:22:16 | Any | Foo.qll:22:11:22:15 | f | semmle.order | 63 |
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.label | getTypeExpr() |
| Foo.qll:22:11:22:15 | f | Foo.qll:22:11:22:13 | TypeExpr | semmle.order | 63 |
| Foo.qll:24:3:24:23 | ComparisonFormula | Foo.qll:24:3:24:3 | Integer | semmle.label | getLeftOperand() |
From 14d2f5fe0280ec4c8e07cb301cc3c0ed90bf21ba Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 13:37:32 +0100
Subject: [PATCH 039/196] QL: add a new ql/could-be-cast query
---
.../src/codeql_ql/style/CouldBeCastQuery.qll | 53 +++++++++++++++++++
ql/ql/src/queries/style/CouldBeCast.ql | 23 ++++++++
.../style/CouldBeCast/CouldBeCast.expected | 3 ++
.../style/CouldBeCast/CouldBeCast.qlref | 1 +
ql/ql/test/queries/style/CouldBeCast/Foo.qll | 19 +++++++
5 files changed, 99 insertions(+)
create mode 100644 ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll
create mode 100644 ql/ql/src/queries/style/CouldBeCast.ql
create mode 100644 ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
create mode 100644 ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref
create mode 100644 ql/ql/test/queries/style/CouldBeCast/Foo.qll
diff --git a/ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll b/ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll
new file mode 100644
index 00000000000..1ad2157c4dc
--- /dev/null
+++ b/ql/ql/src/codeql_ql/style/CouldBeCastQuery.qll
@@ -0,0 +1,53 @@
+import ql
+
+/**
+ * Holds if `aggr` is of one of the following forms:
+ * `exists(var | range)` or `any(var | range)` or `any(var | | range)` or `any(type x | .. | x)`
+ */
+private predicate castAggregate(AstNode aggr, Formula range, VarDecl var, string kind) {
+ kind = "exists" and
+ exists(Exists ex | aggr = ex |
+ ex.getRange() = range and
+ not exists(ex.getFormula()) and
+ count(ex.getArgument(_)) = 1 and
+ ex.getArgument(0) = var
+ )
+ or
+ kind = "any" and
+ exists(Any anyy | aggr = anyy |
+ not exists(anyy.getRange()) and
+ anyy.getExpr(0) = range and
+ count(anyy.getExpr(_)) = 1 and
+ count(anyy.getArgument(_)) = 1 and
+ anyy.getArgument(0) = var
+ )
+ or
+ kind = "any" and
+ exists(Any anyy | aggr = anyy |
+ range = anyy.getRange() and
+ count(anyy.getArgument(_)) = 1 and
+ anyy.getArgument(0) = var and
+ not exists(anyy.getExpr(0))
+ )
+ or
+ kind = "any" and
+ exists(Any anyy | aggr = anyy |
+ range = anyy.getRange() and
+ count(anyy.getExpr(_)) = 1 and
+ count(anyy.getArgument(_)) = 1 and
+ anyy.getExpr(_).(VarAccess).getDeclaration() = var and
+ anyy.getArgument(0) = var
+ )
+}
+
+/** Holds if `aggr` is an aggregate that could be replaced with an instanceof expression or an inline cast. */
+predicate aggregateCouldBeCast(
+ AstNode aggr, ComparisonFormula comp, string kind, VarDecl var, AstNode operand
+) {
+ castAggregate(aggr, comp, var, kind) and
+ comp.getOperator() = "=" and
+ count(VarAccess access | access.getDeclaration() = var and access.getParent() != aggr) = 1 and
+ comp.getAnOperand().(VarAccess).getDeclaration() = var and
+ operand = comp.getAnOperand() and
+ not operand.(VarAccess).getDeclaration() = var
+}
diff --git a/ql/ql/src/queries/style/CouldBeCast.ql b/ql/ql/src/queries/style/CouldBeCast.ql
new file mode 100644
index 00000000000..73eeaf0a90f
--- /dev/null
+++ b/ql/ql/src/queries/style/CouldBeCast.ql
@@ -0,0 +1,23 @@
+/**
+ * @name Expression can be replaced with a cast
+ * @description An exists/any that is only used to cast a value to a type
+ * can be replaced with a cast.
+ * @kind problem
+ * @problem.severity warning
+ * @id ql/could-be-cast
+ * @precision very-high
+ */
+
+import ql
+import codeql_ql.style.CouldBeCastQuery
+
+from AstNode aggr, VarDecl var, string msg
+where
+ exists(string kind | aggregateCouldBeCast(aggr, _, kind, var, _) |
+ kind = "exists" and
+ msg = "The assignment to $@ in the exists(..) can replaced with an instanceof expression."
+ or
+ kind = "any" and
+ msg = "The assignment to $@ in this any(..) can be replaced with an inline cast."
+ )
+select aggr, msg, var, var.getName()
diff --git a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
new file mode 100644
index 00000000000..41792f6892d
--- /dev/null
+++ b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
@@ -0,0 +1,3 @@
+| Foo.qll:3:3:3:24 | Exists | The assignment to $@ in the exists(..) can replaced with an instanceof expression. | Foo.qll:3:10:3:15 | j | j |
+| Foo.qll:7:3:7:21 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:7:7:7:12 | j | j |
+| Foo.qll:9:3:9:25 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:9:7:9:12 | j | j |
diff --git a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref
new file mode 100644
index 00000000000..78879bb0ab0
--- /dev/null
+++ b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.qlref
@@ -0,0 +1 @@
+queries/style/CouldBeCast.ql
\ No newline at end of file
diff --git a/ql/ql/test/queries/style/CouldBeCast/Foo.qll b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
new file mode 100644
index 00000000000..1bd94cfd829
--- /dev/null
+++ b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
@@ -0,0 +1,19 @@
+bindingset[i]
+predicate foo(int i) {
+ exists(Even j | j = i) // NOT OK
+ or
+ exists(Even j | j = i | j % 4 = 0) // OK
+ or
+ any(Even j | j = i) = 2 // NOT OK
+ or
+ any(Even j | j = i | j) = 2 // NOT OK
+ or
+ any(Even j | j = i | j * 2) = 4 // OK
+ or
+ any(Even j | j = i and j % 4 = 0 | j) = 4 // OK
+}
+
+class Even extends int {
+ bindingset[this]
+ Even() { this % 2 = 0 }
+}
From 92f5a5f893db792be3074997378a99330d7fcb38 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Tue, 18 Jan 2022 13:43:17 +0100
Subject: [PATCH 040/196] Reduce FPs in IncorrectPrivilegeAssignment.ql
Implements suggestions from https://github.com/github/codeql/pull/6949#issuecomment-976482965
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index 72c7f359b47..9c0481702f7 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -53,7 +53,13 @@ where
fctmp.getTarget().hasGlobalOrStdName("fopen") or
fctmp.getTarget().hasGlobalOrStdName("open")
) and
- not fctmp.getArgument(1).getValue().matches("r%") and
+ (
+ fctmp.getArgument(1).getValue().matches("%a%") or
+ // unfortunately cannot use numeric value here because // O_APPEND is defined differently on different OSes:
+ // https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
+ // this may introduce false negatives
+ fctmp.getArgument(1).getValueText().matches("%O_APPEND%")
+ ) and
fctmp.getNumberOfArguments() = 2 and
not fctmp.getArgument(0).getValue() = "/dev/null" and
fcsnd = fctmp
From 30d896bdbbf2f436e498f1db39537012c4efc5e0 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Tue, 18 Jan 2022 14:25:43 +0100
Subject: [PATCH 041/196] QL: make the alert-message more precise when the
type-cast is also redundant
---
ql/ql/src/queries/style/CouldBeCast.ql | 12 ++++++++----
.../queries/style/CouldBeCast/CouldBeCast.expected | 2 ++
ql/ql/test/queries/style/CouldBeCast/Foo.qll | 4 ++++
3 files changed, 14 insertions(+), 4 deletions(-)
diff --git a/ql/ql/src/queries/style/CouldBeCast.ql b/ql/ql/src/queries/style/CouldBeCast.ql
index 73eeaf0a90f..a5c0d6c6607 100644
--- a/ql/ql/src/queries/style/CouldBeCast.ql
+++ b/ql/ql/src/queries/style/CouldBeCast.ql
@@ -11,13 +11,17 @@
import ql
import codeql_ql.style.CouldBeCastQuery
-from AstNode aggr, VarDecl var, string msg
+from AstNode aggr, VarDecl var, string msg, Expr operand
where
- exists(string kind | aggregateCouldBeCast(aggr, _, kind, var, _) |
+ exists(string kind | aggregateCouldBeCast(aggr, _, kind, var, operand) |
kind = "exists" and
- msg = "The assignment to $@ in the exists(..) can replaced with an instanceof expression."
+ if operand.getType().getASuperType*() = var.getType()
+ then msg = "The assignment in the exists(..) is redundant."
+ else msg = "The assignment to $@ in the exists(..) can replaced with an instanceof expression."
or
kind = "any" and
- msg = "The assignment to $@ in this any(..) can be replaced with an inline cast."
+ if operand.getType().getASuperType*() = var.getType()
+ then msg = "The assignment in the any(..) is redundant."
+ else msg = "The assignment to $@ in this any(..) can be replaced with an inline cast."
)
select aggr, msg, var, var.getName()
diff --git a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
index 41792f6892d..83792e2fa46 100644
--- a/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
+++ b/ql/ql/test/queries/style/CouldBeCast/CouldBeCast.expected
@@ -1,3 +1,5 @@
| Foo.qll:3:3:3:24 | Exists | The assignment to $@ in the exists(..) can replaced with an instanceof expression. | Foo.qll:3:10:3:15 | j | j |
| Foo.qll:7:3:7:21 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:7:7:7:12 | j | j |
| Foo.qll:9:3:9:25 | Any | The assignment to $@ in this any(..) can be replaced with an inline cast. | Foo.qll:9:7:9:12 | j | j |
+| Foo.qll:15:3:15:20 | Any | The assignment in the any(..) is redundant. | Foo.qll:15:7:15:11 | j | j |
+| Foo.qll:17:3:17:23 | Exists | The assignment in the exists(..) is redundant. | Foo.qll:17:10:17:14 | j | j |
diff --git a/ql/ql/test/queries/style/CouldBeCast/Foo.qll b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
index 1bd94cfd829..5f6771f0043 100644
--- a/ql/ql/test/queries/style/CouldBeCast/Foo.qll
+++ b/ql/ql/test/queries/style/CouldBeCast/Foo.qll
@@ -11,6 +11,10 @@ predicate foo(int i) {
any(Even j | j = i | j * 2) = 4 // OK
or
any(Even j | j = i and j % 4 = 0 | j) = 4 // OK
+ or
+ any(int j | j = i) = 2 // NOT OK
+ or
+ exists(int j | j = i) // NOT OK
}
class Even extends int {
From 47697f59c150882a5d7c530072f1cad30bff0544 Mon Sep 17 00:00:00 2001
From: Jeff Gran
Date: Sat, 13 Nov 2021 13:42:17 -0700
Subject: [PATCH 042/196] Ruby: Add classes for detecting user input from
`graphql-ruby`
---
ruby/ql/lib/codeql/ruby/Frameworks.qll | 1 +
.../ql/lib/codeql/ruby/frameworks/GraphQL.qll | 422 ++++++++++++++++++
.../library-tests/frameworks/GraphQL.expected | 46 ++
.../test/library-tests/frameworks/GraphQL.ql | 36 ++
.../frameworks/StandardLibrary.expected | 9 +
.../app/graphql/mutations/base_mutation.rb | 8 +
.../frameworks/app/graphql/mutations/dummy.rb | 14 +
.../frameworks/app/graphql/resolvers/base.rb | 4 +
.../app/graphql/resolvers/dummy_resolver.rb | 15 +
.../app/graphql/types/base_argument.rb | 4 +
.../app/graphql/types/base_field.rb | 5 +
.../app/graphql/types/base_input_object.rb | 5 +
.../app/graphql/types/base_interface.rb | 7 +
.../app/graphql/types/base_object.rb | 5 +
.../app/graphql/types/mutation_type.rb | 5 +
.../app/graphql/types/query_type.rb | 46 ++
.../cwe-078/CommandInjection.expected | 8 +
.../security/cwe-078/CommandInjection.rb | 38 ++
18 files changed, 678 insertions(+)
create mode 100644 ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
create mode 100644 ruby/ql/test/library-tests/frameworks/GraphQL.expected
create mode 100644 ruby/ql/test/library-tests/frameworks/GraphQL.ql
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb
create mode 100644 ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb
diff --git a/ruby/ql/lib/codeql/ruby/Frameworks.qll b/ruby/ql/lib/codeql/ruby/Frameworks.qll
index 8939bacf23b..70bb35f4651 100644
--- a/ruby/ql/lib/codeql/ruby/Frameworks.qll
+++ b/ruby/ql/lib/codeql/ruby/Frameworks.qll
@@ -6,6 +6,7 @@ private import codeql.ruby.frameworks.ActionController
private import codeql.ruby.frameworks.ActiveRecord
private import codeql.ruby.frameworks.ActiveStorage
private import codeql.ruby.frameworks.ActionView
+private import codeql.ruby.frameworks.GraphQL
private import codeql.ruby.frameworks.Rails
private import codeql.ruby.frameworks.StandardLibrary
private import codeql.ruby.frameworks.Files
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
new file mode 100644
index 00000000000..e6779b65a0f
--- /dev/null
+++ b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
@@ -0,0 +1,422 @@
+private import codeql.ruby.AST
+private import codeql.ruby.Concepts
+private import codeql.ruby.controlflow.CfgNodes
+private import codeql.ruby.DataFlow
+private import codeql.ruby.dataflow.RemoteFlowSources
+private import codeql.ruby.ast.internal.Module
+private import codeql.ruby.ApiGraphs
+
+private class GraphqlRelayClassicMutationAccess extends ConstantReadAccess {
+ //GraphQL::Schema::RelayClassicMutation
+ GraphqlRelayClassicMutationAccess() {
+ this =
+ API::getTopLevelMember("GraphQL")
+ .getMember("Schema")
+ .getMember("RelayClassicMutation")
+ .getAUse()
+ .asExpr()
+ .getExpr()
+ }
+}
+
+private class GraphqlSchemaResolverAccess extends ConstantReadAccess {
+ //GraphQL::Schema::Resolver
+ GraphqlSchemaResolverAccess() {
+ this =
+ API::getTopLevelMember("GraphQL")
+ .getMember("Schema")
+ .getMember("Resolver")
+ .getAUse()
+ .asExpr()
+ .getExpr()
+ }
+}
+
+private class GraphqlSchemaObjectAccess extends ConstantReadAccess {
+ //GraphQL::Schema::Object
+ GraphqlSchemaObjectAccess() {
+ this =
+ API::getTopLevelMember("GraphQL")
+ .getMember("Schema")
+ .getMember("Object")
+ .getAUse()
+ .asExpr()
+ .getExpr()
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends `GraphQL::Schema::RelayClassicMutation`.
+ * For example,
+ *
+ * ```rb
+ * module Mutations
+ * class BaseMutation < GraphQL::Schema::RelayClassicMutation
+ * argument_class Types::BaseArgument
+ * field_class Types::BaseField
+ * input_object_class Types::BaseInputObject
+ * object_class Types::BaseObject
+ * end
+ * end
+ *
+ * module Mutation
+ * class MyMutation < BaseMutation
+ * argument :something_id, ID, required: false
+ * field :success, Boolean, null: false
+ *
+ * def resolve(something_id:)
+ * # call your application logic here...
+ * end
+ * end
+ * end
+ * ```
+ */
+private class GraphqlRelayClassicMutationClass extends ClassDeclaration {
+ GraphqlRelayClassicMutationClass() {
+ // class BaseMutation < GraphQL::Schema::RelayClassicMutation
+ this.getSuperclassExpr() instanceof GraphqlRelayClassicMutationAccess
+ or
+ // class MyMutation < BaseMutation
+ exists(GraphqlRelayClassicMutationClass other |
+ other.getModule() = resolveConstantReadAccess(this.getSuperclassExpr())
+ )
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends `GraphQL::Schema::Resolver`.
+ * For example,
+ *
+ * ```rb
+ * module Resolvers
+ * class Base < GraphQL::Schema::Resolver
+ * argument_class Arguments::Base
+ * end
+ * end
+ *
+ * module Resolvers
+ * class RecommendedItems < Resolvers::Base
+ * type [Types::Item], null: false
+ * argument :order_by, Types::ItemOrder, required: false
+ *
+ * def resolve(order_by: )
+ * # call your application logic here...
+ * end
+ * end
+ * end
+ * ```
+ */
+private class GraphqlSchemaResolverClass extends ClassDeclaration {
+ GraphqlSchemaResolverClass() {
+ // class BaseResolver < GraphQL::Schema::Resolver
+ this.getSuperclassExpr() instanceof GraphqlSchemaResolverAccess
+ or
+ // class MyResolver < BaseResolver
+ exists(GraphqlSchemaResolverClass other |
+ other.getModule() = resolveConstantReadAccess(this.getSuperclassExpr())
+ )
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends `GraphQL::Schema::Object`.
+ * For example,
+ *
+ * ```rb
+ * class BaseObject < GraphQL::Schema::Object
+ * field_class BaseField
+ * end
+ *
+ * class Musician < BaseObject
+ * field :favorite_key, Key
+ * end
+ * ```
+ */
+class GraphqlSchemaObjectClass extends ClassDeclaration {
+ GraphqlSchemaObjectClass() {
+ // class BaseObject < GraphQL::Schema::Object
+ this.getSuperclassExpr() instanceof GraphqlSchemaObjectAccess
+ or
+ // class MyObject < BaseObject
+ exists(GraphqlSchemaObjectClass other |
+ other.getModule() = resolveConstantReadAccess(this.getSuperclassExpr())
+ )
+ }
+
+ /** Gets a `GraphqlFieldDefinitionMethodCall` called in this class. */
+ GraphqlFieldDefinitionMethodCall getAFieldDefinitionMethodCall() {
+ result.getReceiverClass() = this
+ }
+}
+
+/**
+ * A `ClassDeclaration` for a class that extends either
+ * `GraphQL::Schema::RelayClassicMutation` or
+ * `GraphQL::Schema::Resolver`.
+ *
+ * Both of these classes have an overrideable `resolve` instance
+ * method which can receive user input in order to resolve a query or mutation.
+ */
+private class GraphqlResolvableClass extends ClassDeclaration {
+ GraphqlResolvableClass() {
+ this instanceof GraphqlRelayClassicMutationClass or
+ this instanceof GraphqlSchemaResolverClass
+ }
+}
+
+/**
+ * A `resolve` instance method on a sub-class of either
+ * `GraphQL::Schema::RelayClassicMutation` or
+ * `GraphQL::Schema::Resolver`.
+ *
+ * This `resolve` method is essentially an HTTP request handler.
+ * The user input data comes in through a GraphQL query, is parsed by the GraphQL
+ * library, and this method handles the request. Then the result is serialized
+ * into a GraphQL response on the way out.
+ *
+ * For example:
+ *
+ * ```rb
+ * module Mutation
+ * class NameAnInstrument < BaseMutationn
+ * argument :instrument_uuid, Types::Uuid,
+ * required: true,
+ * loads: ::Instrument,
+ * as: :instrument,
+ * argument :name, String, required: true
+ *
+ * def load_instrument(uuid)
+ * ::Instrument.find_by(uuid: uuid)
+ * end
+ *
+ * # GraphqlResolveMethod
+ * def resolve(instrument:, name:)
+ * instrument.set_name(name)
+ * end
+ * end
+ * end
+ * ```
+ */
+class GraphqlResolveMethod extends Method, HTTP::Server::RequestHandler::Range {
+ private GraphqlResolvableClass resolvableClass;
+
+ GraphqlResolveMethod() { this = resolvableClass.getMethod("resolve") }
+
+ override Parameter getARoutedParameter() { result = this.getAParameter() }
+
+ override string getFramework() { result = "GraphQL" }
+
+ /** Gets the mutation class containing this method. */
+ GraphqlResolvableClass getMutationClass() { result = resolvableClass }
+}
+
+/**
+ * A `load_*` method on a sub-class of either
+ * `GraphQL::Schema::RelayClassicMutation` or
+ * `GraphQL::Schema::Resolver`.
+ *
+ * This method takes user input (some kind of ID or specifier) and is intended
+ * to resolve the domain object using that ID.
+ *
+ * For example:
+ *
+ * ```rb
+ * module Mutation
+ * class NameAnInstrument < BaseMutationn
+ * argument :instrument_uuid, Types::Uuid,
+ * required: true,
+ * loads: ::Instrument,
+ * as: :instrument,
+ * argument :name, String, required: true
+ *
+ * # GraphqlLoadMethod
+ * def load_instrument(uuid)
+ * ::Instrument.find_by(uuid: uuid)
+ * end
+ *
+ * def resolve(instrument:, name:)
+ * instrument.set_name(name)
+ * end
+ * end
+ * end
+ * ```
+ */
+class GraphqlLoadMethod extends Method, HTTP::Server::RequestHandler::Range {
+ private GraphqlResolvableClass resolvableClass;
+
+ GraphqlLoadMethod() {
+ this.getEnclosingModule() = resolvableClass and
+ this.getName().regexpMatch("^load_.*")
+ }
+
+ override Parameter getARoutedParameter() { result = this.getAParameter() }
+
+ override string getFramework() { result = "GraphQL" }
+
+ /** Gets the mutation class containing this method. */
+ GraphqlResolvableClass getMutationClass() { result = resolvableClass }
+}
+
+/**
+ * A `MethodCall` that represents calling a class method on a
+ * a sub-class of `GraphQL::Schema::Object`
+ */
+private class GraphqlSchemaObjectClassMethodCall extends MethodCall {
+ private GraphqlSchemaObjectClass recvCls;
+
+ GraphqlSchemaObjectClassMethodCall() {
+ // e.g. Foo.some_method(...)
+ recvCls.getModule() = resolveConstantReadAccess(this.getReceiver())
+ or
+ // e.g. self.some_method(...) within a graphql Object or Interface
+ this.getReceiver() instanceof Self and
+ this.getEnclosingModule() = recvCls
+ }
+
+ /** Gets the `GraphqlSchemaObjectClass` representing the receiver of this method. */
+ GraphqlSchemaObjectClass getReceiverClass() { result = recvCls }
+}
+
+/**
+ * A `MethodCall` that represents calling the class method `field` on a GraphQL
+ * object.
+ *
+ * For example:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * # GraphqlFieldDefinitionMethodCall
+ * field :email, String
+ * end
+ * ```
+ *
+ * See also: https://graphql-ruby.org/fields/introduction.html
+ */
+class GraphqlFieldDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCall {
+ GraphqlFieldDefinitionMethodCall() { this.getMethodName() = "field" }
+
+ /** Gets the name of this GraphQL field. */
+ string getFieldName() { result = this.getArgument(0).getValueText() }
+}
+
+/**
+ * A `MethodCall` that represents calling the class method `argument` inside the
+ * block for a `field` definition on a GraphQL object.
+ *
+ * For example:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * field :email, String
+ * field :friends, [Types::User] do
+ * # GraphqlFieldArgumentDefinitionMethodCall
+ * argument :starts_with, String, "Show only friends matching the given prefix"
+ * end
+ * end
+ * ```
+ *
+ * See Also: https://graphql-ruby.org/fields/arguments
+ */
+private class GraphqlFieldArgumentDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCall {
+ private GraphqlFieldDefinitionMethodCall fieldDefinition;
+
+ GraphqlFieldArgumentDefinitionMethodCall() {
+ this.getMethodName() = "argument" and
+ fieldDefinition.getBlock() = this.getEnclosingCallable()
+ }
+
+ /** Gets the method call that defines the GraphQL field this argument is for */
+ GraphqlFieldDefinitionMethodCall getFieldDefinition() { result = fieldDefinition }
+
+ /** Gets the name of the field which this is an argument for */
+ string getFieldName() { result = this.getFieldDefinition().getFieldName() }
+
+ /** Gets the name of the argument (i.e. the first argument to this `argument` method call) */
+ string getArgumentName() { result = this.getArgument(0).(SymbolLiteral).getValueText() }
+}
+
+/**
+ * A `Method` which represents an instance method which is the resolver method for a
+ * GraphQL `field`.
+ *
+ * For example:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * field :email, String
+ * field :friends, [Types::User] do
+ * argument :starts_with, String, "Show only friends matching the given prefix"
+ * end
+ *
+ * # GraphqlFieldResolutionMethod
+ * def friends(starts_with:)
+ * object.friends.where("name like #{starts_with}")
+ * end
+ * end
+ * ```
+ *
+ * or:
+ *
+ * ```rb
+ * class Types::User < GraphQL::Schema::Object
+ * field :email, String
+ * field :friends, [Types::User] do
+ * argument :starts_with, String, "Show only friends matching the given prefix",
+ * resolver_method: :my_custom_method, extras: [:graphql_name]
+ * end
+ *
+ * # GraphqlFieldResolutionMethod
+ * def my_custom_method(**args)
+ * puts args[:graphql_name] # for debugging
+ * object.friends.where("name like #{args[:starts_with]}")
+ * end
+ * end
+ * ```
+ */
+class GraphqlFieldResolutionMethod extends Method, HTTP::Server::RequestHandler::Range {
+ private GraphqlSchemaObjectClass schemaObjectClass;
+
+ GraphqlFieldResolutionMethod() {
+ this.getEnclosingModule() = schemaObjectClass and
+ exists(GraphqlFieldDefinitionMethodCall defn |
+ // field :foo, resolver_method: :custom_method
+ // def custom_method(...)
+ defn.getKeywordArgument("resolver_method").(SymbolLiteral).getValueText() = this.getName()
+ or
+ // field :foo
+ // def foo(...)
+ not exists(defn.getKeywordArgument("resolver_method").(SymbolLiteral)) and
+ defn.getFieldName() = this.getName()
+ )
+ }
+
+ /** Gets the method call which is the definition of the field corresponding to this resolver method. */
+ GraphqlFieldDefinitionMethodCall getDefinition() {
+ result.getKeywordArgument("resolver_method").(SymbolLiteral).getValueText() = this.getName()
+ or
+ not exists(result.getKeywordArgument("resolver_method").(SymbolLiteral)) and
+ result.getFieldName() = this.getName()
+ }
+
+ // check for a named argument the same name as a defined argument for this field
+ override Parameter getARoutedParameter() {
+ result = this.getAParameter() and
+ exists(GraphqlFieldArgumentDefinitionMethodCall argDefn |
+ argDefn.getEnclosingCallable() = this.getDefinition().getBlock() and
+ (
+ result.(KeywordParameter).hasName(argDefn.getArgumentName())
+ or
+ // TODO this will cause false positives because now *anything* in the **args
+ // param will be flagged as as RoutedParameter/RemoteFlowSource, but really
+ // only the hash keys corresponding to the defined arguments are user input
+ // others could be things defined in the `:extras` keyword argument to the `argument`
+ result instanceof HashSplatParameter // often you see `def field(**args)`
+ )
+ )
+ }
+
+ override string getFramework() { result = "GraphQL" }
+
+ /** Gets the class containing this method. */
+ GraphqlSchemaObjectClass getGraphqlClass() { result = schemaObjectClass }
+}
diff --git a/ruby/ql/test/library-tests/frameworks/GraphQL.expected b/ruby/ql/test/library-tests/frameworks/GraphQL.expected
new file mode 100644
index 00000000000..173f3846f9a
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/GraphQL.expected
@@ -0,0 +1,46 @@
+graphqlSchemaObjectClass
+| app/graphql/types/base_object.rb:2:3:4:5 | BaseObject |
+| app/graphql/types/mutation_type.rb:2:3:4:5 | MutationType |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType |
+graphqlSchemaObjectFieldDefinition
+| app/graphql/types/mutation_type.rb:2:3:4:5 | MutationType | app/graphql/types/mutation_type.rb:3:5:3:44 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:3:5:5:40 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:7:5:9:7 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:15:5:17:7 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:24:5:26:7 | call to field |
+| app/graphql/types/query_type.rb:2:3:45:5 | QueryType | app/graphql/types/query_type.rb:32:5:35:7 | call to field |
+graphqlResolveMethod
+| app/graphql/mutations/dummy.rb:9:5:12:7 | resolve |
+| app/graphql/resolvers/dummy_resolver.rb:10:5:13:7 | resolve |
+graphqlResolveMethodRoutedParameter
+| app/graphql/mutations/dummy.rb:9:5:12:7 | resolve | app/graphql/mutations/dummy.rb:9:17:9:25 | something |
+| app/graphql/resolvers/dummy_resolver.rb:10:5:13:7 | resolve | app/graphql/resolvers/dummy_resolver.rb:10:17:10:25 | something |
+graphqlLoadMethod
+| app/graphql/mutations/dummy.rb:5:5:7:7 | load_something |
+| app/graphql/resolvers/dummy_resolver.rb:6:5:8:7 | load_something |
+graphqlLoadMethodRoutedParameter
+| app/graphql/mutations/dummy.rb:5:5:7:7 | load_something | app/graphql/mutations/dummy.rb:5:24:5:25 | id |
+| app/graphql/resolvers/dummy_resolver.rb:6:5:8:7 | load_something | app/graphql/resolvers/dummy_resolver.rb:6:24:6:25 | id |
+graphqlFieldDefinitionMethodCall
+| app/graphql/types/mutation_type.rb:3:5:3:44 | call to field |
+| app/graphql/types/query_type.rb:3:5:5:40 | call to field |
+| app/graphql/types/query_type.rb:7:5:9:7 | call to field |
+| app/graphql/types/query_type.rb:15:5:17:7 | call to field |
+| app/graphql/types/query_type.rb:24:5:26:7 | call to field |
+| app/graphql/types/query_type.rb:32:5:35:7 | call to field |
+graphqlFieldResolutionMethod
+| app/graphql/types/query_type.rb:10:5:13:7 | with_arg |
+| app/graphql/types/query_type.rb:18:5:22:7 | custom_method |
+| app/graphql/types/query_type.rb:27:5:30:7 | with_splat |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg |
+graphqlFieldResolutionRoutedParameter
+| app/graphql/types/query_type.rb:10:5:13:7 | with_arg | app/graphql/types/query_type.rb:10:18:10:23 | number |
+| app/graphql/types/query_type.rb:18:5:22:7 | custom_method | app/graphql/types/query_type.rb:18:23:18:33 | blah_number |
+| app/graphql/types/query_type.rb:27:5:30:7 | with_splat | app/graphql/types/query_type.rb:27:20:27:25 | **args |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg | app/graphql/types/query_type.rb:36:34:36:37 | arg1 |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg | app/graphql/types/query_type.rb:36:41:36:46 | **rest |
+graphqlFieldResolutionDefinition
+| app/graphql/types/query_type.rb:10:5:13:7 | with_arg | app/graphql/types/query_type.rb:7:5:9:7 | call to field |
+| app/graphql/types/query_type.rb:18:5:22:7 | custom_method | app/graphql/types/query_type.rb:15:5:17:7 | call to field |
+| app/graphql/types/query_type.rb:27:5:30:7 | with_splat | app/graphql/types/query_type.rb:24:5:26:7 | call to field |
+| app/graphql/types/query_type.rb:36:5:40:7 | with_splat_and_named_arg | app/graphql/types/query_type.rb:32:5:35:7 | call to field |
diff --git a/ruby/ql/test/library-tests/frameworks/GraphQL.ql b/ruby/ql/test/library-tests/frameworks/GraphQL.ql
new file mode 100644
index 00000000000..b443d923222
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/GraphQL.ql
@@ -0,0 +1,36 @@
+private import codeql.ruby.frameworks.GraphQL
+private import codeql.ruby.AST
+
+query predicate graphqlSchemaObjectClass(GraphqlSchemaObjectClass cls) { any() }
+
+query predicate graphqlSchemaObjectFieldDefinition(
+ GraphqlSchemaObjectClass cls, GraphqlFieldDefinitionMethodCall meth
+) {
+ cls.getAFieldDefinitionMethodCall() = meth
+}
+
+query predicate graphqlResolveMethod(GraphqlResolveMethod meth) { any() }
+
+query predicate graphqlResolveMethodRoutedParameter(GraphqlResolveMethod meth, Parameter p) {
+ meth.getARoutedParameter() = p
+}
+
+query predicate graphqlLoadMethod(GraphqlLoadMethod meth) { any() }
+
+query predicate graphqlLoadMethodRoutedParameter(GraphqlLoadMethod meth, Parameter p) {
+ meth.getARoutedParameter() = p
+}
+
+query predicate graphqlFieldDefinitionMethodCall(GraphqlFieldDefinitionMethodCall cls) { any() }
+
+query predicate graphqlFieldResolutionMethod(GraphqlFieldResolutionMethod cls) { any() }
+
+query predicate graphqlFieldResolutionRoutedParameter(GraphqlFieldResolutionMethod meth, Parameter p) {
+ meth.getARoutedParameter() = p
+}
+
+query predicate graphqlFieldResolutionDefinition(
+ GraphqlFieldResolutionMethod meth, GraphqlFieldDefinitionMethodCall def
+) {
+ meth.getDefinition() = def
+}
diff --git a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
index 36fea1b31cd..039e9019886 100644
--- a/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
+++ b/ruby/ql/test/library-tests/frameworks/StandardLibrary.expected
@@ -19,6 +19,15 @@ kernelSystemCallExecutions
| CommandExecution.rb:19:1:19:59 | call to system |
| CommandExecution.rb:20:1:20:62 | call to system |
| CommandExecution.rb:21:1:21:72 | call to system |
+| app/graphql/mutations/dummy.rb:10:7:10:33 | call to system |
+| app/graphql/resolvers/dummy_resolver.rb:11:7:11:33 | call to system |
+| app/graphql/types/query_type.rb:11:7:11:30 | call to system |
+| app/graphql/types/query_type.rb:19:7:19:35 | call to system |
+| app/graphql/types/query_type.rb:20:7:20:30 | call to system |
+| app/graphql/types/query_type.rb:28:7:28:40 | call to system |
+| app/graphql/types/query_type.rb:37:7:37:28 | call to system |
+| app/graphql/types/query_type.rb:38:7:38:35 | call to system |
+| app/graphql/types/query_type.rb:43:7:43:27 | call to system |
kernelExecCallExecutions
| CommandExecution.rb:23:1:23:16 | call to exec |
| CommandExecution.rb:24:1:24:19 | call to exec |
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb
new file mode 100644
index 00000000000..0749ec0313f
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/base_mutation.rb
@@ -0,0 +1,8 @@
+module Mutations
+ class BaseMutation < GraphQL::Schema::RelayClassicMutation
+ argument_class Types::BaseArgument
+ field_class Types::BaseField
+ input_object_class Types::BaseInputObject
+ object_class Types::BaseObject
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb
new file mode 100644
index 00000000000..52f01c3d6eb
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/mutations/dummy.rb
@@ -0,0 +1,14 @@
+module Mutations
+ class Dummy < BaseMutation
+ argument :something_id, ID, required: false
+
+ def load_something(id)
+ "Something number #{id}"
+ end
+
+ def resolve(something:)
+ system("echo #{something}")
+ { success: true }
+ end
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb
new file mode 100644
index 00000000000..a51595c00a7
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/base.rb
@@ -0,0 +1,4 @@
+module Resolvers
+ class Base < GraphQL::Schema::Resolver
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb
new file mode 100644
index 00000000000..1fbc927c816
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/resolvers/dummy_resolver.rb
@@ -0,0 +1,15 @@
+module Resolvers
+ class DummyResolver < Resolvers::Base
+ type String, null: false
+ argument :something_id, ID, required: true
+
+ def load_something(id)
+ "Something number #{id}"
+ end
+
+ def resolve(something:)
+ system("echo #{something}")
+ "true"
+ end
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb
new file mode 100644
index 00000000000..c1bfdabbfee
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_argument.rb
@@ -0,0 +1,4 @@
+module Types
+ class BaseArgument < GraphQL::Schema::Argument
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb
new file mode 100644
index 00000000000..7142ef7ddb4
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_field.rb
@@ -0,0 +1,5 @@
+module Types
+ class BaseField < GraphQL::Schema::Field
+ argument_class Types::BaseArgument
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb
new file mode 100644
index 00000000000..c97c4796373
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_input_object.rb
@@ -0,0 +1,5 @@
+module Types
+ class BaseInputObject < GraphQL::Schema::InputObject
+ argument_class Types::BaseArgument
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb
new file mode 100644
index 00000000000..f25c9650044
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_interface.rb
@@ -0,0 +1,7 @@
+module Types
+ module BaseInterface
+ include GraphQL::Schema::Interface
+
+ field_class Types::BaseField
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb
new file mode 100644
index 00000000000..1f918414d98
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/base_object.rb
@@ -0,0 +1,5 @@
+module Types
+ class BaseObject < GraphQL::Schema::Object
+ field_class Types::BaseField
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb
new file mode 100644
index 00000000000..5ef19f95ae6
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/mutation_type.rb
@@ -0,0 +1,5 @@
+module Types
+ class MutationType < Types::BaseObject
+ field :dummy, mutation: Mutations::Dummy
+ end
+end
diff --git a/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb b/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb
new file mode 100644
index 00000000000..e0bc578a911
--- /dev/null
+++ b/ruby/ql/test/library-tests/frameworks/app/graphql/types/query_type.rb
@@ -0,0 +1,46 @@
+module Types
+ class QueryType < Types::BaseObject
+ field :test_field, String, null: false,
+ description: "An example field added by the generator",
+ resolver: Resolvers::DummyResolver
+
+ field :with_arg, String, null: false, description: "A field with an argument" do
+ argument :number, Int, "A number", required: true
+ end
+ def with_arg(number:)
+ system("echo #{number}")
+ number.to_s
+ end
+
+ field :with_method, String, null: false, description: "A field with a custom resolver method", resolver_method: :custom_method do
+ argument :blah_number, Int, "A number", required: true
+ end
+ def custom_method(blah_number:, number: nil)
+ system("echo #{blah_number}")
+ system("echo #{number}")
+ blah_number.to_s
+ end
+
+ field :with_splat, String, null: false, description: "A field with a double-splatted argument" do
+ argument :something, Int, "A number", required: true
+ end
+ def with_splat(**args)
+ system("echo #{args[:something]}")
+ args[:something].to_s
+ end
+
+ field :with_splat_and_named_arg, String, null: false, description: "A field with two named arguments, where the method captures the second via a hash splat param" do
+ argument :arg1, Int, "A number", required: true
+ argument :arg2, Int, "Another number", required: true
+ end
+ def with_splat_and_named_arg(arg1:, **rest)
+ system("echo #{arg1}")
+ system("echo #{rest[:arg2]}")
+ arg1.to_s
+ end
+
+ def foo(arg)
+ system("echo #{arg}")
+ end
+ end
+end
diff --git a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
index 8849322976c..6118b4b20c6 100644
--- a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
+++ b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.expected
@@ -10,6 +10,8 @@ edges
| CommandInjection.rb:6:15:6:26 | ...[...] : | CommandInjection.rb:34:39:34:51 | "grep #{...}" |
| CommandInjection.rb:46:15:46:20 | call to params : | CommandInjection.rb:46:15:46:26 | ...[...] : |
| CommandInjection.rb:46:15:46:26 | ...[...] : | CommandInjection.rb:50:24:50:36 | "echo #{...}" |
+| CommandInjection.rb:64:18:64:23 | number : | CommandInjection.rb:65:14:65:29 | "echo #{...}" |
+| CommandInjection.rb:72:23:72:33 | blah_number : | CommandInjection.rb:73:14:73:34 | "echo #{...}" |
nodes
| CommandInjection.rb:6:15:6:20 | call to params : | semmle.label | call to params : |
| CommandInjection.rb:6:15:6:26 | ...[...] : | semmle.label | ...[...] : |
@@ -24,6 +26,10 @@ nodes
| CommandInjection.rb:46:15:46:20 | call to params : | semmle.label | call to params : |
| CommandInjection.rb:46:15:46:26 | ...[...] : | semmle.label | ...[...] : |
| CommandInjection.rb:50:24:50:36 | "echo #{...}" | semmle.label | "echo #{...}" |
+| CommandInjection.rb:64:18:64:23 | number : | semmle.label | number : |
+| CommandInjection.rb:65:14:65:29 | "echo #{...}" | semmle.label | "echo #{...}" |
+| CommandInjection.rb:72:23:72:33 | blah_number : | semmle.label | blah_number : |
+| CommandInjection.rb:73:14:73:34 | "echo #{...}" | semmle.label | "echo #{...}" |
subpaths
#select
| CommandInjection.rb:7:10:7:15 | #{...} | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:7:10:7:15 | #{...} | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
@@ -35,3 +41,5 @@ subpaths
| CommandInjection.rb:33:24:33:36 | "echo #{...}" | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:33:24:33:36 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
| CommandInjection.rb:34:39:34:51 | "grep #{...}" | CommandInjection.rb:6:15:6:20 | call to params : | CommandInjection.rb:34:39:34:51 | "grep #{...}" | This command depends on $@. | CommandInjection.rb:6:15:6:20 | call to params | a user-provided value |
| CommandInjection.rb:50:24:50:36 | "echo #{...}" | CommandInjection.rb:46:15:46:20 | call to params : | CommandInjection.rb:50:24:50:36 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:46:15:46:20 | call to params | a user-provided value |
+| CommandInjection.rb:65:14:65:29 | "echo #{...}" | CommandInjection.rb:64:18:64:23 | number : | CommandInjection.rb:65:14:65:29 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:64:18:64:23 | number | a user-provided value |
+| CommandInjection.rb:73:14:73:34 | "echo #{...}" | CommandInjection.rb:72:23:72:33 | blah_number : | CommandInjection.rb:73:14:73:34 | "echo #{...}" | This command depends on $@. | CommandInjection.rb:72:23:72:33 | blah_number | a user-provided value |
diff --git a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb
index f91d36f71bd..ed9750128cc 100644
--- a/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb
+++ b/ruby/ql/test/query-tests/security/cwe-078/CommandInjection.rb
@@ -50,3 +50,41 @@ EOF
Open3.capture2("echo #{cmd}")
end
end
+
+module Types
+ class BaseObject < GraphQL::Schema::Object; end
+ class QueryType < BaseObject
+ field :test_field, String, null: false,
+ description: "An example field added by the generator",
+ resolver: Resolvers::DummyResolver
+
+ field :with_arg, String, null: false, description: "A field with an argument" do
+ argument :number, Int, "A number", required: true
+ end
+ def with_arg(number:)
+ system("echo #{number}")
+ number.to_s
+ end
+
+ field :with_method, String, null: false, description: "A field with a custom resolver method", resolver_method: :custom_method do
+ argument :blah_number, Int, "A number", required: true
+ end
+ def custom_method(blah_number:, number: nil)
+ system("echo #{blah_number}")
+ system("echo #{number}") # OK, number: is not an `argument` for this field
+ blah_number.to_s
+ end
+
+ field :with_splat, String, null: false, description: "A field with a double-splatted argument" do
+ argument :something, Int, "A number", required: true
+ end
+ def with_splat(**args)
+ system("echo #{args[:something]}")
+ args[:something].to_s
+ end
+
+ def foo(arg)
+ system("echo #{arg}") # OK, this is just a random method, not a resolver method
+ end
+ end
+end
From 982fb8f73a185c6c6e269b238cc1036a2ca5ba8d Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 18 Jan 2022 16:26:28 +0000
Subject: [PATCH 043/196] C++: Add change note.
---
.../src/change-notes/2022-01-18-improper-null-termination.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md
diff --git a/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md b/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md
new file mode 100644
index 00000000000..19d5b950037
--- /dev/null
+++ b/cpp/ql/src/change-notes/2022-01-18-improper-null-termination.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The "Potential improper null termination" (`cpp/improper-null-termination`) query now produces fewer false positive results around control flow branches and loops.
From 8eb674358628135c58692131a5db9e771bdabccf Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:22:21 +0100
Subject: [PATCH 044/196] Split out Lang2 rows
---
.../code/java/frameworks/apache/Lang.qll | 273 +-------------
.../java/frameworks/apache/Lang2Generated.qll | 336 ++++++++++++++++++
2 files changed, 337 insertions(+), 272 deletions(-)
create mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
index 45157b4993e..a2dad559bad 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
@@ -1,6 +1,7 @@
/** Definitions related to the Apache Commons Lang library. */
import java
+import Lang2Generated
private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.ExternalFlow
@@ -311,155 +312,6 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint"
]
}
}
@@ -494,58 +346,6 @@ private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
]
}
}
@@ -578,20 +378,6 @@ private class ApacheWordUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
]
}
}
@@ -617,34 +403,6 @@ private class ApacheStrTokenizerModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint"
]
}
}
@@ -658,8 +416,6 @@ private class ApacheStrLookupModel extends SummaryModelCsv {
[
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- "org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint"
]
}
}
@@ -698,33 +454,6 @@ private class ApacheStrSubstitutorModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
]
}
}
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
new file mode 100644
index 00000000000..f83a07b4985
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
@@ -0,0 +1,336 @@
+/** Definitions related to the Apache Commons Lang 2 library. */
+
+import java
+private import semmle.code.java.dataflow.ExternalFlow
+
+private class ApacheStrBuilderModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint"
+ ]
+ }
+}
+
+private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `WordUtils`.
+ */
+private class ApacheWordUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrTokenizer`.
+ */
+private class ApacheStrTokenizerModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrLookup`.
+ */
+private class ApacheStrLookupModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrSubstitutor`.
+ */
+private class ApacheStrSubstitutorModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
+ ]
+ }
+}
From 82bda6d573f2de74528e343d82b6a25afce9715f Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:23:37 +0100
Subject: [PATCH 045/196] Merge Lang2 summary models
---
.../java/frameworks/apache/Lang2Generated.qll | 64 ++-----------------
1 file changed, 6 insertions(+), 58 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
index f83a07b4985..dff115e676c 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
@@ -3,7 +3,7 @@
import java
private import semmle.code.java.dataflow.ExternalFlow
-private class ApacheStrBuilderModel extends SummaryModelCsv {
+private class ApacheCommonsLangModel extends SummaryModelCsv {
override predicate row(string row) {
row =
[
@@ -155,15 +155,7 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
"org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
@@ -215,18 +207,7 @@ private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
"org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `WordUtils`.
- */
-private class ApacheWordUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
@@ -240,18 +221,7 @@ private class ApacheWordUtilsModel extends SummaryModelCsv {
"org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrTokenizer`.
- */
-private class ApacheStrTokenizerModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
@@ -279,31 +249,9 @@ private class ApacheStrTokenizerModel extends SummaryModelCsv {
"org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrLookup`.
- */
-private class ApacheStrLookupModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrSubstitutor`.
- */
-private class ApacheStrSubstitutorModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint",
"org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
From 67b60dcf78573a390a10df1797077fdddcd55541 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:24:12 +0100
Subject: [PATCH 046/196] Sort Lang2 rows
---
.../java/frameworks/apache/Lang2Generated.qll | 344 +++++++++---------
1 file changed, 172 insertions(+), 172 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
index dff115e676c..757f28f19cf 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang2Generated.qll
@@ -7,278 +7,278 @@ private class ApacheCommonsLangModel extends SummaryModelCsv {
override predicate row(string row) {
row =
[
- "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;append;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;appendln;(org.apache.commons.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
"org.apache.commons.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
"org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;replace;(org.apache.commons.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;append;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;appendln;(org.apache.commons.text.TextStringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;TextStringBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;delete;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replace;(org.apache.commons.text.matcher.StringMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
"org.apache.commons.text;TextStringBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.text;TextStringBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.text;TextStringBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;TextStringBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.text;TextStringBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.text;TextStringBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text;TextStringBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;abbreviate;;;Argument[3];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;StringTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.text.lookup;StringLookup;true;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.text.lookup;StringLookupFactory;false;mapStringLookup;;;MapValue of Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;StringSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;replace;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.text;StringSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.text;StringSubstitutor;false;replaceIn;(org.apache.commons.text.TextStringBuilder,int,int);;Argument[-1];Argument[0];taint"
]
}
}
From 736e68820c1cc036b38ae5625078743ff0182887 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:26:34 +0100
Subject: [PATCH 047/196] Split out Lang3 models
---
.../code/java/frameworks/apache/Lang.qll | 578 +----------------
.../java/frameworks/apache/Lang3Generated.qll | 581 ++++++++++++++++++
2 files changed, 582 insertions(+), 577 deletions(-)
create mode 100644 java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
index a2dad559bad..b536539670e 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang.qll
@@ -2,6 +2,7 @@
import java
import Lang2Generated
+import Lang3Generated
private import semmle.code.java.dataflow.FlowSteps
private import semmle.code.java.dataflow.ExternalFlow
@@ -28,328 +29,6 @@ class MethodApacheSerializationUtilsDeserialize extends Method {
}
}
-/**
- * Taint-propagating models for `ArrayUtils`.
- */
-private class ApacheArrayUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;remove;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurrences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeElement;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value"
- ]
- }
-}
-
-private class ApacheStringEscapeUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStringUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;defaultString;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;deleteWhitespace;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;difference;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;firstNonBlank;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;StringUtils;false;firstNonEmpty;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;StringUtils;false;getBytes;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getCommonPrefix;;;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;remove;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeEnd;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeEndIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;ArrayElement of Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripStart;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripToEmpty;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;stripToNull;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substring;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringAfter;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringAfterLast;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringBefore;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringBeforeLast;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringBetween;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;substringsBetween;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toCodePoints;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toEncodedString;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toRootLowerCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toRootUpperCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;toString;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;trim;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;trimToEmpty;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;trimToNull;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStrBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- ]
- }
-}
-
-private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- ]
- }
-}
-
/**
* An Apache Commons-Lang StrBuilder method that returns `this`.
*/
@@ -358,258 +37,3 @@ private class ApacheStrBuilderFluentMethod extends FluentMethod {
this.getReturnType().(RefType).hasQualifiedName("org.apache.commons.lang3.text", "StrBuilder")
}
}
-
-/**
- * Taint-propagating models for `WordUtils`.
- */
-private class ApacheWordUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrTokenizer`.
- */
-private class ApacheStrTokenizerModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrLookup`.
- */
-private class ApacheStrLookupModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrSubstitutor`.
- */
-private class ApacheStrSubstitutorModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `RegexUtils`.
- */
-private class ApacheRegExUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `ObjectUtils`.
- */
-private class ApacheObjectUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- // Note all the functions annotated with `taint` flow really should have `value` flow,
- // but we don't support value-preserving varargs functions at the moment.
- "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value"
- ]
- }
-}
-
-private class ApacheToStringBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
- // The following are value-preserving steps for fluent methods:
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
- */
-private class ApachePairModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
- */
-private class ApacheTripleModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `MutableObject`.
- */
-private class ApacheMutableObjectModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
- ]
- }
-}
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
new file mode 100644
index 00000000000..1513898adf8
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
@@ -0,0 +1,581 @@
+/** Definitions related to the Apache Commons Lang 3 library. */
+
+import java
+private import semmle.code.java.dataflow.ExternalFlow
+
+/**
+ * Taint-propagating models for `ArrayUtils`.
+ */
+private class ApacheArrayUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;remove;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeAllOccurrences;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeElement;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value"
+ ]
+ }
+}
+
+private class ApacheStringEscapeUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint"
+ ]
+ }
+}
+
+private class ApacheStringUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;defaultString;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;deleteWhitespace;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;difference;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;firstNonBlank;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;StringUtils;false;firstNonEmpty;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;StringUtils;false;getBytes;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getCommonPrefix;;;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissing;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;prependIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;remove;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeEnd;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeEndIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;ArrayElement of Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceIgnoreCase;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnce;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceOnceIgnoreCase;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripStart;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripToEmpty;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;stripToNull;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substring;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringAfter;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringAfterLast;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringBefore;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringBeforeLast;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringBetween;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;substringsBetween;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toCodePoints;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toEncodedString;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toRootLowerCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toRootUpperCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;toString;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;trim;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;trimToEmpty;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;trimToNull;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint"
+ ]
+ }
+}
+
+private class ApacheStrBuilderModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
+ ]
+ }
+}
+
+private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `WordUtils`.
+ */
+private class ApacheWordUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrTokenizer`.
+ */
+private class ApacheStrTokenizerModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrLookup`.
+ */
+private class ApacheStrLookupModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `StrSubstitutor`.
+ */
+private class ApacheStrSubstitutorModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `RegexUtils`.
+ */
+private class ApacheRegExUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
+ ]
+ }
+}
+
+/**
+ * Taint-propagating models for `ObjectUtils`.
+ */
+private class ApacheObjectUtilsModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ // Note all the functions annotated with `taint` flow really should have `value` flow,
+ // but we don't support value-preserving varargs functions at the moment.
+ "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value"
+ ]
+ }
+}
+
+private class ApacheToStringBuilderModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
+ // The following are value-preserving steps for fluent methods:
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
+ */
+private class ApachePairModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
+ */
+private class ApacheTripleModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
+ ]
+ }
+}
+
+/**
+ * Value-propagating models for `MutableObject`.
+ */
+private class ApacheMutableObjectModel extends SummaryModelCsv {
+ override predicate row(string row) {
+ row =
+ [
+ "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
+ ]
+ }
+}
From e6800c877c4f856a14ac73e0c9b40a5581cdceb2 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:28:55 +0100
Subject: [PATCH 048/196] Merge Lang3 rows
---
.../java/frameworks/apache/Lang3Generated.qll | 163 +-----------------
1 file changed, 9 insertions(+), 154 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
index 1513898adf8..43c1da32177 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
@@ -3,10 +3,7 @@
import java
private import semmle.code.java.dataflow.ExternalFlow
-/**
- * Taint-propagating models for `ArrayUtils`.
- */
-private class ApacheArrayUtilsModel extends SummaryModelCsv {
+private class ApacheCommonsLang3Model extends SummaryModelCsv {
override predicate row(string row) {
row =
[
@@ -44,24 +41,8 @@ private class ApacheArrayUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value"
- ]
- }
-}
-
-private class ApacheStringEscapeUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStringUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
@@ -204,15 +185,7 @@ private class ApacheStringUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint"
- ]
- }
-}
-
-private class ApacheStrBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
@@ -287,14 +260,6 @@ private class ApacheStrBuilderModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- ]
- }
-}
-
-private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
@@ -321,17 +286,6 @@ private class ApacheStrBuilderFluentMethodsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `WordUtils`.
- */
-private class ApacheWordUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
@@ -344,17 +298,6 @@ private class ApacheWordUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrTokenizer`.
- */
-private class ApacheStrTokenizerModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
@@ -369,30 +312,8 @@ private class ApacheStrTokenizerModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrLookup`.
- */
-private class ApacheStrLookupModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `StrSubstitutor`.
- */
-private class ApacheStrSubstitutorModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
@@ -420,17 +341,6 @@ private class ApacheStrSubstitutorModel extends SummaryModelCsv {
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- ]
- }
-}
-
-/**
- * Taint-propagating models for `RegexUtils`.
- */
-private class ApacheRegExUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
"org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
@@ -439,20 +349,7 @@ private class ApacheRegExUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint"
- ]
- }
-}
-
-/**
- * Taint-propagating models for `ObjectUtils`.
- */
-private class ApacheObjectUtilsModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
- // Note all the functions annotated with `taint` flow really should have `value` flow,
- // but we don't support value-preserving varargs functions at the moment.
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
@@ -466,15 +363,7 @@ private class ApacheObjectUtilsModel extends SummaryModelCsv {
"org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value"
- ]
- }
-}
-
-private class ApacheToStringBuilderModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value",
"org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
@@ -488,22 +377,10 @@ private class ApacheToStringBuilderModel extends SummaryModelCsv {
"org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
- // The following are value-preserving steps for fluent methods:
"org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Pair`, `ImmutablePair` and `MutablePair`.
- */
-private class ApachePairModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
@@ -526,18 +403,7 @@ private class ApachePairModel extends SummaryModelCsv {
"org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `Triple`, `ImmutableTriple` and `MutableTriple`.
- */
-private class ApacheTripleModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value",
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
"org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
@@ -561,18 +427,7 @@ private class ApacheTripleModel extends SummaryModelCsv {
"org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value"
- ]
- }
-}
-
-/**
- * Value-propagating models for `MutableObject`.
- */
-private class ApacheMutableObjectModel extends SummaryModelCsv {
- override predicate row(string row) {
- row =
- [
+ "org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value",
"org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
"org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
"org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
From 9e91b805d6ce2e9a82d3c2d9681d0686492c9041 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Tue, 18 Jan 2022 16:29:26 +0100
Subject: [PATCH 049/196] Sort Lang3 models
---
.../java/frameworks/apache/Lang3Generated.qll | 394 +++++++++---------
1 file changed, 197 insertions(+), 197 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
index 43c1da32177..251f72e4c80 100644
--- a/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/apache/Lang3Generated.qll
@@ -7,23 +7,23 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
override predicate row(string row) {
row =
[
- "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;;;Argument[2];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(boolean[],boolean);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(byte[],byte);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(char[],char);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(double[],double);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(float[],float);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(int[],int);;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;add;(java.lang.Object[],java.lang.Object);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(long[],long);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;add;(short[],short);;Argument[1];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;addAll;;;ArrayElement of Argument[0..1];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;addFirst;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;addFirst;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;clone;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;get;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;get;(java.lang.Object[],int,java.lang.Object);;Argument[2];ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;insert;;;ArrayElement of Argument[1..2];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.Object[],java.lang.Class);;Argument[0];ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;nullToEmpty;(java.lang.String[]);;Argument[0];ReturnValue;value",
@@ -35,17 +35,40 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;ArrayUtils;false;removeElements;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;subarray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toArray;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapKey of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toMap;;;ArrayElement of ArrayElement of Argument[0];MapValue of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapKey of ArrayElement of Argument[0];MapKey of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toMap;;;MapValue of ArrayElement of Argument[0];MapValue of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toObject;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
- "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
"org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;Argument[1];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ArrayUtils;false;toPrimitive;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
+ "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value",
+ "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringEscapeUtils;false;escapeJson;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviate;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;abbreviate;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;abbreviateMiddle;;;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;appendIfMissing;;;Argument[0];ReturnValue;taint",
@@ -53,10 +76,10 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;appendIfMissingIgnoreCase;;;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;capitalize;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;center;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;center;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;chomp;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;chop;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;defaultIfBlank;;;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;defaultIfEmpty;;;Argument[0..1];ReturnValue;taint",
@@ -70,31 +93,31 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;getDigits;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;getIfBlank;;;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;getIfEmpty;;;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(char[],char,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(char[],char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Iterable,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],char);;ArrayElement of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String,int,int);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[],java.lang.String);;ArrayElement of Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.lang.Object[]);;ArrayElement of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,char);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.Iterator,java.lang.String);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.List,char,int,int);;Element of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;join;(java.util.List,java.lang.String,int,int);;Element of Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;joinWith;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;joinWith;;;ArrayElement of Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;left;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;leftPad;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;leftPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;lowerCase;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;mid;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;normalizeSpace;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;overlay;;;Argument[0];ReturnValue;taint",
@@ -112,14 +135,14 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;removeStart;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;removeStartIgnoreCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;repeat;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;repeat;(java.lang.String,java.lang.String,int);;Argument[1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replace;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replace;;;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceChars;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;replaceChars;(java.lang.String,java.lang.String,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceEach;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceEach;;;ArrayElement of Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;replaceEachRepeatedly;;;Argument[0];ReturnValue;taint",
@@ -137,23 +160,23 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;reverse;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;reverseDelimited;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;right;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;rightPad;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;rightPad;(java.lang.String,int,java.lang.String);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;rotate;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;split;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByCharacterType;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByCharacterTypeCamelCase;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByWholeSeparator;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitByWholeSeparatorPreserveAllTokens;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,char);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;splitPreserveAllTokens;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;strip;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;stripAccents;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;stripAll;;;ArrayElement of Argument[0];ArrayElement of ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;stripEnd;;;Argument[0];ReturnValue;taint",
@@ -179,258 +202,235 @@ private class ApacheCommonsLang3Model extends SummaryModelCsv {
"org.apache.commons.lang3;StringUtils;false;truncate;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;uncapitalize;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;unwrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String,java.util.Locale);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3;StringUtils;false;upperCase;(java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;valueOf;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrap;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,char);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3;StringUtils;false;wrapIfMissing;(java.lang.String,java.lang.String);;Argument[0..1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;append;(char[],int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.CharSequence);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;append;(java.nio.CharBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;append;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterable);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Iterator);;Element of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendAll;(Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[],int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(char[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,int,int);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer,int,int);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuffer);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder,int,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendln;(java.lang.StringBuilder);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;appendln;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,int);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String,java.lang.String);;Argument[0..1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;(java.lang.String);;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendTo;;;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterable,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Iterator,String);;Element of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;(Object[],String);;ArrayElement of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;asReader;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;asTokenizer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;build;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrBuilder;false;getChars;(char[]);;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;getChars;(int,int,char[],int);;Argument[-1];Argument[2];taint",
"org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[1];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;leftString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;midString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;readFrom;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;replace;(int,int,java.lang.String);;Argument[2];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;replace;(org.apache.commons.lang3.text.StrMatcher,java.lang.String,int,int,int);;Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[1];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[1];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;rightString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.text;StrBuilder;false;StrBuilder;(java.lang.String);;Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrBuilder;false;subSequence;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;substring;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toCharArray;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuffer;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrBuilder;false;toStringBuilder;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadLeft;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendFixedWidthPadRight;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendln;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNewLine;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendNull;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendPadding;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendSeparator;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;appendWithSeparators;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;delete;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;deleteFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;ensureCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;insert;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;minimizeCapacity;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replace;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceAll;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;replaceFirst;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;reverse;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setCharAt;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setLength;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNewLineText;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;StrBuilder;false;setNullText;;;Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.text;StrBuilder;false;trim;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;lookup;;;Argument[-1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrLookup;false;mapLookup;;;MapValue of Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[],int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(char[]);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.CharSequence);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map,java.lang.String,java.lang.String);;MapValue of Argument[1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Map);;MapValue of Argument[1];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object,java.util.Properties);;MapValue of Argument[1];ReturnValue;taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.Object);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(java.lang.StringBuffer);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replace;(org.apache.commons.lang3.text.StrBuilder);;Argument[0];ReturnValue;taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuffer);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder,int,int);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(java.lang.StringBuilder);;Argument[-1];Argument[0];taint",
"org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder,int,int);;Argument[-1];Argument[0];taint",
- "org.apache.commons.lang3;RegExUtils;false;removeAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removeFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;removePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[0];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceAll;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replaceFirst;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;RegExUtils;false;replacePattern;;;Argument[2];ReturnValue;taint",
- "org.apache.commons.lang3;ObjectUtils;false;clone;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;cloneIfPossible;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_BYTE;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;CONST_SHORT;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;defaultIfNull;;;Argument[0..1];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;firstNonNull;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;getIfNull;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;max;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;median;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;min;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;mode;;;ArrayElement of Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;requireNonEmpty;;;Argument[0];ReturnValue;value",
- "org.apache.commons.lang3;ObjectUtils;false;toString;(Object,String);;Argument[1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;toString;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.Object[]);;ArrayElement of Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[]);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object);;Argument[0..1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;(java.lang.String,java.lang.Object[],boolean);;ArrayElement of Argument[1];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;build;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;getStringBuffer;;;Argument[-1];ReturnValue;taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[0];Argument[-1];taint",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;append;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendAsObjectToString;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendSuper;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.builder;ToStringBuilder;false;appendToString;;;Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;replaceIn;(org.apache.commons.lang3.text.StrBuilder);;Argument[-1];Argument[0];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;setVariableResolver;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrSubstitutor;false;StrSubstitutor;;;MapValue of Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;clone;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getContent;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getCSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenArray;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTokenList;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;getTSVInstance;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;next;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;nextToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previous;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;previousToken;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;reset;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;StrTokenizer;;;Argument[0];Argument[-1];taint",
+ "org.apache.commons.lang3.text;StrTokenizer;false;toString;;;Argument[-1];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;capitalizeFully;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;initials;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;swapCase;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String,char[]);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;uncapitalize;(java.lang.String);;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;;;Argument[0];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean,java.lang.String);;Argument[2];ReturnValue;taint",
+ "org.apache.commons.lang3.text;WordUtils;false;wrap;(java.lang.String,int,java.lang.String,boolean);;Argument[2];ReturnValue;taint",
"org.apache.commons.lang3.tuple;ImmutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;ImmutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;left;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutablePair;false;right;;;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;ImmutableTriple;false;ImmutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
"org.apache.commons.lang3.tuple;ImmutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;MutablePair;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutablePair;false;setValue;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutableTriple;false;getLeft;;;Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;getMiddle;;;Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;getRight;;;Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];ReturnValue;value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
- "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;MutableTriple;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of ReturnValue;value",
"org.apache.commons.lang3.tuple;MutableTriple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of ReturnValue;value",
- "org.apache.commons.lang3.mutable;MutableObject;false;MutableObject;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;setValue;;;Argument[0];SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];value",
- "org.apache.commons.lang3.mutable;MutableObject;false;getValue;;;SyntheticField[org.apache.commons.lang3.mutable.MutableObject.value] of Argument[-1];ReturnValue;value"
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setLeft;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.left] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setMiddle;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.middle] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;MutableTriple;false;setRight;;;Argument[0];Field[org.apache.commons.lang3.tuple.MutableTriple.right] of Argument[-1];value",
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getKey;;;Field[org.apache.commons.lang3.tuple.MutablePair.left] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;getValue;;;Field[org.apache.commons.lang3.tuple.MutablePair.right] of Argument[-1];ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutablePair.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Pair;false;of;(java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutablePair.right] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[0];Field[org.apache.commons.lang3.tuple.ImmutableTriple.left] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[1];Field[org.apache.commons.lang3.tuple.ImmutableTriple.middle] of ReturnValue;value",
+ "org.apache.commons.lang3.tuple;Triple;false;of;(java.lang.Object,java.lang.Object,java.lang.Object);;Argument[2];Field[org.apache.commons.lang3.tuple.ImmutableTriple.right] of ReturnValue;value",
]
}
}
From d1c89562b832b309f6fcb034e1bae9e0d0266fb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Tue, 18 Jan 2022 21:45:13 +0100
Subject: [PATCH 050/196] Apply suggestions from code review
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index 9c0481702f7..a06e63d0925 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -55,10 +55,11 @@ where
) and
(
fctmp.getArgument(1).getValue().matches("%a%") or
+ fctmp.getArgument(1).getValue().matches("%w%") or
// unfortunately cannot use numeric value here because // O_APPEND is defined differently on different OSes:
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
// this may introduce false negatives
- fctmp.getArgument(1).getValueText().matches("%O_APPEND%")
+ fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT")
) and
fctmp.getNumberOfArguments() = 2 and
not fctmp.getArgument(0).getValue() = "/dev/null" and
From 3fa25168984cddda7b7313b3164b843520cb5b87 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Tue, 18 Jan 2022 21:47:55 +0100
Subject: [PATCH 051/196] Update
cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index a06e63d0925..43344b589ad 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -56,7 +56,7 @@ where
(
fctmp.getArgument(1).getValue().matches("%a%") or
fctmp.getArgument(1).getValue().matches("%w%") or
- // unfortunately cannot use numeric value here because // O_APPEND is defined differently on different OSes:
+ // unfortunately cannot use numeric value here because // O_CREAT is defined differently on different OSes:
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
// this may introduce false negatives
fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT")
From 4f7f92490a4afb01c5b3b163d5664b08feb2dbea Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Tue, 18 Jan 2022 15:02:13 +1300
Subject: [PATCH 052/196] Distinguish regex components from strings
Create a set of classes for components of regex literals,
separate from those of string literals. This allows us to special-case
components of free-spacing regexes (ones with the /x flag) to not have a
`getValueText()`.
This in turn is useful because our regex parser can't handle free-spacing
regexes, so excluding them ensures that we don't generate erroneous
ReDoS alerts.
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 88 ++++++++++++++++++-
.../lib/codeql/ruby/controlflow/CfgNodes.qll | 34 ++++++-
.../internal/ControlFlowGraphImpl.qll | 8 +-
ruby/ql/test/library-tests/ast/Ast.expected | 62 ++++++-------
.../test/library-tests/ast/ValueText.expected | 2 -
.../ast/literals/literals.expected | 73 +++++++--------
.../library-tests/ast/literals/literals.ql | 4 +
7 files changed, 193 insertions(+), 78 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 1f5350bdb33..177b771c73c 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -277,7 +277,9 @@ class StringComponent extends AstNode, TStringComponent {
class StringTextComponent extends StringComponent, TStringTextComponent {
private Ruby::Token g;
- StringTextComponent() { this = TStringTextComponent(g) }
+ StringTextComponent() {
+ this = TStringTextComponent(g) and not g.getParent() instanceof Ruby::Regex
+ }
final override string toString() { result = g.getValue() }
@@ -292,7 +294,9 @@ class StringTextComponent extends StringComponent, TStringTextComponent {
class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponent {
private Ruby::EscapeSequence g;
- StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
+ StringEscapeSequenceComponent() {
+ this = TStringEscapeSequenceComponent(g) and not g.getParent() instanceof Ruby::Regex
+ }
final override string toString() { result = g.getValue() }
@@ -308,7 +312,9 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
TStringInterpolationComponent {
private Ruby::Interpolation g;
- StringInterpolationComponent() { this = TStringInterpolationComponent(g) }
+ StringInterpolationComponent() {
+ this = TStringInterpolationComponent(g) and not g.getParent() instanceof Ruby::Regex
+ }
final override string toString() { result = "#{...}" }
@@ -319,6 +325,82 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
}
+/**
+ * The base class for a component of a regular expression literal.
+ */
+class RegExpComponent extends AstNode, TStringComponent {
+ private RegExpLiteral parent;
+
+ RegExpComponent() { toGenerated(this).getParent() = toGenerated(parent) }
+
+ string getValueText() { none() }
+}
+
+/**
+ * A component of a regex literal that is simply text.
+ *
+ * For example, the following regex literals all contain `RegExpTextComponent`
+ * components whose `getValueText()` returns `"foo"`:
+ *
+ * ```rb
+ * 'foo'
+ * "#{ bar() }foo"
+ * "foo#{ bar() } baz"
+ * ```
+ */
+class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
+ private Ruby::Token g;
+
+ RegExpTextComponent() { this = TStringTextComponent(g) and g.getParent() instanceof Ruby::Regex }
+
+ final override string toString() { result = g.getValue() }
+
+ // Exclude components that are children of a free-spacing regex.
+ // We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
+ final override string getValueText() {
+ not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and result = g.getValue()
+ }
+
+ final override string getAPrimaryQlClass() { result = "RegExpTextComponent" }
+}
+
+/**
+ * An escape sequence component of a regex literal.
+ */
+class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponent {
+ private Ruby::EscapeSequence g;
+
+ RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
+
+ final override string toString() { result = g.getValue() }
+
+ // Exclude components that are children of a free-spacing regex.
+ // We do this because `ParseRegExp.qll` cannot handle free-spacing regexes.
+ final override string getValueText() {
+ not this.getParent().(RegExpLiteral).hasFreeSpacingFlag() and result = g.getValue()
+ }
+
+ final override string getAPrimaryQlClass() { result = "RegExpEscapeSequenceComponent" }
+}
+
+/**
+ * An interpolation expression component of a regex literal.
+ */
+class RegExpInterpolationComponent extends RegExpComponent, StmtSequence,
+ TStringInterpolationComponent {
+ private Ruby::Interpolation g;
+
+ RegExpInterpolationComponent() { this = TStringInterpolationComponent(g) }
+
+ final override string toString() { result = "#{...}" }
+
+ final override Stmt getStmt(int n) { toGenerated(result) = g.getChild(n) }
+
+ final override string getValueText() { none() }
+
+ final override string getAPrimaryQlClass() { result = "RegExpInterpolationComponent" }
+}
+
/**
* A string, symbol, regexp, or subshell literal.
*/
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
index 8c35c4fc1b0..36eb0b3078f 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/CfgNodes.qll
@@ -132,6 +132,13 @@ class StringComponentCfgNode extends AstCfgNode {
string getValueText() { result = this.getNode().(StringComponent).getValueText() }
}
+/** A control-flow node that wraps a `RegExpComponent` AST expression. */
+class RegExpComponentCfgNode extends AstCfgNode {
+ RegExpComponentCfgNode() { this.getNode() instanceof RegExpComponent }
+
+ string getValueText() { result = this.getNode().(RegExpComponent).getValueText() }
+}
+
private AstNode desugar(AstNode n) {
result = n.getDesugared()
or
@@ -474,6 +481,15 @@ module ExprNodes {
final override string getValueText() { result = this.getLastStmt().getValueText() }
}
+ /** A control-flow node that wraps a `RegExpInterpolationComponent` AST expression. */
+ class RegExpInterpolationComponentCfgNode extends RegExpComponentCfgNode, StmtSequenceCfgNode {
+ RegExpInterpolationComponentCfgNode() { this.getNode() instanceof RegExpInterpolationComponent }
+
+ // If last statement in the interpolation is a constant or local variable read,
+ // attempt to look up its definition and return the definition's `getValueText()`.
+ final override string getValueText() { result = this.getLastStmt().getValueText() }
+ }
+
private class StringlikeLiteralChildMapping extends ExprChildMapping, StringlikeLiteral {
override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
}
@@ -510,11 +526,27 @@ module ExprNodes {
final override StringLiteral getExpr() { result = super.getExpr() }
}
+ private class RegExpLiteralChildMapping extends ExprChildMapping, RegExpLiteral {
+ override predicate relevantChild(AstNode n) { n = this.getComponent(_) }
+ }
+
/** A control-flow node that wraps a `RegExpLiteral` AST expression. */
class RegExpLiteralCfgNode extends ExprCfgNode {
- override RegExpLiteral e;
+ override RegExpLiteralChildMapping e;
+
+ RegExpComponentCfgNode getComponent(int n) { e.hasCfgChild(e.getComponent(n), this, result) }
final override RegExpLiteral getExpr() { result = super.getExpr() }
+
+ language[monotonicAggregates]
+ override string getValueText() {
+ result =
+ concat(RegExpComponentCfgNode c, int i |
+ c = this.getComponent(i)
+ |
+ c.getValueText() order by i
+ )
+ }
}
/** A control-flow node that wraps a `ComparisonOperation` AST expression. */
diff --git a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
index c56d1e6369d..99e6b86dd21 100644
--- a/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
+++ b/ruby/ql/lib/codeql/ruby/controlflow/internal/ControlFlowGraphImpl.qll
@@ -1351,7 +1351,13 @@ module Trees {
}
private class StringComponentTree extends LeafTree, StringComponent {
- StringComponentTree() { not this instanceof StringInterpolationComponent }
+ StringComponentTree() {
+ // Interpolations contain `StmtSequence`s, so they shouldn't be treated as leaf nodes.
+ not this instanceof StringInterpolationComponent and
+ // In the interests of brevity we treat regexes as string literals when constructing the CFG.
+ // Thus we must exclude regex interpolations here too.
+ not this instanceof RegExpInterpolationComponent
+ }
}
private class ToplevelTree extends BodyStmtTree, Toplevel {
diff --git a/ruby/ql/test/library-tests/ast/Ast.expected b/ruby/ql/test/library-tests/ast/Ast.expected
index 94b5cb5fda1..e48bc0d102f 100644
--- a/ruby/ql/test/library-tests/ast/Ast.expected
+++ b/ruby/ql/test/library-tests/ast/Ast.expected
@@ -946,7 +946,7 @@ control/cases.rb:
# 92| 0: [RegExpCharacterRange] 0-9
# 92| 0: [RegExpConstant, RegExpNormalChar] 0
# 92| 1: [RegExpConstant, RegExpNormalChar] 9
-# 92| getComponent: [StringTextComponent] .*abc[0-9]
+# 92| getComponent: [RegExpTextComponent] .*abc[0-9]
# 93| getBranch: [InClause] in ... then ...
# 93| getPattern: [RangeLiteral] _ .. _
# 93| getBegin: [IntegerLiteral] 5
@@ -1761,13 +1761,13 @@ literals/literals.rb:
# 137| 0: [RegExpConstant, RegExpNormalChar] f
# 137| 1: [RegExpConstant, RegExpNormalChar] o
# 137| 2: [RegExpConstant, RegExpNormalChar] o
-# 137| getComponent: [StringTextComponent] foo
+# 137| getComponent: [RegExpTextComponent] foo
# 138| getStmt: [RegExpLiteral] /foo/
# 138| getParsed: [RegExpSequence] foo
# 138| 0: [RegExpConstant, RegExpNormalChar] f
# 138| 1: [RegExpConstant, RegExpNormalChar] o
# 138| 2: [RegExpConstant, RegExpNormalChar] o
-# 138| getComponent: [StringTextComponent] foo
+# 138| getComponent: [RegExpTextComponent] foo
# 139| getStmt: [RegExpLiteral] /foo+\sbar\S/
# 139| getParsed: [RegExpSequence] foo+\sbar\S
# 139| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1779,10 +1779,10 @@ literals/literals.rb:
# 139| 5: [RegExpConstant, RegExpNormalChar] a
# 139| 6: [RegExpConstant, RegExpNormalChar] r
# 139| 7: [RegExpCharacterClassEscape] \S
-# 139| getComponent: [StringTextComponent] foo+
-# 139| getComponent: [StringEscapeSequenceComponent] \s
-# 139| getComponent: [StringTextComponent] bar
-# 139| getComponent: [StringEscapeSequenceComponent] \S
+# 139| getComponent: [RegExpTextComponent] foo+
+# 139| getComponent: [RegExpEscapeSequenceComponent] \s
+# 139| getComponent: [RegExpTextComponent] bar
+# 139| getComponent: [RegExpEscapeSequenceComponent] \S
# 140| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
# 140| getParsed: [RegExpSequence] foo2barbarbar
# 140| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1798,35 +1798,31 @@ literals/literals.rb:
# 140| 10: [RegExpConstant, RegExpNormalChar] b
# 140| 11: [RegExpConstant, RegExpNormalChar] a
# 140| 12: [RegExpConstant, RegExpNormalChar] r
-# 140| getComponent: [StringTextComponent] foo
-# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getComponent: [RegExpTextComponent] foo
+# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [AddExpr] ... + ...
# 140| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 140| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 140| getComponent: [StringTextComponent] bar
-# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getComponent: [RegExpTextComponent] bar
+# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [LocalVariableAccess] bar
-# 140| getComponent: [StringInterpolationComponent] #{...}
+# 140| getComponent: [RegExpInterpolationComponent] #{...}
# 140| getStmt: [ConstantReadAccess] BAR
# 141| getStmt: [RegExpLiteral] /foo/
-# 141| getParsed: [RegExpSequence] foo
-# 141| 0: [RegExpConstant, RegExpNormalChar] f
-# 141| 1: [RegExpConstant, RegExpNormalChar] o
-# 141| 2: [RegExpConstant, RegExpNormalChar] o
-# 141| getComponent: [StringTextComponent] foo
+# 141| getComponent: [RegExpTextComponent] foo
# 142| getStmt: [RegExpLiteral] //
# 143| getStmt: [RegExpLiteral] /foo/
# 143| getParsed: [RegExpSequence] foo
# 143| 0: [RegExpConstant, RegExpNormalChar] f
# 143| 1: [RegExpConstant, RegExpNormalChar] o
# 143| 2: [RegExpConstant, RegExpNormalChar] o
-# 143| getComponent: [StringTextComponent] foo
+# 143| getComponent: [RegExpTextComponent] foo
# 144| getStmt: [RegExpLiteral] /foo/
# 144| getParsed: [RegExpSequence] foo
# 144| 0: [RegExpConstant, RegExpNormalChar] f
# 144| 1: [RegExpConstant, RegExpNormalChar] o
# 144| 2: [RegExpConstant, RegExpNormalChar] o
-# 144| getComponent: [StringTextComponent] foo
+# 144| getComponent: [RegExpTextComponent] foo
# 145| getStmt: [RegExpLiteral] /foo+\sbar\S/
# 145| getParsed: [RegExpSequence] foo+\sbar\S
# 145| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1838,10 +1834,10 @@ literals/literals.rb:
# 145| 5: [RegExpConstant, RegExpNormalChar] a
# 145| 6: [RegExpConstant, RegExpNormalChar] r
# 145| 7: [RegExpCharacterClassEscape] \S
-# 145| getComponent: [StringTextComponent] foo+
-# 145| getComponent: [StringEscapeSequenceComponent] \s
-# 145| getComponent: [StringTextComponent] bar
-# 145| getComponent: [StringEscapeSequenceComponent] \S
+# 145| getComponent: [RegExpTextComponent] foo+
+# 145| getComponent: [RegExpEscapeSequenceComponent] \s
+# 145| getComponent: [RegExpTextComponent] bar
+# 145| getComponent: [RegExpEscapeSequenceComponent] \S
# 146| getStmt: [RegExpLiteral] /foo#{...}bar#{...}#{...}/
# 146| getParsed: [RegExpSequence] foo2barbarbar
# 146| 0: [RegExpConstant, RegExpNormalChar] f
@@ -1857,22 +1853,18 @@ literals/literals.rb:
# 146| 10: [RegExpConstant, RegExpNormalChar] b
# 146| 11: [RegExpConstant, RegExpNormalChar] a
# 146| 12: [RegExpConstant, RegExpNormalChar] r
-# 146| getComponent: [StringTextComponent] foo
-# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getComponent: [RegExpTextComponent] foo
+# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [AddExpr] ... + ...
# 146| getAnOperand/getLeftOperand/getReceiver: [IntegerLiteral] 1
# 146| getAnOperand/getArgument/getRightOperand: [IntegerLiteral] 1
-# 146| getComponent: [StringTextComponent] bar
-# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getComponent: [RegExpTextComponent] bar
+# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [LocalVariableAccess] bar
-# 146| getComponent: [StringInterpolationComponent] #{...}
+# 146| getComponent: [RegExpInterpolationComponent] #{...}
# 146| getStmt: [ConstantReadAccess] BAR
# 147| getStmt: [RegExpLiteral] /foo/
-# 147| getParsed: [RegExpSequence] foo
-# 147| 0: [RegExpConstant, RegExpNormalChar] f
-# 147| 1: [RegExpConstant, RegExpNormalChar] o
-# 147| 2: [RegExpConstant, RegExpNormalChar] o
-# 147| getComponent: [StringTextComponent] foo
+# 147| getComponent: [RegExpTextComponent] foo
# 150| getStmt: [StringLiteral] "abcdefghijklmnopqrstuvwxyzabcdef"
# 150| getComponent: [StringTextComponent] abcdefghijklmnopqrstuvwxyzabcdef
# 151| getStmt: [StringLiteral] "foobarfoobarfoobarfoobarfooba..."
@@ -2399,7 +2391,7 @@ operations/operations.rb:
# 65| 2: [RegExpConstant, RegExpNormalChar] o
# 65| 3: [RegExpStar] .*
# 65| 0: [RegExpDot] .
-# 65| getComponent: [StringTextComponent] foo.*
+# 65| getComponent: [RegExpTextComponent] foo.*
# 66| getStmt: [NoRegExpMatchExpr] ... !~ ...
# 66| getAnOperand/getLeftOperand/getReceiver: [LocalVariableAccess] handle
# 66| getAnOperand/getArgument/getRightOperand: [RegExpLiteral] /.*bar/
@@ -2409,7 +2401,7 @@ operations/operations.rb:
# 66| 1: [RegExpConstant, RegExpNormalChar] b
# 66| 2: [RegExpConstant, RegExpNormalChar] a
# 66| 3: [RegExpConstant, RegExpNormalChar] r
-# 66| getComponent: [StringTextComponent] .*bar
+# 66| getComponent: [RegExpTextComponent] .*bar
# 69| getStmt: [AssignAddExpr] ... += ...
# 69| getAnOperand/getLeftOperand: [LocalVariableAccess] x
# 69| getAnOperand/getRightOperand: [IntegerLiteral] 128
diff --git a/ruby/ql/test/library-tests/ast/ValueText.expected b/ruby/ql/test/library-tests/ast/ValueText.expected
index a456501c0c8..59ca6a262b0 100644
--- a/ruby/ql/test/library-tests/ast/ValueText.expected
+++ b/ruby/ql/test/library-tests/ast/ValueText.expected
@@ -552,7 +552,6 @@
| literals/literals.rb:140:12:140:12 | 1 | 1 |
| literals/literals.rb:140:20:140:22 | bar | bar |
| literals/literals.rb:140:26:140:28 | BAR | bar |
-| literals/literals.rb:141:1:141:8 | /foo/ | foo |
| literals/literals.rb:142:1:142:4 | // | |
| literals/literals.rb:143:1:143:7 | /foo/ | foo |
| literals/literals.rb:144:1:144:8 | /foo/ | foo |
@@ -563,7 +562,6 @@
| literals/literals.rb:146:14:146:14 | 1 | 1 |
| literals/literals.rb:146:22:146:24 | bar | bar |
| literals/literals.rb:146:28:146:30 | BAR | bar |
-| literals/literals.rb:147:1:147:10 | /foo/ | foo |
| literals/literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals/literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals/literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.expected b/ruby/ql/test/library-tests/ast/literals/literals.expected
index a84d52fe2b0..6c0428650f7 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.expected
+++ b/ruby/ql/test/library-tests/ast/literals/literals.expected
@@ -198,7 +198,7 @@ allLiterals
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:140:8:140:8 | 1 | IntegerLiteral | 1 |
| literals.rb:140:12:140:12 | 1 | IntegerLiteral | 1 |
-| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | foo |
+| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | |
| literals.rb:142:1:142:4 | // | RegExpLiteral | |
| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | foo |
| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | foo |
@@ -206,7 +206,7 @@ allLiterals
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | foo2barbarbar |
| literals.rb:146:10:146:10 | 1 | IntegerLiteral | 1 |
| literals.rb:146:14:146:14 | 1 | IntegerLiteral | 1 |
-| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | foo |
+| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
@@ -310,13 +310,13 @@ stringlikeLiterals
| literals.rb:138:1:138:6 | /foo/ | foo |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
-| literals.rb:141:1:141:8 | /foo/ | foo |
+| literals.rb:141:1:141:8 | /foo/ | |
| literals.rb:142:1:142:4 | // | |
| literals.rb:143:1:143:7 | /foo/ | foo |
| literals.rb:144:1:144:8 | /foo/ | foo |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar |
-| literals.rb:147:1:147:10 | /foo/ | foo |
+| literals.rb:147:1:147:10 | /foo/ | |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | abcdefghijklmnopqrstuvwxyzabcdef |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | foobarfoobarfoobarfoobarfoobarfoo |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | foobar\\\\foobar\\\\foobar\\\\foobar\\\\foobar |
@@ -387,13 +387,20 @@ regExpLiterals
| literals.rb:138:1:138:6 | /foo/ | foo | i |
| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
-| literals.rb:141:1:141:8 | /foo/ | foo | oxm |
+| literals.rb:141:1:141:8 | /foo/ | | oxm |
| literals.rb:142:1:142:4 | // | | |
| literals.rb:143:1:143:7 | /foo/ | foo | |
| literals.rb:144:1:144:8 | /foo/ | foo | i |
| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | foo+\\sbar\\S | |
| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | foo2barbarbar | |
-| literals.rb:147:1:147:10 | /foo/ | foo | mxo |
+| literals.rb:147:1:147:10 | /foo/ | | mxo |
+regExpInterpolations
+| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
+| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
+| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
+| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
+| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
+| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
symbolLiterals
| literals.rb:84:1:84:3 | :"" | |
| literals.rb:85:1:85:6 | :hello | hello |
@@ -540,30 +547,30 @@ stringComponents
| literals.rb:132:1:132:32 | `du -d #{...} #{...} #{...}` | SubshellLiteral | 5 | literals.rb:132:26:132:31 | #{...} | StringInterpolationComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 0 | literals.rb:133:4:133:9 | du -d | StringTextComponent |
| literals.rb:133:1:133:20 | `du -d #{...}` | SubshellLiteral | 1 | literals.rb:133:10:133:19 | #{...} | StringInterpolationComponent |
-| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | StringTextComponent |
-| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | 0 | literals.rb:138:2:138:4 | foo | StringTextComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:139:2:139:5 | foo+ | StringTextComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | StringEscapeSequenceComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | StringTextComponent |
-| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | StringEscapeSequenceComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | StringTextComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | StringInterpolationComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | StringTextComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | StringInterpolationComponent |
-| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | StringInterpolationComponent |
-| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | StringTextComponent |
-| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | StringTextComponent |
-| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | StringTextComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:145:4:145:7 | foo+ | StringTextComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | StringEscapeSequenceComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | StringTextComponent |
-| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | StringEscapeSequenceComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | StringTextComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | StringInterpolationComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | StringTextComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | StringInterpolationComponent |
-| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | StringInterpolationComponent |
-| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | StringTextComponent |
+| literals.rb:137:1:137:5 | /foo/ | RegExpLiteral | 0 | literals.rb:137:2:137:4 | foo | RegExpTextComponent |
+| literals.rb:138:1:138:6 | /foo/ | RegExpLiteral | 0 | literals.rb:138:2:138:4 | foo | RegExpTextComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:139:2:139:5 | foo+ | RegExpTextComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:139:6:139:7 | \\s | RegExpEscapeSequenceComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:139:8:139:10 | bar | RegExpTextComponent |
+| literals.rb:139:1:139:13 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:139:11:139:12 | \\S | RegExpEscapeSequenceComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:140:2:140:4 | foo | RegExpTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:140:5:140:14 | #{...} | RegExpInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:140:15:140:17 | bar | RegExpTextComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:140:18:140:23 | #{...} | RegExpInterpolationComponent |
+| literals.rb:140:1:140:30 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:140:24:140:29 | #{...} | RegExpInterpolationComponent |
+| literals.rb:141:1:141:8 | /foo/ | RegExpLiteral | 0 | literals.rb:141:2:141:4 | foo | RegExpTextComponent |
+| literals.rb:143:1:143:7 | /foo/ | RegExpLiteral | 0 | literals.rb:143:4:143:6 | foo | RegExpTextComponent |
+| literals.rb:144:1:144:8 | /foo/ | RegExpLiteral | 0 | literals.rb:144:4:144:6 | foo | RegExpTextComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 0 | literals.rb:145:4:145:7 | foo+ | RegExpTextComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 1 | literals.rb:145:8:145:9 | \\s | RegExpEscapeSequenceComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 2 | literals.rb:145:10:145:12 | bar | RegExpTextComponent |
+| literals.rb:145:1:145:15 | /foo+\\sbar\\S/ | RegExpLiteral | 3 | literals.rb:145:13:145:14 | \\S | RegExpEscapeSequenceComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 0 | literals.rb:146:4:146:6 | foo | RegExpTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 1 | literals.rb:146:7:146:16 | #{...} | RegExpInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 2 | literals.rb:146:17:146:19 | bar | RegExpTextComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 3 | literals.rb:146:20:146:25 | #{...} | RegExpInterpolationComponent |
+| literals.rb:146:1:146:32 | /foo#{...}bar#{...}#{...}/ | RegExpLiteral | 4 | literals.rb:146:26:146:31 | #{...} | RegExpInterpolationComponent |
+| literals.rb:147:1:147:10 | /foo/ | RegExpLiteral | 0 | literals.rb:147:4:147:6 | foo | RegExpTextComponent |
| literals.rb:150:1:150:34 | "abcdefghijklmnopqrstuvwxyzabcdef" | StringLiteral | 0 | literals.rb:150:2:150:33 | abcdefghijklmnopqrstuvwxyzabcdef | StringTextComponent |
| literals.rb:151:1:151:35 | "foobarfoobarfoobarfoobarfooba..." | StringLiteral | 0 | literals.rb:151:2:151:34 | foobarfoobarfoobarfoobarfoobarfoo | StringTextComponent |
| literals.rb:152:1:152:40 | "foobar\\\\foobar\\\\foobar\\\\fooba..." | StringLiteral | 0 | literals.rb:152:2:152:7 | foobar | StringTextComponent |
@@ -613,12 +620,6 @@ stringInterpolations
| literals.rb:132:19:132:24 | #{...} | 0 | literals.rb:132:21:132:23 | bar | LocalVariableAccess |
| literals.rb:132:26:132:31 | #{...} | 0 | literals.rb:132:28:132:30 | BAR | ConstantReadAccess |
| literals.rb:133:10:133:19 | #{...} | 0 | literals.rb:133:13:133:17 | ... - ... | SubExpr |
-| literals.rb:140:5:140:14 | #{...} | 0 | literals.rb:140:8:140:12 | ... + ... | AddExpr |
-| literals.rb:140:18:140:23 | #{...} | 0 | literals.rb:140:20:140:22 | bar | LocalVariableAccess |
-| literals.rb:140:24:140:29 | #{...} | 0 | literals.rb:140:26:140:28 | BAR | ConstantReadAccess |
-| literals.rb:146:7:146:16 | #{...} | 0 | literals.rb:146:10:146:14 | ... + ... | AddExpr |
-| literals.rb:146:20:146:25 | #{...} | 0 | literals.rb:146:22:146:24 | bar | LocalVariableAccess |
-| literals.rb:146:26:146:31 | #{...} | 0 | literals.rb:146:28:146:30 | BAR | ConstantReadAccess |
| literals.rb:158:14:158:22 | #{...} | 0 | literals.rb:158:17:158:20 | call to name | MethodCall |
| literals.rb:172:12:172:29 | #{...} | 0 | literals.rb:172:15:172:27 | call to interpolation | MethodCall |
| literals.rb:177:15:177:32 | #{...} | 0 | literals.rb:177:18:177:30 | call to interpolation | MethodCall |
diff --git a/ruby/ql/test/library-tests/ast/literals/literals.ql b/ruby/ql/test/library-tests/ast/literals/literals.ql
index 52469a35e50..0fd46abea70 100644
--- a/ruby/ql/test/library-tests/ast/literals/literals.ql
+++ b/ruby/ql/test/library-tests/ast/literals/literals.ql
@@ -23,6 +23,10 @@ query predicate regExpLiterals(RegExpLiteral l, string valueText, string flags)
stringlikeLiterals(l, valueText) and flags = l.getFlagString()
}
+query predicate regExpInterpolations(RegExpInterpolationComponent c, int i, Expr e, string eClass) {
+ e = c.getStmt(i) and eClass = e.getAPrimaryQlClass()
+}
+
query predicate symbolLiterals(SymbolLiteral l, string valueText) {
stringlikeLiterals(l, valueText)
}
From a1b0315d90b5bbe04196159ed929eb47ce088ad1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jaroslav=20Loba=C4=8Devski?=
Date: Wed, 19 Jan 2022 00:52:10 +0100
Subject: [PATCH 053/196] Update
cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
---
.../Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
index 43344b589ad..22e42d39147 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
+++ b/cpp/ql/src/experimental/Security/CWE/CWE-266/IncorrectPrivilegeAssignment.ql
@@ -59,7 +59,8 @@ where
// unfortunately cannot use numeric value here because // O_CREAT is defined differently on different OSes:
// https://github.com/red/red/blob/92feb0c0d5f91e087ab35fface6906afbf99b603/runtime/definitions.reds#L477-L491
// this may introduce false negatives
- fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT")
+ fctmp.getArgument(1).(BitwiseOrExpr).getAChild*().getValueText().matches("O_CREAT") or
+ fctmp.getArgument(1).getValueText().matches("%O_CREAT%")
) and
fctmp.getNumberOfArguments() = 2 and
not fctmp.getArgument(0).getValue() = "/dev/null" and
From f7240be13675b95fd348f618d3797bedceb21267 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 19 Jan 2022 00:09:52 +0000
Subject: [PATCH 054/196] Add changed framework coverage reports
---
.../library-coverage/coverage.csv | 222 +++++++++---------
.../library-coverage/coverage.rst | 8 +-
2 files changed, 115 insertions(+), 115 deletions(-)
diff --git a/java/documentation/library-coverage/coverage.csv b/java/documentation/library-coverage/coverage.csv
index 9576ed23eec..ac2c82d2732 100644
--- a/java/documentation/library-coverage/coverage.csv
+++ b/java/documentation/library-coverage/coverage.csv
@@ -1,111 +1,111 @@
-package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
-android.app,7,,84,,,,,,7,,,,,,,,,,,,,,,,,,13,71
-android.content,24,27,96,,,,,,16,,,,,,,,,8,,,,,,,27,,31,65
-android.database,59,,30,,,,,,,,,,,,,,,59,,,,,,,,,30,
-android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,45,15
-android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,41,81
-android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,16,,
-android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,3,,2,,
-androidx.slice,,5,88,,,,,,,,,,,,,,,,,,,,,,5,,27,61
-cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,6,
-com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,62,23
-com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,17
-com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,2,551
-com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,
-com.google.common.io,6,,73,,,,,,,,,,,,,,,,6,,,,,,,,72,1
-com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,
-com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,
-flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1
-groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,
-groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,
-jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,,
-jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23
-jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,
-jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,,
-jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,2,,,,,,,94,55
-java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-java.io,37,,31,,15,,,,,,,,,,,,,,,,22,,,,,,30,1
-java.lang,8,,56,,,,,,,,,,8,,,,,,,,,,,,,,45,11
-java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,3,7,
-java.nio,15,,4,,13,,,,,,,,,,,,,,,,2,,,,,,4,
-java.sql,7,,,,,,,,,,,,,,,,,7,,,,,,,,,,
-java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,16,414
-javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,2,,7,,
-javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,100,23
-javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,
-javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,
-javax.net.ssl,2,,,,,,,,,,,,,,,,2,,,,,,,,,,,
-javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,
-javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,21,2,
-javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,1,,
-javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,
-javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,9,,
-javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,2,,,,,,,94,55
-javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,1,,,,6,
-javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,3,,,,,,
-jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,10
-net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,5,,,,,
-ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,
-org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,6,
-org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783
-org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,17,783
-org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,,22,
-org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,
-org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,
-org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,293,131
-org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,
-org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,
-org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,220,52
-org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,
-org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,1,,2,39,
-org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,2,
-org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,18,6
-org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,2,,3,62,8
-org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,6,,,,,,,,,,
-org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,
-org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,4,4
-org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,
-org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,
-org.dom4j,20,,,,,,,,,,,,,,,,,,,,,20,,,,,,
-org.hibernate,7,,,,,,,,,,,,,,,,,7,,,,,,,,,,
-org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,
-org.jooq,1,,,,,,,,,,,,,,,,,1,,,,,,,,,,
-org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,198,38
-org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,
-org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,
-org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,2,4
-org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,26
-org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13
-org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
-org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,60,10
-org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,10,,,,,,,,,,
-org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,9,,,,,,,,,,
-org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,
-org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,,
-org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,6,,
-org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,32
-org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,87,52
-org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,13,
-org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,3,,
-org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,8,,
-org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,12,13,
-org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,
-org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,138,25
-org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,1,
-org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,3,,
-play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,4,,
-ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
-ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4,
-ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10,
-ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,48
-ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,3,
-ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35
-ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,6,4,
-ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,10,10,
-ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,35
+package,sink,source,summary,sink:bean-validation,sink:create-file,sink:groovy,sink:header-splitting,sink:information-leak,sink:intent-start,sink:jexl,sink:jndi-injection,sink:ldap,sink:logging,sink:mvel,sink:ognl-injection,sink:open-url,sink:pending-intent-sent,sink:set-hostname-verifier,sink:sql,sink:url-open-stream,sink:url-redirect,sink:write-file,sink:xpath,sink:xslt,sink:xss,source:contentprovider,source:remote,summary:taint,summary:value
+android.app,16,,103,,,,,,7,,,,,,,,9,,,,,,,,,,,18,85
+android.content,24,27,96,,,,,,16,,,,,,,,,,8,,,,,,,27,,31,65
+android.database,59,,30,,,,,,,,,,,,,,,,59,,,,,,,,,30,
+android.net,,,60,,,,,,,,,,,,,,,,,,,,,,,,,45,15
+android.os,,,122,,,,,,,,,,,,,,,,,,,,,,,,,41,81
+android.util,6,16,,,,,,,,,,,6,,,,,,,,,,,,,,16,,
+android.webkit,3,2,,,,,,,,,,,,,,,,,,,,,,,3,,2,,
+androidx.slice,2,5,88,,,,,,,,,,,,,,2,,,,,,,,,5,,27,61
+cn.hutool.core.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.esotericsoftware.kryo.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.esotericsoftware.kryo5.io,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.fasterxml.jackson.core,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+com.fasterxml.jackson.databind,,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,
+com.google.common.base,,,85,,,,,,,,,,,,,,,,,,,,,,,,,62,23
+com.google.common.cache,,,17,,,,,,,,,,,,,,,,,,,,,,,,,,17
+com.google.common.collect,,,553,,,,,,,,,,,,,,,,,,,,,,,,,2,551
+com.google.common.flogger,29,,,,,,,,,,,,29,,,,,,,,,,,,,,,,
+com.google.common.io,6,,73,,,,,,,,,,,,,,,,,6,,,,,,,,72,1
+com.opensymphony.xwork2.ognl,3,,,,,,,,,,,,,,3,,,,,,,,,,,,,,
+com.unboundid.ldap.sdk,17,,,,,,,,,,,17,,,,,,,,,,,,,,,,,
+flexjson,,,1,,,,,,,,,,,,,,,,,,,,,,,,,,1
+groovy.lang,26,,,,,26,,,,,,,,,,,,,,,,,,,,,,,
+groovy.util,5,,,,,5,,,,,,,,,,,,,,,,,,,,,,,
+jakarta.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,7,,
+jakarta.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,100,23
+jakarta.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
+jakarta.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,9,,
+jakarta.ws.rs.core,2,,149,,,,,,,,,,,,,,,,,,2,,,,,,,94,55
+java.beans,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+java.io,37,,31,,15,,,,,,,,,,,,,,,,,22,,,,,,31,
+java.lang,8,,58,,,,,,,,,,8,,,,,,,,,,,,,,,46,12
+java.net,10,3,7,,,,,,,,,,,,,10,,,,,,,,,,,3,7,
+java.nio,15,,6,,13,,,,,,,,,,,,,,,,,2,,,,,,6,
+java.sql,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,,
+java.util,34,,430,,,,,,,,,,34,,,,,,,,,,,,,,,16,414
+javax.faces.context,2,7,,,,,,,,,,,,,,,,,,,,,,,2,,7,,
+javax.json,,,123,,,,,,,,,,,,,,,,,,,,,,,,,100,23
+javax.management.remote,2,,,,,,,,,,2,,,,,,,,,,,,,,,,,,
+javax.naming,7,,,,,,,,,,6,1,,,,,,,,,,,,,,,,,
+javax.net.ssl,2,,,,,,,,,,,,,,,,,2,,,,,,,,,,,
+javax.script,1,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
+javax.servlet,4,21,2,,,,3,1,,,,,,,,,,,,,,,,,,,21,2,
+javax.validation,1,1,,1,,,,,,,,,,,,,,,,,,,,,,,1,,
+javax.ws.rs.client,1,,,,,,,,,,,,,,,1,,,,,,,,,,,,,
+javax.ws.rs.container,,9,,,,,,,,,,,,,,,,,,,,,,,,,9,,
+javax.ws.rs.core,3,,149,,,,1,,,,,,,,,,,,,,2,,,,,,,94,55
+javax.xml.transform,1,,6,,,,,,,,,,,,,,,,,,,,,1,,,,6,
+javax.xml.xpath,3,,,,,,,,,,,,,,,,,,,,,,3,,,,,,
+jodd.json,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,10
+net.sf.saxon.s9api,5,,,,,,,,,,,,,,,,,,,,,,,5,,,,,
+ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,
+org.apache.commons.codec,,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,
+org.apache.commons.collections,,,800,,,,,,,,,,,,,,,,,,,,,,,,,17,783
+org.apache.commons.collections4,,,800,,,,,,,,,,,,,,,,,,,,,,,,,17,783
+org.apache.commons.io,,,22,,,,,,,,,,,,,,,,,,,,,,,,,22,
+org.apache.commons.jexl2,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,,
+org.apache.commons.jexl3,15,,,,,,,,,15,,,,,,,,,,,,,,,,,,,
+org.apache.commons.lang3,,,424,,,,,,,,,,,,,,,,,,,,,,,,,293,131
+org.apache.commons.logging,6,,,,,,,,,,,,6,,,,,,,,,,,,,,,,
+org.apache.commons.ognl,6,,,,,,,,,,,,,,6,,,,,,,,,,,,,,
+org.apache.commons.text,,,272,,,,,,,,,,,,,,,,,,,,,,,,,220,52
+org.apache.directory.ldap.client.api,1,,,,,,,,,,,1,,,,,,,,,,,,,,,,,
+org.apache.hc.core5.function,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+org.apache.hc.core5.http,1,2,39,,,,,,,,,,,,,,,,,,,,,,1,,2,39,
+org.apache.hc.core5.net,,,2,,,,,,,,,,,,,,,,,,,,,,,,,2,
+org.apache.hc.core5.util,,,24,,,,,,,,,,,,,,,,,,,,,,,,,18,6
+org.apache.http,27,3,70,,,,,,,,,,,,,25,,,,,,,,,2,,3,62,8
+org.apache.ibatis.jdbc,6,,,,,,,,,,,,,,,,,,6,,,,,,,,,,
+org.apache.log4j,11,,,,,,,,,,,,11,,,,,,,,,,,,,,,,
+org.apache.logging.log4j,359,,8,,,,,,,,,,359,,,,,,,,,,,,,,,4,4
+org.apache.shiro.codec,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+org.apache.shiro.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
+org.codehaus.groovy.control,1,,,,,1,,,,,,,,,,,,,,,,,,,,,,,
+org.dom4j,20,,,,,,,,,,,,,,,,,,,,,,20,,,,,,
+org.hibernate,7,,,,,,,,,,,,,,,,,,7,,,,,,,,,,
+org.jboss.logging,324,,,,,,,,,,,,324,,,,,,,,,,,,,,,,
+org.jooq,1,,,,,,,,,,,,,,,,,,1,,,,,,,,,,
+org.json,,,236,,,,,,,,,,,,,,,,,,,,,,,,,198,38
+org.mvel2,16,,,,,,,,,,,,,16,,,,,,,,,,,,,,,
+org.scijava.log,13,,,,,,,,,,,,13,,,,,,,,,,,,,,,,
+org.slf4j,55,,6,,,,,,,,,,55,,,,,,,,,,,,,,,2,4
+org.springframework.beans,,,26,,,,,,,,,,,,,,,,,,,,,,,,,,26
+org.springframework.cache,,,13,,,,,,,,,,,,,,,,,,,,,,,,,,13
+org.springframework.context,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,
+org.springframework.http,14,,70,,,,,,,,,,,,,14,,,,,,,,,,,,60,10
+org.springframework.jdbc.core,10,,,,,,,,,,,,,,,,,,10,,,,,,,,,,
+org.springframework.jdbc.object,9,,,,,,,,,,,,,,,,,,9,,,,,,,,,,
+org.springframework.jndi,1,,,,,,,,,,1,,,,,,,,,,,,,,,,,,
+org.springframework.ldap,42,,,,,,,,,,28,14,,,,,,,,,,,,,,,,,
+org.springframework.security.web.savedrequest,,6,,,,,,,,,,,,,,,,,,,,,,,,,6,,
+org.springframework.ui,,,32,,,,,,,,,,,,,,,,,,,,,,,,,,32
+org.springframework.util,,,139,,,,,,,,,,,,,,,,,,,,,,,,,87,52
+org.springframework.validation,,,13,,,,,,,,,,,,,,,,,,,,,,,,,13,
+org.springframework.web.client,13,3,,,,,,,,,,,,,,13,,,,,,,,,,,3,,
+org.springframework.web.context.request,,8,,,,,,,,,,,,,,,,,,,,,,,,,8,,
+org.springframework.web.multipart,,12,13,,,,,,,,,,,,,,,,,,,,,,,,12,13,
+org.springframework.web.reactive.function.client,2,,,,,,,,,,,,,,,2,,,,,,,,,,,,,
+org.springframework.web.util,,,163,,,,,,,,,,,,,,,,,,,,,,,,,138,25
+org.xml.sax,,,1,,,,,,,,,,,,,,,,,,,,,,,,,1,
+org.xmlpull.v1,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,,
+play.mvc,,4,,,,,,,,,,,,,,,,,,,,,,,,,4,,
+ratpack.core.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,
+ratpack.core.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,6,4,
+ratpack.core.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,10,10,
+ratpack.exec,,,48,,,,,,,,,,,,,,,,,,,,,,,,,,48
+ratpack.form,,,3,,,,,,,,,,,,,,,,,,,,,,,,,3,
+ratpack.func,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35
+ratpack.handling,,6,4,,,,,,,,,,,,,,,,,,,,,,,,6,4,
+ratpack.http,,10,10,,,,,,,,,,,,,,,,,,,,,,,,10,10,
+ratpack.util,,,35,,,,,,,,,,,,,,,,,,,,,,,,,,35
diff --git a/java/documentation/library-coverage/coverage.rst b/java/documentation/library-coverage/coverage.rst
index 013af21c2da..15a17fe3b34 100644
--- a/java/documentation/library-coverage/coverage.rst
+++ b/java/documentation/library-coverage/coverage.rst
@@ -7,7 +7,7 @@ Java framework & library support
:widths: auto
Framework / library,Package,Flow sources,Taint & value steps,Sinks (total),`CWE‑022` :sub:`Path injection`,`CWE‑036` :sub:`Path traversal`,`CWE‑079` :sub:`Cross-site scripting`,`CWE‑089` :sub:`SQL injection`,`CWE‑090` :sub:`LDAP injection`,`CWE‑094` :sub:`Code injection`,`CWE‑319` :sub:`Cleartext transmission`
- Android,``android.*``,45,392,99,,,3,67,,,
+ Android,``android.*``,45,411,108,,,3,67,,,
`Apache Commons Collections `_,"``org.apache.commons.collections``, ``org.apache.commons.collections4``",,1600,,,,,,,,
`Apache Commons IO `_,``org.apache.commons.io``,,22,,,,,,,,
`Apache Commons Lang `_,``org.apache.commons.lang3``,,424,,,,,,,,
@@ -15,9 +15,9 @@ Java framework & library support
`Apache HttpComponents `_,"``org.apache.hc.core5.*``, ``org.apache.http``",5,136,28,,,3,,,,25
`Google Guava `_,``com.google.common.*``,,728,35,,6,,,,,
`JSON-java `_,``org.json``,,236,,,,,,,,
- Java Standard Library,``java.*``,3,529,111,28,,,7,,,10
+ Java Standard Library,``java.*``,3,533,111,28,,,7,,,10
Java extensions,"``javax.*``, ``jakarta.*``",54,552,32,,,4,,1,1,2
`Spring `_,``org.springframework.*``,29,472,91,,,,19,14,,29
- Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,919,,,,14,18,,
- Totals,,180,5646,1315,28,6,10,107,33,1,66
+ Others,"``androidx.slice``, ``cn.hutool.core.codec``, ``com.esotericsoftware.kryo.io``, ``com.esotericsoftware.kryo5.io``, ``com.fasterxml.jackson.core``, ``com.fasterxml.jackson.databind``, ``com.opensymphony.xwork2.ognl``, ``com.unboundid.ldap.sdk``, ``flexjson``, ``groovy.lang``, ``groovy.util``, ``jodd.json``, ``net.sf.saxon.s9api``, ``ognl``, ``org.apache.commons.codec``, ``org.apache.commons.jexl2``, ``org.apache.commons.jexl3``, ``org.apache.commons.logging``, ``org.apache.commons.ognl``, ``org.apache.directory.ldap.client.api``, ``org.apache.ibatis.jdbc``, ``org.apache.log4j``, ``org.apache.logging.log4j``, ``org.apache.shiro.codec``, ``org.apache.shiro.jndi``, ``org.codehaus.groovy.control``, ``org.dom4j``, ``org.hibernate``, ``org.jboss.logging``, ``org.jooq``, ``org.mvel2``, ``org.scijava.log``, ``org.slf4j``, ``org.xml.sax``, ``org.xmlpull.v1``, ``play.mvc``, ``ratpack.core.form``, ``ratpack.core.handling``, ``ratpack.core.http``, ``ratpack.exec``, ``ratpack.form``, ``ratpack.func``, ``ratpack.handling``, ``ratpack.http``, ``ratpack.util``",44,283,921,,,,14,18,,
+ Totals,,180,5669,1326,28,6,10,107,33,1,66
From f02aeafef137706ca0edbbf611e658ad22587718 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 09:22:01 +0100
Subject: [PATCH 055/196] Ruby: Move regex/non-regex split into `TAstNode` to
convey disjointness
---
ruby/ql/lib/codeql/ruby/ast/Literal.qll | 41 +++++++++-----------
ruby/ql/lib/codeql/ruby/ast/internal/AST.qll | 40 +++++++++++++++----
2 files changed, 51 insertions(+), 30 deletions(-)
diff --git a/ruby/ql/lib/codeql/ruby/ast/Literal.qll b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
index 177b771c73c..569871380a7 100644
--- a/ruby/ql/lib/codeql/ruby/ast/Literal.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/Literal.qll
@@ -274,12 +274,10 @@ class StringComponent extends AstNode, TStringComponent {
* "foo#{ bar() } baz"
* ```
*/
-class StringTextComponent extends StringComponent, TStringTextComponent {
+class StringTextComponent extends StringComponent, TStringTextComponentNonRegexp {
private Ruby::Token g;
- StringTextComponent() {
- this = TStringTextComponent(g) and not g.getParent() instanceof Ruby::Regex
- }
+ StringTextComponent() { this = TStringTextComponentNonRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -291,12 +289,10 @@ class StringTextComponent extends StringComponent, TStringTextComponent {
/**
* An escape sequence component of a string or string-like literal.
*/
-class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponent {
+class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequenceComponentNonRegexp {
private Ruby::EscapeSequence g;
- StringEscapeSequenceComponent() {
- this = TStringEscapeSequenceComponent(g) and not g.getParent() instanceof Ruby::Regex
- }
+ StringEscapeSequenceComponent() { this = TStringEscapeSequenceComponentNonRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -309,12 +305,10 @@ class StringEscapeSequenceComponent extends StringComponent, TStringEscapeSequen
* An interpolation expression component of a string or string-like literal.
*/
class StringInterpolationComponent extends StringComponent, StmtSequence,
- TStringInterpolationComponent {
+ TStringInterpolationComponentNonRegexp {
private Ruby::Interpolation g;
- StringInterpolationComponent() {
- this = TStringInterpolationComponent(g) and not g.getParent() instanceof Ruby::Regex
- }
+ StringInterpolationComponent() { this = TStringInterpolationComponentNonRegexp(g) }
final override string toString() { result = "#{...}" }
@@ -325,14 +319,15 @@ class StringInterpolationComponent extends StringComponent, StmtSequence,
final override string getAPrimaryQlClass() { result = "StringInterpolationComponent" }
}
+private class TRegExpComponent =
+ TStringTextComponentRegexp or TStringEscapeSequenceComponentRegexp or
+ TStringInterpolationComponentRegexp;
+
/**
* The base class for a component of a regular expression literal.
*/
-class RegExpComponent extends AstNode, TStringComponent {
- private RegExpLiteral parent;
-
- RegExpComponent() { toGenerated(this).getParent() = toGenerated(parent) }
-
+class RegExpComponent extends AstNode, TRegExpComponent {
+ /** Gets the source text for this regex component, if any. */
string getValueText() { none() }
}
@@ -348,10 +343,10 @@ class RegExpComponent extends AstNode, TStringComponent {
* "foo#{ bar() } baz"
* ```
*/
-class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
+class RegExpTextComponent extends RegExpComponent, TStringTextComponentRegexp {
private Ruby::Token g;
- RegExpTextComponent() { this = TStringTextComponent(g) and g.getParent() instanceof Ruby::Regex }
+ RegExpTextComponent() { this = TStringTextComponentRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -367,10 +362,10 @@ class RegExpTextComponent extends RegExpComponent, TStringTextComponent {
/**
* An escape sequence component of a regex literal.
*/
-class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponent {
+class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequenceComponentRegexp {
private Ruby::EscapeSequence g;
- RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponent(g) }
+ RegExpEscapeSequenceComponent() { this = TStringEscapeSequenceComponentRegexp(g) }
final override string toString() { result = g.getValue() }
@@ -387,10 +382,10 @@ class RegExpEscapeSequenceComponent extends RegExpComponent, TStringEscapeSequen
* An interpolation expression component of a regex literal.
*/
class RegExpInterpolationComponent extends RegExpComponent, StmtSequence,
- TStringInterpolationComponent {
+ TStringInterpolationComponentRegexp {
private Ruby::Interpolation g;
- RegExpInterpolationComponent() { this = TStringInterpolationComponent(g) }
+ RegExpInterpolationComponent() { this = TStringInterpolationComponentRegexp(g) }
final override string toString() { result = "#{...}" }
diff --git a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
index 58df607d4f2..4a95c54e8b3 100644
--- a/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
+++ b/ruby/ql/lib/codeql/ruby/ast/internal/AST.qll
@@ -272,10 +272,25 @@ private module Cached {
TStmtSequenceSynth(AST::AstNode parent, int i) { mkSynthChild(StmtSequenceKind(), parent, i) } or
TStringArrayLiteral(Ruby::StringArray g) or
TStringConcatenation(Ruby::ChainedString g) or
- TStringEscapeSequenceComponent(Ruby::EscapeSequence g) or
- TStringInterpolationComponent(Ruby::Interpolation g) or
- TStringTextComponent(Ruby::Token g) {
- g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent
+ TStringEscapeSequenceComponentNonRegexp(Ruby::EscapeSequence g) {
+ not g.getParent() instanceof Ruby::Regex
+ } or
+ TStringEscapeSequenceComponentRegexp(Ruby::EscapeSequence g) {
+ g.getParent() instanceof Ruby::Regex
+ } or
+ TStringInterpolationComponentNonRegexp(Ruby::Interpolation g) {
+ not g.getParent() instanceof Ruby::Regex
+ } or
+ TStringInterpolationComponentRegexp(Ruby::Interpolation g) {
+ g.getParent() instanceof Ruby::Regex
+ } or
+ TStringTextComponentNonRegexp(Ruby::Token g) {
+ (g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent) and
+ not g.getParent() instanceof Ruby::Regex
+ } or
+ TStringTextComponentRegexp(Ruby::Token g) {
+ (g instanceof Ruby::StringContent or g instanceof Ruby::HeredocContent) and
+ g.getParent() instanceof Ruby::Regex
} or
TSubExprReal(Ruby::Binary g) { g instanceof @ruby_binary_minus } or
TSubExprSynth(AST::AstNode parent, int i) { mkSynthChild(SubExprKind(), parent, i) } or
@@ -489,9 +504,12 @@ private module Cached {
n = TSplatParameter(result) or
n = TStringArrayLiteral(result) or
n = TStringConcatenation(result) or
- n = TStringEscapeSequenceComponent(result) or
- n = TStringInterpolationComponent(result) or
- n = TStringTextComponent(result) or
+ n = TStringEscapeSequenceComponentNonRegexp(result) or
+ n = TStringEscapeSequenceComponentRegexp(result) or
+ n = TStringInterpolationComponentNonRegexp(result) or
+ n = TStringInterpolationComponentRegexp(result) or
+ n = TStringTextComponentNonRegexp(result) or
+ n = TStringTextComponentRegexp(result) or
n = TSubExprReal(result) or
n = TSubshellLiteral(result) or
n = TSymbolArrayLiteral(result) or
@@ -680,6 +698,14 @@ class TIntegerLiteral = TIntegerLiteralReal or TIntegerLiteralSynth;
class TBooleanLiteral = TTrueLiteral or TFalseLiteral;
+class TStringTextComponent = TStringTextComponentNonRegexp or TStringTextComponentRegexp;
+
+class TStringEscapeSequenceComponent =
+ TStringEscapeSequenceComponentNonRegexp or TStringEscapeSequenceComponentRegexp;
+
+class TStringInterpolationComponent =
+ TStringInterpolationComponentNonRegexp or TStringInterpolationComponentRegexp;
+
class TStringComponent =
TStringTextComponent or TStringEscapeSequenceComponent or TStringInterpolationComponent;
From 08d48b9375e3bb3a8936f25ec783cf314078bd58 Mon Sep 17 00:00:00 2001
From: Harry Maclean
Date: Wed, 19 Jan 2022 21:42:46 +1300
Subject: [PATCH 056/196] Add top-level doc comment to GraphQL.qll
---
ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
index e6779b65a0f..8f153c917c1 100644
--- a/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
+++ b/ruby/ql/lib/codeql/ruby/frameworks/GraphQL.qll
@@ -1,3 +1,7 @@
+/**
+ * Provides classes for modelling the `graphql` gem.
+ */
+
private import codeql.ruby.AST
private import codeql.ruby.Concepts
private import codeql.ruby.controlflow.CfgNodes
From 2eea6ca5fd2cc36dc4b2297df2a50f4075a84fa8 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 12:50:22 +0100
Subject: [PATCH 057/196] C#: Example record type with autogenerated
Deconstruct method.
---
.../LocalScopeVariableShadowsMember.cs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs b/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs
index 18d5e86dd24..cf3062f8af6 100644
--- a/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs
+++ b/csharp/ql/test/query-tests/Bad Practices/Declarations/LocalScopeVariableShadowsMember/LocalScopeVariableShadowsMember.cs
@@ -61,4 +61,8 @@ class LocalScopeVariableShadowsMember
{
public C4(int f) { } // GOOD
}
+
+ record class GoodRecordClass(object Prop1, object Prop2) { } // GOOD
+
+ record struct GoodRecordStruct(object Prop1, object Prop2) { } // GOOD
}
From 194da454b1ae7d8edf21da035819ca61e446a855 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 12:51:01 +0100
Subject: [PATCH 058/196] C#: Add record deconstruct method as an exception
from the bad practice rule.
---
.../Declarations/LocalScopeVariableShadowsMember.ql | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql
index d3b9135df6e..766fb6d890a 100644
--- a/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql
+++ b/csharp/ql/src/Bad Practices/Declarations/LocalScopeVariableShadowsMember.ql
@@ -39,6 +39,10 @@ private predicate acceptableShadowing(LocalScopeVariable v, Member m) {
)
or
t.getAConstructor().getAParameter() = v
+ or
+ // Record types have auto-generated Deconstruct methods, which declare an out parameter
+ // with the same name as the property field(s).
+ t.(RecordType).getAMethod("Deconstruct").getAParameter() = v
)
}
From edafdc8fdef140fdfb7c360681d0f648f290cfad Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Tue, 18 Jan 2022 14:44:00 +0100
Subject: [PATCH 059/196] C#: Added change note.
---
csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md
diff --git a/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md b/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md
new file mode 100644
index 00000000000..dad981966ba
--- /dev/null
+++ b/csharp/ql/lib/change-notes/2022-01-18-local-shadows-member.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The query `cs/local-shadows-member` no longer highlights parameters of `record` types.
\ No newline at end of file
From 71ddd00a6c90fb6a48104919d325b4b717a5087e Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 11:33:03 +0100
Subject: [PATCH 060/196] C#: Workaround Roslyn bug in
`INamedTypeSymbol.TupleElements`
---
.../Entities/Types/TupleType.cs | 2 +-
.../Semmle.Extraction.CSharp/SymbolExtensions.cs | 10 ++++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
index 56db07671d7..d572fe2c267 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
private TupleType(Context cx, INamedTypeSymbol init) : base(cx, init)
{
- tupleElementsLazy = new Lazy(() => Symbol.TupleElements.Select(t => Field.Create(cx, t)).ToArray());
+ tupleElementsLazy = new Lazy(() => Symbol.TupleElementsAdjusted().Select(t => Field.Create(cx, t)).ToArray());
}
// All tuple types are "local types"
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
index 72ecf842959..80fd1ddd710 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
@@ -280,12 +280,18 @@ namespace Semmle.Extraction.CSharp
private static void BuildFunctionPointerTypeId(this IFunctionPointerTypeSymbol funptr, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined) =>
BuildFunctionPointerSignature(funptr, trapFile, s => s.BuildOrWriteId(cx, trapFile, symbolBeingDefined));
+ ///
+ /// Workaround for a Roslyn bug: https://github.com/dotnet/roslyn/issues/53943
+ ///
+ public static IEnumerable TupleElementsAdjusted(this INamedTypeSymbol type) =>
+ type.TupleElements.Where(f => f is not null && f.Type is not null);
+
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
trapFile.Write('(');
- trapFile.BuildList(",", named.TupleElements,
+ trapFile.BuildList(",", named.TupleElementsAdjusted(),
f =>
{
trapFile.Write((f.CorrespondingTupleField ?? f).Name);
@@ -464,7 +470,7 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('(');
trapFile.BuildList(
",",
- namedType.TupleElements.Select(f => f.Type),
+ namedType.TupleElementsAdjusted().Select(f => f.Type),
t => t.BuildDisplayName(cx, trapFile));
trapFile.Write(")");
return;
From d467725ccd49569219311dc457f2125cd8001248 Mon Sep 17 00:00:00 2001
From: Henry Mercer
Date: Wed, 19 Jan 2022 12:08:33 +0000
Subject: [PATCH 061/196] JS: Bump ML-powered query packs to v0.0.5
---
.../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +-
.../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
index 4042feb4c70..963899246f7 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-experimental-atm-lib
-version: 0.0.4
+version: 0.0.5
extractor: javascript
library: true
groups:
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
index 2a0dd62d1f8..9fb0fc7ad93 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
@@ -1,6 +1,6 @@
name: codeql/javascript-experimental-atm-queries
language: javascript
-version: 0.0.4
+version: 0.0.5
suites: codeql-suites
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
groups:
From 974a8b1a9a830253db88a23055e336e9fe68bad0 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Jan 2022 12:21:58 +0000
Subject: [PATCH 062/196] C++: Add a test case.
---
.../tests/CleartextTransmission.expected | 4 ++++
.../CWE/CWE-311/semmle/tests/test3.cpp | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index 354ccf9eb53..aacd539c18b 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -84,6 +84,7 @@ edges
| test3.cpp:350:9:350:16 | password | test3.cpp:352:16:352:23 | password |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password |
+| test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
@@ -195,6 +196,8 @@ nodes
| test3.cpp:352:16:352:23 | password | semmle.label | password |
| test3.cpp:353:4:353:18 | call to decrypt_inplace | semmle.label | call to decrypt_inplace |
| test3.cpp:353:20:353:27 | password | semmle.label | password |
+| test3.cpp:366:8:366:15 | password | semmle.label | password |
+| test3.cpp:368:15:368:22 | password | semmle.label | password |
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
@@ -226,3 +229,4 @@ subpaths
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
+| test3.cpp:368:3:368:6 | call to recv | test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:366:8:366:15 | password | password |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index 15e314566d1..2b8fa14a917 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -356,3 +356,21 @@ void test_loops()
}
}
}
+
+void DoDisguisedOperation(char *buffer, size_t size);
+void SecureZeroBuffer(char *buffer, size_t size);
+
+void test_securezero()
+{
+ {
+ char password[256];
+
+ recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted [FALSE POSITIVE]
+
+ DoDisguisedOperation(password, 256); // decryption (disguised)
+
+ // ...
+
+ SecureZeroBuffer(password, 256); // evidence we may have been doing decryption
+ }
+}
From d77ba020f9d0dfc7cfd9717be775a6068073013f Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 6 Dec 2021 16:44:13 +0000
Subject: [PATCH 063/196] C++: Support more routines as proof-of-encryption in
cpp/cleartext-transmission.
---
.../src/Security/CWE/CWE-311/CleartextTransmission.ql | 11 ++++++++---
.../semmle/tests/CleartextTransmission.expected | 5 ++++-
.../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +-
3 files changed, 13 insertions(+), 5 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
index 401ffc1b9d6..393bef5ccdc 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
@@ -147,13 +147,18 @@ class NetworkRecv extends NetworkSendRecv {
}
/**
- * An expression that is an argument or return value from an encryption or
- * decryption call.
+ * An expression that is an argument or return value from an encryption /
+ * decryption call. This is quite inclusive to minimize false positives, for
+ * example `SecureZeroMemory` is not an encryption routine but a clue that
+ * encryption may be present.
*/
class Encrypted extends Expr {
Encrypted() {
exists(FunctionCall fc |
- fc.getTarget().getName().toLowerCase().regexpMatch(".*(crypt|encode|decode).*") and
+ fc.getTarget()
+ .getName()
+ .toLowerCase()
+ .regexpMatch(".*(crypt|encode|decode|hash|securezero).*") and
(
this = fc or
this = fc.getAnArgument()
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index aacd539c18b..bc82a6b2c80 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -85,6 +85,8 @@ edges
| test3.cpp:350:9:350:16 | password | test3.cpp:353:4:353:18 | call to decrypt_inplace |
| test3.cpp:350:9:350:16 | password | test3.cpp:353:20:353:27 | password |
| test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password |
+| test3.cpp:366:8:366:15 | password | test3.cpp:374:3:374:18 | call to SecureZeroBuffer |
+| test3.cpp:366:8:366:15 | password | test3.cpp:374:20:374:27 | password |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:21:48:27 | call to encrypt |
| test.cpp:41:23:41:43 | cleartext password! | test.cpp:48:29:48:39 | thePassword |
| test.cpp:66:23:66:43 | cleartext password! | test.cpp:76:21:76:27 | call to encrypt |
@@ -198,6 +200,8 @@ nodes
| test3.cpp:353:20:353:27 | password | semmle.label | password |
| test3.cpp:366:8:366:15 | password | semmle.label | password |
| test3.cpp:368:15:368:22 | password | semmle.label | password |
+| test3.cpp:374:3:374:18 | call to SecureZeroBuffer | semmle.label | call to SecureZeroBuffer |
+| test3.cpp:374:20:374:27 | password | semmle.label | password |
| test.cpp:41:23:41:43 | cleartext password! | semmle.label | cleartext password! |
| test.cpp:48:21:48:27 | call to encrypt | semmle.label | call to encrypt |
| test.cpp:48:29:48:39 | thePassword | semmle.label | thePassword |
@@ -229,4 +233,3 @@ subpaths
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:341:4:341:7 | call to recv | test3.cpp:339:9:339:16 | password | test3.cpp:341:16:341:23 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:339:9:339:16 | password | password |
-| test3.cpp:368:3:368:6 | call to recv | test3.cpp:366:8:366:15 | password | test3.cpp:368:15:368:22 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:366:8:366:15 | password | password |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index 2b8fa14a917..ede9e9c0349 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -365,7 +365,7 @@ void test_securezero()
{
char password[256];
- recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted [FALSE POSITIVE]
+ recv(val(), password, 256, val()); // GOOD: password is (probably) encrypted
DoDisguisedOperation(password, 256); // decryption (disguised)
From c8509cc382fa8630214344894da1707ffa97db85 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 5 Jan 2022 11:54:38 +0100
Subject: [PATCH 064/196] C#: Introduce extractor mode to identify DBs created
with `codeql test run`
---
.../ExtractorOptions.cs | 65 ++++++-------------
.../Semmle.Extraction.CIL.Driver/Program.cs | 7 +-
.../Semmle.Extraction.CIL/Analyser.cs | 10 +--
.../Entities/PdbSourceFile.cs | 2 +-
.../extractor/Semmle.Extraction.CIL/Tuples.cs | 2 +-
.../Entities/Assembly.cs | 2 +-
.../Entities/Attribute.cs | 2 +-
.../Entities/CachedSymbol.cs | 2 +-
.../Entities/Expressions/Invocation.cs | 2 +-
.../Semmle.Extraction.CSharp/Entities/File.cs | 2 +-
.../PreprocessorDirective.cs | 2 +-
.../Entities/Types/NamedType.cs | 2 +-
.../Extractor/Analyser.cs | 2 +-
.../Extractor/StandaloneAnalyser.cs | 2 +-
.../Extractor/TracingAnalyser.cs | 4 +-
.../Populators/TypeContainerVisitor.cs | 2 +-
.../Semmle.Extraction.CSharp/Tuples.cs | 2 +-
csharp/extractor/Semmle.Extraction/Context.cs | 2 +-
.../Semmle.Extraction/Extractor/Extractor.cs | 2 +-
.../Extractor/ExtractorMode.cs | 16 +++++
.../Extractor/StandaloneExtractor.cs | 8 ++-
.../Extractor/TracingExtractor.cs | 9 ++-
csharp/extractor/Semmle.Extraction/Options.cs | 14 +++-
csharp/ql/lib/semmle/code/csharp/File.qll | 14 +++-
24 files changed, 97 insertions(+), 80 deletions(-)
create mode 100644 csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs
diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
index 75405d562fe..d5e783ac0a0 100644
--- a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
@@ -6,6 +6,7 @@ using System.Reflection.Metadata;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Globalization;
+using Semmle.Util;
using Semmle.Util.Logging;
namespace Semmle.Extraction.CIL.Driver
@@ -169,18 +170,14 @@ namespace Semmle.Extraction.CIL.Driver
///
/// Parses the command line and collates a list of DLLs/EXEs to extract.
///
- internal class ExtractorOptions
+ internal class ExtractorOptions : CommonOptions
{
private readonly AssemblyList assemblyList = new AssemblyList();
public ExtractorOptions(string[] args)
{
- Verbosity = Verbosity.Info;
- Threads = System.Environment.ProcessorCount;
PDB = true;
- TrapCompression = TrapWriter.CompressionMode.Gzip;
-
- ParseArgs(args);
+ this.ParseArguments(args);
AddFrameworkDirectories(false);
@@ -203,12 +200,6 @@ namespace Semmle.Extraction.CIL.Driver
AddDirectory(RuntimeEnvironment.GetRuntimeDirectory(), extractAll);
}
- public Verbosity Verbosity { get; private set; }
- public bool NoCache { get; private set; }
- public int Threads { get; private set; }
- public bool PDB { get; private set; }
- public TrapWriter.CompressionMode TrapCompression { get; private set; }
-
private void AddFileOrDirectory(string path)
{
path = Path.GetFullPath(path);
@@ -237,43 +228,25 @@ namespace Semmle.Extraction.CIL.Driver
///
public IEnumerable MissingReferences => assemblyList.MissingReferences;
- private void ParseArgs(string[] args)
+ public override bool HandleFlag(string flag, bool value)
{
- foreach (var arg in args)
+ switch (flag)
{
- if (arg == "--verbose")
- {
- Verbosity = Verbosity.All;
- }
- else if (arg == "--silent")
- {
- Verbosity = Verbosity.Off;
- }
- else if (arg.StartsWith("--verbosity:"))
- {
- Verbosity = (Verbosity)int.Parse(arg.Substring(12));
- }
- else if (arg == "--dotnet")
- {
- AddFrameworkDirectories(true);
- }
- else if (arg == "--nocache")
- {
- NoCache = true;
- }
- else if (arg.StartsWith("--threads:"))
- {
- Threads = int.Parse(arg.Substring(10));
- }
- else if (arg == "--no-pdb")
- {
- PDB = false;
- }
- else
- {
- AddFileOrDirectory(arg);
- }
+ case "dotnet":
+ if (value)
+ AddFrameworkDirectories(true);
+ return true;
+ default:
+ return base.HandleFlag(flag, value);
}
}
+
+ public override bool HandleArgument(string argument)
+ {
+ AddFileOrDirectory(argument);
+ return true;
+ }
+
+ public override void InvalidArgument(string argument) { }
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs
index 940cd647ed8..9e72f560854 100644
--- a/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/Program.cs
@@ -20,11 +20,11 @@ namespace Semmle.Extraction.CIL.Driver
Console.WriteLine(" path A directory/dll/exe to analyze");
}
- private static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression)
+ private static void ExtractAssembly(Layout layout, string assemblyPath, ILogger logger, CommonOptions options)
{
var sw = new Stopwatch();
sw.Start();
- Analyser.ExtractCIL(layout, assemblyPath, logger, nocache, extractPdbs, trapCompression, out _, out _);
+ Analyser.ExtractCIL(layout, assemblyPath, logger, options, out _, out _);
sw.Stop();
logger.Log(Severity.Info, " {0} ({1})", assemblyPath, sw.Elapsed);
}
@@ -43,8 +43,7 @@ namespace Semmle.Extraction.CIL.Driver
var actions = options.AssembliesToExtract
.Select(asm => asm.Filename)
- .Select(filename =>
- () => ExtractAssembly(layout, filename, logger, options.NoCache, options.PDB, options.TrapCompression))
+ .Select(filename => () => ExtractAssembly(layout, filename, logger, options))
.ToArray();
foreach (var missingRef in options.MissingReferences)
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs b/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs
index d93d7eb7dc7..e78843148af 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Analyser.cs
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL
/// Whether to extract PDBs.
/// The path of the trap file.
/// Whether the file was extracted (false=cached).
- public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, bool nocache, bool extractPdbs, TrapWriter.CompressionMode trapCompression, out string trapFile, out bool extracted)
+ public static void ExtractCIL(Layout layout, string assemblyPath, ILogger logger, CommonOptions options, out string trapFile, out bool extracted)
{
trapFile = "";
extracted = false;
@@ -33,14 +33,14 @@ namespace Semmle.Extraction.CIL
{
var canonicalPathCache = CanonicalPathCache.Create(logger, 1000);
var pathTransformer = new PathTransformer(canonicalPathCache);
- var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer);
+ var extractor = new TracingExtractor(assemblyPath, logger, pathTransformer, options);
var transformedAssemblyPath = pathTransformer.Transform(assemblyPath);
var project = layout.LookupProjectOrDefault(transformedAssemblyPath);
- using var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), trapCompression, discardDuplicates: true);
+ using var trapWriter = project.CreateTrapWriter(logger, transformedAssemblyPath.WithSuffix(".cil"), options.TrapCompression, discardDuplicates: true);
trapFile = trapWriter.TrapFile;
- if (nocache || !System.IO.File.Exists(trapFile))
+ if (!options.Cache || !System.IO.File.Exists(trapFile))
{
- ExtractCIL(extractor, trapWriter, extractPdbs);
+ ExtractCIL(extractor, trapWriter, options.PDB);
extracted = true;
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs
index 45623b3ceeb..29eb7d118ff 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/PdbSourceFile.cs
@@ -25,7 +25,7 @@ namespace Semmle.Extraction.CIL.Entities
else
Context.TrapWriter.Archive(TransformedPath, text);
- yield return Tuples.file_extraction_mode(this, 2);
+ yield return Tuples.file_extraction_mode(this, Context.Extractor.Mode | ExtractorMode.Pdb);
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs
index d58647aba77..44519f45468 100644
--- a/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL/Tuples.cs
@@ -206,7 +206,7 @@ namespace Semmle.Extraction.CIL
internal static Tuple files(File file, string fullName) =>
new Tuple("files", file, fullName);
- internal static Tuple file_extraction_mode(File file, int mode) =>
+ internal static Tuple file_extraction_mode(File file, ExtractorMode mode) =>
new Tuple("file_extraction_mode", file, mode);
internal static Tuple folders(Folder folder, string path) =>
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs
index 9555fabec4f..043f8dbf664 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Assembly.cs
@@ -64,7 +64,7 @@ namespace Semmle.Extraction.CSharp.Entities
public static Assembly CreateOutputAssembly(Context cx)
{
- if (cx.Extractor.Standalone)
+ if (cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
throw new InternalError("Attempting to create the output assembly in standalone extraction mode");
return AssemblyConstructorFactory.Instance.CreateEntity(cx, outputAssemblyCacheKey, null);
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs
index 7e7fc39aab8..a1b976c4a6c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Attribute.cs
@@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities
if (attributeSyntax is not null)
{
- if (!Context.Extractor.Standalone)
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
{
trapFile.attribute_location(this, Assembly.CreateOutputAssembly(Context));
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs
index 378bda881f7..e03f945175b 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/CachedSymbol.cs
@@ -85,7 +85,7 @@ namespace Semmle.Extraction.CSharp.Entities
{
// Some built in operators lack locations, so loc is null.
yield return Context.CreateLocation(ReportingLocation);
- if (!Context.Extractor.Standalone && loc.Kind == LocationKind.SourceFile)
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) && loc.Kind == LocationKind.SourceFile)
yield return Assembly.CreateOutputAssembly(Context);
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs
index a50b68f75b7..1af93bfe25c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs
@@ -129,7 +129,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
.Where(method => method.Parameters.Length >= Syntax.ArgumentList.Arguments.Count)
.Where(method => method.Parameters.Count(p => !p.HasExplicitDefaultValue) <= Syntax.ArgumentList.Arguments.Count);
- return Context.Extractor.Standalone ?
+ return Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) ?
candidates.FirstOrDefault() :
candidates.SingleOrDefault();
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs
index fae77b033ad..5d43a7f89d3 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/File.cs
@@ -61,7 +61,7 @@ namespace Semmle.Extraction.CSharp.Entities
}
}
- trapFile.file_extraction_mode(this, Context.Extractor.Standalone ? 1 : 0);
+ trapFile.file_extraction_mode(this, Context.Extractor.Mode);
}
private bool IsPossiblyTextFile()
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs
index dba00d61207..a5337bf836c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/PreprocessorDirective.cs
@@ -16,7 +16,7 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.preprocessor_directive_active(this, Symbol.IsActive);
trapFile.preprocessor_directive_location(this, Context.CreateLocation(ReportingLocation));
- if (!Context.Extractor.Standalone)
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
{
var compilation = Compilation.Create(Context);
trapFile.preprocessor_directive_compilation(this, compilation);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs
index 06c6ccee9a8..e412aa7809d 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs
@@ -108,7 +108,7 @@ namespace Semmle.Extraction.CSharp.Entities
foreach (var l in GetLocations(Symbol))
yield return Context.CreateLocation(l);
- if (!Context.Extractor.Standalone && Symbol.DeclaringSyntaxReferences.Any())
+ if (!Context.Extractor.Mode.HasFlag(ExtractorMode.Standalone) && Symbol.DeclaringSyntaxReferences.Any())
yield return Assembly.CreateOutputAssembly(Context);
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs
index 907948f2408..336a76ffbdc 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/Analyser.cs
@@ -178,7 +178,7 @@ namespace Semmle.Extraction.CSharp
{
var stopwatch = new Stopwatch();
stopwatch.Start();
- CIL.Analyser.ExtractCIL(layout, r.FilePath!, Logger, !options.Cache, options.PDB, options.TrapCompression, out var trapFile, out var extracted);
+ CIL.Analyser.ExtractCIL(layout, r.FilePath!, Logger, options, out var trapFile, out var extracted);
stopwatch.Stop();
ReportProgress(r.FilePath, trapFile, stopwatch.Elapsed, extracted ? AnalysisAction.Extracted : AnalysisAction.UpToDate);
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs
index 23661234f98..9173ab35217 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/StandaloneAnalyser.cs
@@ -15,7 +15,7 @@ namespace Semmle.Extraction.CSharp
{
compilation = compilationIn;
layout = new Layout();
- extractor = new StandaloneExtractor(Logger, PathTransformer);
+ extractor = new StandaloneExtractor(Logger, PathTransformer, options);
this.options = options;
LogExtractorInfo(Extraction.Extractor.Version);
SetReferencePaths();
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
index 133148723fa..4c15d053a93 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor/TracingAnalyser.cs
@@ -49,7 +49,7 @@ namespace Semmle.Extraction.CSharp
this.layout = new Layout();
this.options = options;
this.compilation = compilation;
- this.extractor = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer);
+ this.extractor = new TracingExtractor(GetOutputName(compilation, commandLineArguments), Logger, PathTransformer, options);
LogDiagnostics();
SetReferencePaths();
@@ -188,7 +188,7 @@ namespace Semmle.Extraction.CSharp
{
get
{
- return extractor is null || extractor.Standalone || compilation is null ? Enumerable.Empty() :
+ return extractor is null || extractor.Mode.HasFlag(ExtractorMode.Standalone) || compilation is null ? Enumerable.Empty() :
compilation.
GetDiagnostics().
Where(e => e.Severity >= DiagnosticSeverity.Error && !errorsToIgnore.Contains(e.Id));
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs
index f49a57398ea..0b60fd4fcf0 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Populators/TypeContainerVisitor.cs
@@ -82,7 +82,7 @@ namespace Semmle.Extraction.CSharp.Populators
public override void VisitAttributeList(AttributeListSyntax node)
{
- if (Cx.Extractor.Standalone)
+ if (Cx.Extractor.Mode.HasFlag(ExtractorMode.Standalone))
return;
var outputAssembly = Assembly.CreateOutputAssembly(Cx);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
index 028a0259a55..e4b2c3ef8df 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs
@@ -451,7 +451,7 @@ namespace Semmle.Extraction.CSharp
internal static void locations_mapped(this System.IO.TextWriter trapFile, NonGeneratedSourceLocation l1, Location l2) =>
trapFile.WriteTuple("locations_mapped", l1, l2);
- internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, int mode) =>
+ internal static void file_extraction_mode(this System.IO.TextWriter trapFile, Entities.File file, ExtractorMode mode) =>
trapFile.WriteTuple("file_extraction_mode", file, mode);
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Context.cs b/csharp/extractor/Semmle.Extraction/Context.cs
index 99da916d294..2cc1ca440b0 100644
--- a/csharp/extractor/Semmle.Extraction/Context.cs
+++ b/csharp/extractor/Semmle.Extraction/Context.cs
@@ -400,7 +400,7 @@ namespace Semmle.Extraction
private void ReportError(InternalError error)
{
- if (!Extractor.Standalone)
+ if (!Extractor.Mode.HasFlag(ExtractorMode.Standalone))
throw error;
ExtractionError(error);
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs
index a40c12d7eee..b16022181df 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/Extractor.cs
@@ -8,7 +8,7 @@ namespace Semmle.Extraction
///
public abstract class Extractor
{
- public abstract bool Standalone { get; }
+ public abstract ExtractorMode Mode { get; }
///
/// Creates a new extractor instance for one compilation unit.
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs b/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs
new file mode 100644
index 00000000000..52ef15f52d4
--- /dev/null
+++ b/csharp/extractor/Semmle.Extraction/Extractor/ExtractorMode.cs
@@ -0,0 +1,16 @@
+using System;
+
+namespace Semmle.Extraction
+{
+ ///
+ /// The mode in which a file is extracted.
+ ///
+ [Flags]
+ public enum ExtractorMode
+ {
+ None = 0,
+ Standalone = 1,
+ Pdb = 2,
+ QlTest = 4,
+ }
+}
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
index 7d4df42ef29..43cf706b306 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
@@ -4,15 +4,19 @@ namespace Semmle.Extraction
{
public class StandaloneExtractor : Extractor
{
- public override bool Standalone => true;
+ private readonly ExtractorMode mode;
+ public override ExtractorMode Mode => mode;
///
/// Creates a new extractor instance for one compilation unit.
///
/// The object used for logging.
/// The object used for path transformations.
- public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer) : base(logger, pathTransformer)
+ public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
+ mode = ExtractorMode.Standalone;
+ if (options.QlTest)
+ mode |= ExtractorMode.QlTest;
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
index eb92f35ad6e..4d764f77a11 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
@@ -4,8 +4,8 @@ namespace Semmle.Extraction
{
public class TracingExtractor : Extractor
{
- public override bool Standalone => false;
-
+ private readonly ExtractorMode mode;
+ public override ExtractorMode Mode => mode;
public string OutputPath { get; }
///
@@ -14,9 +14,12 @@ namespace Semmle.Extraction
/// The name of the output DLL/EXE, or null if not specified (standalone extraction).
/// The object used for logging.
/// The object used for path transformations.
- public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer) : base(logger, pathTransformer)
+ public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
OutputPath = outputPath;
+ mode = ExtractorMode.None;
+ if (options.QlTest)
+ mode |= ExtractorMode.QlTest;
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Options.cs b/csharp/extractor/Semmle.Extraction/Options.cs
index fffe3c88b4b..fe1c9b33fff 100644
--- a/csharp/extractor/Semmle.Extraction/Options.cs
+++ b/csharp/extractor/Semmle.Extraction/Options.cs
@@ -37,13 +37,18 @@ namespace Semmle.Extraction
///
/// Whether to extract PDB information.
///
- public bool PDB { get; private set; } = false;
+ public bool PDB { get; set; } = false;
///
/// Whether "fast extraction mode" has been enabled.
///
public bool Fast { get; private set; } = false;
+ ///
+ /// Whether extraction is done using `codeql test run`.
+ ///
+ public bool QlTest { get; private set; } = false;
+
///
/// The compression algorithm used for trap files.
///
@@ -70,6 +75,10 @@ namespace Semmle.Extraction
{
switch (flag)
{
+ case "silent":
+ if (value)
+ Verbosity = Verbosity.Off;
+ return true;
case "verbose":
Verbosity = value ? Verbosity.Debug : Verbosity.Error;
return true;
@@ -90,6 +99,9 @@ namespace Semmle.Extraction
CIL = !value;
Fast = value;
return true;
+ case "qltest":
+ QlTest = value;
+ return true;
case "brotli":
TrapCompression = value ? TrapWriter.CompressionMode.Brotli : TrapWriter.CompressionMode.Gzip;
return true;
diff --git a/csharp/ql/lib/semmle/code/csharp/File.qll b/csharp/ql/lib/semmle/code/csharp/File.qll
index f0ee0d6ca7f..5fc0d29e0b6 100644
--- a/csharp/ql/lib/semmle/code/csharp/File.qll
+++ b/csharp/ql/lib/semmle/code/csharp/File.qll
@@ -218,7 +218,12 @@ class File extends Container, @file {
* A source file can come from a PDB and from regular extraction
* in the same snapshot.
*/
- predicate isPdbSourceFile() { file_extraction_mode(this, 2) }
+ predicate isPdbSourceFile() {
+ exists(int i |
+ file_extraction_mode(this, i) and
+ i.bitAnd(2) = 2
+ )
+ }
}
/**
@@ -228,5 +233,10 @@ class SourceFile extends File {
SourceFile() { this.fromSource() }
/** Holds if the file was extracted without building the source code. */
- predicate extractedStandalone() { file_extraction_mode(this, 1) }
+ predicate extractedStandalone() {
+ exists(int i |
+ file_extraction_mode(this, i) and
+ i.bitAnd(1) = 1
+ )
+ }
}
From 4f90b45dd788e2d945e76cc66d4959f7063ae779 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 10:14:44 +0100
Subject: [PATCH 065/196] C#: Address review comments
---
.../Semmle.Extraction.CIL.Driver/ExtractorOptions.cs | 3 +--
.../Semmle.Extraction/Extractor/StandaloneExtractor.cs | 9 +++++----
.../Semmle.Extraction/Extractor/TracingExtractor.cs | 9 +++++----
csharp/extractor/Semmle.Extraction/Options.cs | 2 +-
4 files changed, 12 insertions(+), 11 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
index d5e783ac0a0..773d43e40f0 100644
--- a/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
+++ b/csharp/extractor/Semmle.Extraction.CIL.Driver/ExtractorOptions.cs
@@ -176,8 +176,7 @@ namespace Semmle.Extraction.CIL.Driver
public ExtractorOptions(string[] args)
{
- PDB = true;
- this.ParseArguments(args);
+ this.ParseArguments(args.Append("--pdb").ToArray());
AddFrameworkDirectories(false);
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
index 43cf706b306..4244e34795a 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/StandaloneExtractor.cs
@@ -4,8 +4,7 @@ namespace Semmle.Extraction
{
public class StandaloneExtractor : Extractor
{
- private readonly ExtractorMode mode;
- public override ExtractorMode Mode => mode;
+ public override ExtractorMode Mode { get; }
///
/// Creates a new extractor instance for one compilation unit.
@@ -14,9 +13,11 @@ namespace Semmle.Extraction
/// The object used for path transformations.
public StandaloneExtractor(ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
- mode = ExtractorMode.Standalone;
+ Mode = ExtractorMode.Standalone;
if (options.QlTest)
- mode |= ExtractorMode.QlTest;
+ {
+ Mode |= ExtractorMode.QlTest;
+ }
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
index 4d764f77a11..d43dd891bbe 100644
--- a/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
+++ b/csharp/extractor/Semmle.Extraction/Extractor/TracingExtractor.cs
@@ -4,8 +4,7 @@ namespace Semmle.Extraction
{
public class TracingExtractor : Extractor
{
- private readonly ExtractorMode mode;
- public override ExtractorMode Mode => mode;
+ public override ExtractorMode Mode { get; }
public string OutputPath { get; }
///
@@ -17,9 +16,11 @@ namespace Semmle.Extraction
public TracingExtractor(string outputPath, ILogger logger, PathTransformer pathTransformer, CommonOptions options) : base(logger, pathTransformer)
{
OutputPath = outputPath;
- mode = ExtractorMode.None;
+ Mode = ExtractorMode.None;
if (options.QlTest)
- mode |= ExtractorMode.QlTest;
+ {
+ Mode |= ExtractorMode.QlTest;
+ }
}
}
}
diff --git a/csharp/extractor/Semmle.Extraction/Options.cs b/csharp/extractor/Semmle.Extraction/Options.cs
index fe1c9b33fff..3ec033c144d 100644
--- a/csharp/extractor/Semmle.Extraction/Options.cs
+++ b/csharp/extractor/Semmle.Extraction/Options.cs
@@ -37,7 +37,7 @@ namespace Semmle.Extraction
///
/// Whether to extract PDB information.
///
- public bool PDB { get; set; } = false;
+ public bool PDB { get; private set; } = false;
///
/// Whether "fast extraction mode" has been enabled.
From d7cd1cf0b9bdc1be77d978822be954397e7291b9 Mon Sep 17 00:00:00 2001
From: Michael Nebel
Date: Wed, 19 Jan 2022 13:50:02 +0100
Subject: [PATCH 066/196] C#: Address review comments.
---
.../PreprocessorDirectives/LineDirective.cs | 18 +++++++-----------
.../LineOrSpanDirective.cs | 7 ++++++-
.../LineSpanDirective.cs | 11 +++++------
.../ql/lib/semmle/code/csharp/Preprocessor.qll | 6 ++++--
4 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
index d4075a6f4a9..8f28b97155c 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineDirective.cs
@@ -8,22 +8,18 @@ namespace Semmle.Extraction.CSharp.Entities
internal class LineDirective : LineOrSpanDirective
{
private LineDirective(Context cx, LineDirectiveTriviaSyntax trivia)
- : base(cx, trivia)
+ : base(cx, trivia, trivia.Line.Kind() switch
+ {
+ SyntaxKind.DefaultKeyword => LineDirectiveKind.Default,
+ SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden,
+ SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric,
+ _ => throw new InternalError(trivia, "Unhandled line token kind")
+ })
{
}
protected override void PopulatePreprocessor(TextWriter trapFile)
{
- var type = Symbol.Line.Kind() switch
- {
- SyntaxKind.DefaultKeyword => LineDirectiveKind.Default,
- SyntaxKind.HiddenKeyword => LineDirectiveKind.Hidden,
- SyntaxKind.NumericLiteralToken => LineDirectiveKind.Numeric,
- _ => throw new InternalError(Symbol, "Unhandled line token kind")
- };
-
- trapFile.directive_lines(this, type);
-
if (Symbol.Line.IsKind(SyntaxKind.NumericLiteralToken))
{
var value = (int)Symbol.Line.Value!;
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
index 546e1571596..20b9ff22a0b 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineOrSpanDirective.cs
@@ -15,13 +15,18 @@ namespace Semmle.Extraction.CSharp.Entities
internal abstract class LineOrSpanDirective : PreprocessorDirective where T : LineOrSpanDirectiveTriviaSyntax
{
- protected LineOrSpanDirective(Context cx, T trivia)
+ private readonly LineDirectiveKind kind;
+
+ protected LineOrSpanDirective(Context cx, T trivia, LineDirectiveKind k)
: base(cx, trivia)
{
+ kind = k;
}
protected override void PopulatePreprocessor(TextWriter trapFile)
{
+ trapFile.directive_lines(this, kind);
+
if (!string.IsNullOrWhiteSpace(Symbol.File.ValueText))
{
var file = File.Create(Context, Symbol.File.ValueText);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
index 7d8396d7b04..9f21204731e 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/PreprocessorDirectives/LineSpanDirective.cs
@@ -8,25 +8,24 @@ namespace Semmle.Extraction.CSharp.Entities
internal class LineSpanDirective : LineOrSpanDirective
{
private LineSpanDirective(Context cx, LineSpanDirectiveTriviaSyntax trivia)
- : base(cx, trivia) { }
+ : base(cx, trivia, LineDirectiveKind.Span) { }
+
public static LineSpanDirective Create(Context cx, LineSpanDirectiveTriviaSyntax line) =>
LineSpanDirectiveFactory.Instance.CreateEntity(cx, line, line);
protected override void PopulatePreprocessor(TextWriter trapFile)
{
- trapFile.directive_lines(this, LineDirectiveKind.Span);
-
var startLine = (int)Symbol.Start.Line.Value!;
var startColumn = (int)Symbol.Start.Character.Value!;
var endLine = (int)Symbol.End.Line.Value!;
var endColumn = (int)Symbol.End.Character.Value!;
trapFile.directive_line_span(this, startLine, startColumn, endLine, endColumn);
- var offset = Symbol.CharacterOffset.Value;
- if (offset is not null)
+ if (Symbol.CharacterOffset.Value is int offset)
{
- trapFile.directive_line_offset(this, (int)offset);
+ trapFile.directive_line_offset(this, offset);
}
+
base.PopulatePreprocessor(trapFile);
}
diff --git a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
index ac6408440e8..604e43d18b8 100644
--- a/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
+++ b/csharp/ql/lib/semmle/code/csharp/Preprocessor.qll
@@ -208,7 +208,9 @@ class HiddenLineDirective extends LineDirective {
override string getAPrimaryQlClass() { result = "HiddenLineDirective" }
}
-abstract private class NumericOrSpanLineDirective extends LineDirective {
+private class NumericOrSpanLineDirective extends LineDirective {
+ NumericOrSpanLineDirective() { directive_lines(this, [2, 3]) }
+
/** Gets the referenced file of this directive. */
File getReferencedFile() { directive_line_file(this, result) }
}
@@ -234,7 +236,7 @@ class SpanLineDirective extends NumericOrSpanLineDirective {
/** Gets the offset of this directive. */
int getOffset() { directive_line_offset(this, result) }
- /** Gets the span of this directive. */
+ /** Holds if the specified start and end positions match this SpanLineDirective. */
predicate span(int startLine, int startColumn, int endLine, int endColumn) {
directive_line_span(this, startLine, startColumn, endLine, endColumn)
}
From 9c2d961ae55a9db6f12a1304a520a2d16cdd3aaa Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Mon, 11 Oct 2021 11:17:36 +0100
Subject: [PATCH 067/196] C++: Fix another expression of stdin / stdout we see
in practice.
---
.../Security/CWE/CWE-311/CleartextTransmission.ql | 14 ++++++++++++--
.../semmle/tests/CleartextTransmission.expected | 3 ---
.../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +-
3 files changed, 13 insertions(+), 6 deletions(-)
diff --git a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
index 393bef5ccdc..e2f3742cd2d 100644
--- a/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
+++ b/cpp/ql/src/Security/CWE/CWE-311/CleartextTransmission.ql
@@ -105,8 +105,8 @@ class Recv extends SendRecv instanceof RemoteFlowSourceFunction {
* practice it usually isn't very important which query reports a result as
* long as its reported exactly once.
*
- * We do exclude function calls that specify a constant socket, which is
- * likely to mean standard input, standard output or a similar channel.
+ * We do exclude function calls that specify an apparently constant socket,
+ * which is likely to mean standard input, standard output or a similar channel.
*/
abstract class NetworkSendRecv extends FunctionCall {
SendRecv target;
@@ -125,6 +125,16 @@ abstract class NetworkSendRecv extends FunctionCall {
v.getInitializer().getExpr() instanceof Literal and
g = globalValueNumber(v.getAnAccess())
)
+ or
+ // result of a function call with literal inputs (likely constant)
+ exists(FunctionCall fc |
+ forex(Expr arg |
+ arg = fc.getAnArgument() |
+ arg instanceof Literal
+ ) and
+ g = globalValueNumber(fc)
+ )
+ // (this is far from exhaustive)
)
)
}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index bc82a6b2c80..298edcb0e71 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -37,7 +37,6 @@ edges
| test3.cpp:214:8:214:15 | password | test3.cpp:217:30:217:37 | password |
| test3.cpp:214:8:214:15 | password | test3.cpp:219:15:219:26 | password_ptr |
| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr |
-| test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password |
| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password |
@@ -147,7 +146,6 @@ nodes
| test3.cpp:217:30:217:37 | password | semmle.label | password |
| test3.cpp:219:15:219:26 | password_ptr | semmle.label | password_ptr |
| test3.cpp:225:34:225:41 | password | semmle.label | password |
-| test3.cpp:227:22:227:29 | password | semmle.label | password |
| test3.cpp:228:26:228:33 | password | semmle.label | password |
| test3.cpp:239:7:239:14 | password | semmle.label | password |
| test3.cpp:241:8:241:15 | password | semmle.label | password |
@@ -225,7 +223,6 @@ subpaths
| test3.cpp:140:3:140:6 | call to send | test3.cpp:129:39:129:47 | password1 | test3.cpp:140:15:140:17 | ptr | This operation transmits 'ptr', which may contain unencrypted sensitive data from $@ | test3.cpp:129:39:129:47 | password1 | password1 |
| test3.cpp:146:3:146:6 | call to send | test3.cpp:126:9:126:23 | global_password | test3.cpp:146:15:146:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:126:9:126:23 | global_password | global_password |
| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password |
-| test3.cpp:227:2:227:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:227:22:227:29 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index ede9e9c0349..ed52bcfbe8c 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -224,7 +224,7 @@ int get_socket(int from);
void test_more_stdio(const char *password)
{
- send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output [FALSE POSITIVE]
+ send(get_socket(1), password, 128, val()); // GOOD: `getsocket(1)` is probably standard output
send(get_socket(val()), password, 128, val()); // BAD
}
From 330b4c3704c59729227717421500e427c3f14743 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Tue, 12 Oct 2021 14:04:51 +0100
Subject: [PATCH 068/196] C++: Generalize hasSocketInput a little to include
fgets and friends.
---
.../semmle/code/cpp/models/implementations/Gets.qll | 2 ++
.../semmle/code/cpp/models/interfaces/FlowSource.qll | 10 ++++++----
.../semmle/tests/CleartextTransmission.expected | 3 ---
.../Security/CWE/CWE-311/semmle/tests/test3.cpp | 2 +-
4 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll
index 407c11834e5..c2dcce138c8 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Gets.qll
@@ -65,4 +65,6 @@ private class GetsFunction extends DataFlowFunction, TaintFunction, ArrayFunctio
}
override predicate hasArrayOutput(int bufParam) { bufParam = 0 }
+
+ override predicate hasSocketInput(FunctionInput input) { input.isParameter(2) }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll
index d454257ea86..6b0a257d6f9 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/interfaces/FlowSource.qll
@@ -20,8 +20,9 @@ abstract class RemoteFlowSourceFunction extends Function {
abstract predicate hasRemoteFlowSource(FunctionOutput output, string description);
/**
- * Holds if remote data from this source comes from a socket described by
- * `input`. There is no result if a socket is not specified.
+ * Holds if remote data from this source comes from a socket or stream
+ * described by `input`. There is no result if none is specified by a
+ * parameter.
*/
predicate hasSocketInput(FunctionInput input) { none() }
}
@@ -59,8 +60,9 @@ abstract class RemoteFlowSinkFunction extends Function {
abstract predicate hasRemoteFlowSink(FunctionInput input, string description);
/**
- * Holds if data put into this sink is transmitted through a socket described
- * by `input`. There is no result if a socket is not specified.
+ * Holds if data put into this sink is transmitted through a socket or stream
+ * described by `input`. There is no result if none is specified by a
+ * parameter.
*/
predicate hasSocketInput(FunctionInput input) { none() }
}
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
index 298edcb0e71..0cba8223956 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/CleartextTransmission.expected
@@ -39,7 +39,6 @@ edges
| test3.cpp:217:18:217:28 | call to rtn_encrypt | test3.cpp:219:15:219:26 | password_ptr |
| test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password |
| test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password |
-| test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:254:15:254:23 | password1 |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:3:256:19 | call to decrypt_to_buffer |
| test3.cpp:252:8:252:16 | password1 | test3.cpp:256:21:256:29 | password1 |
@@ -149,7 +148,6 @@ nodes
| test3.cpp:228:26:228:33 | password | semmle.label | password |
| test3.cpp:239:7:239:14 | password | semmle.label | password |
| test3.cpp:241:8:241:15 | password | semmle.label | password |
-| test3.cpp:242:8:242:15 | password | semmle.label | password |
| test3.cpp:252:8:252:16 | password1 | semmle.label | password1 |
| test3.cpp:252:24:252:32 | password2 | semmle.label | password2 |
| test3.cpp:254:15:254:23 | password1 | semmle.label | password1 |
@@ -225,7 +223,6 @@ subpaths
| test3.cpp:159:3:159:6 | call to send | test3.cpp:152:29:152:36 | password | test3.cpp:159:15:159:20 | buffer | This operation transmits 'buffer', which may contain unencrypted sensitive data from $@ | test3.cpp:152:29:152:36 | password | password |
| test3.cpp:228:2:228:5 | call to send | test3.cpp:225:34:225:41 | password | test3.cpp:228:26:228:33 | password | This operation transmits 'password', which may contain unencrypted sensitive data from $@ | test3.cpp:225:34:225:41 | password | password |
| test3.cpp:241:2:241:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:241:8:241:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
-| test3.cpp:242:2:242:6 | call to fgets | test3.cpp:239:7:239:14 | password | test3.cpp:242:8:242:15 | password | This operation receives into 'password', which may put unencrypted sensitive data into $@ | test3.cpp:239:7:239:14 | password | password |
| test3.cpp:272:3:272:6 | call to send | test3.cpp:268:19:268:26 | password | test3.cpp:272:15:272:18 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:268:19:268:26 | password | password |
| test3.cpp:295:2:295:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:295:14:295:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
| test3.cpp:300:2:300:5 | call to send | test3.cpp:308:58:308:66 | password2 | test3.cpp:300:14:300:17 | data | This operation transmits 'data', which may contain unencrypted sensitive data from $@ | test3.cpp:308:58:308:66 | password2 | password2 |
diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
index ed52bcfbe8c..65882bf4be2 100644
--- a/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
+++ b/cpp/ql/test/query-tests/Security/CWE/CWE-311/semmle/tests/test3.cpp
@@ -239,7 +239,7 @@ void test_fgets(FILE *stream)
char password[128];
fgets(password, 128, stream); // BAD
- fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input [FALSE POSITIVE]
+ fgets(password, 128, STDIN_STREAM); // GOOD: `STDIN_STREAM` is probably standard input
}
void encrypt_to_buffer(const char *input, char* output);
From acfd593eb417aae1c11ccbe69e1f2b2abe82eaf5 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Jan 2022 12:49:02 +0000
Subject: [PATCH 069/196] C++: Change note.
---
cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md
diff --git a/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md b/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md
new file mode 100644
index 00000000000..4d89ad2eeaf
--- /dev/null
+++ b/cpp/ql/src/change-notes/2022-01-19-cleartext-transmission.md
@@ -0,0 +1,4 @@
+---
+category: minorAnalysis
+---
+* The "Cleartext transmission of sensitive information" (`cpp/cleartext-transmission`) query has been improved in several ways to reduce false positive results.
\ No newline at end of file
From 023049479933aa2341dc7b4771a5a4827f599195 Mon Sep 17 00:00:00 2001
From: Geoffrey White <40627776+geoffw0@users.noreply.github.com>
Date: Wed, 19 Jan 2022 13:07:55 +0000
Subject: [PATCH 070/196] C++: Expand QLDoc comment.
---
.../Likely Bugs/Memory Management/ImproperNullTermination.ql | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
index f51c47cf70e..025e50b246f 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
+++ b/cpp/ql/src/Likely Bugs/Memory Management/ImproperNullTermination.ql
@@ -24,8 +24,8 @@ DeclStmt declWithNoInit(LocalVariable v) {
}
/**
- * Flow from a buffer that is not not null terminated to a sink that requires
- * null termination.
+ * Control flow reachability from a buffer that is not not null terminated to a
+ * sink that requires null termination.
*/
class ImproperNullTerminationReachability extends StackVariableReachabilityWithReassignment {
ImproperNullTerminationReachability() { this = "ImproperNullTerminationReachability" }
From dacb33d1dd0aa68c56fa0b2e5043ff1730990606 Mon Sep 17 00:00:00 2001
From: Tom Hvitved
Date: Wed, 19 Jan 2022 14:12:21 +0100
Subject: [PATCH 071/196] C#: Adjust Roslyn workaround
---
.../Entities/TypeMention.cs | 6 +++-
.../Entities/Types/TupleType.cs | 14 ++++++---
.../SymbolExtensions.cs | 31 +++++++++++++------
.../Semmle.Extraction/TrapExtensions.cs | 18 +++++++++--
4 files changed, 52 insertions(+), 17 deletions(-)
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs
index 08a1fa3eb0f..b23ba8ced26 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/TypeMention.cs
@@ -90,7 +90,11 @@ namespace Semmle.Extraction.CSharp.Entities
var tts = (TupleTypeSyntax)syntax;
var tt = (TupleType)type;
Emit(trapFile, loc ?? syntax.GetLocation(), parent, type);
- tts.Elements.Zip(tt.TupleElements, (s, t) => Create(Context, s.Type, this, t.Type)).Enumerate();
+ foreach (var (s, t) in tts.Elements.Zip(tt.TupleElements, (s, t) => (s, t?.Type)))
+ {
+ if (t is not null)
+ Create(Context, s.Type, this, t);
+ }
return;
case SyntaxKind.GenericName:
Emit(trapFile, loc ?? syntax.GetLocation(), parent, type);
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
index d572fe2c267..f25016b6f59 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs
@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
private TupleType(Context cx, INamedTypeSymbol init) : base(cx, init)
{
- tupleElementsLazy = new Lazy(() => Symbol.TupleElementsAdjusted().Select(t => Field.Create(cx, t)).ToArray());
+ tupleElementsLazy = new Lazy(() => Symbol.GetTupleElementsMaybeNull().Select(t => t is null ? null : Field.Create(cx, t)).ToArray());
}
// All tuple types are "local types"
@@ -47,7 +47,10 @@ namespace Semmle.Extraction.CSharp.Entities
var index = 0;
foreach (var element in TupleElements)
- trapFile.tuple_element(this, index++, element);
+ {
+ if (element is not null)
+ trapFile.tuple_element(this, index++, element);
+ }
// Note: symbol.Locations seems to be very inconsistent
// about what locations are available for a tuple type.
@@ -56,9 +59,10 @@ namespace Semmle.Extraction.CSharp.Entities
trapFile.type_location(this, Context.CreateLocation(l));
}
- private readonly Lazy tupleElementsLazy;
- public Field[] TupleElements => tupleElementsLazy.Value;
+ private readonly Lazy tupleElementsLazy;
+ public Field?[] TupleElements => tupleElementsLazy.Value;
- public override IEnumerable TypeMentions => TupleElements.Select(e => e.Type);
+ public override IEnumerable TypeMentions =>
+ TupleElements.OfType().Select(e => e.Type);
}
}
diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
index 80fd1ddd710..26a104286a8 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs
@@ -283,20 +283,27 @@ namespace Semmle.Extraction.CSharp
///
/// Workaround for a Roslyn bug: https://github.com/dotnet/roslyn/issues/53943
///
- public static IEnumerable TupleElementsAdjusted(this INamedTypeSymbol type) =>
- type.TupleElements.Where(f => f is not null && f.Type is not null);
+ public static IEnumerable GetTupleElementsMaybeNull(this INamedTypeSymbol type) =>
+ type.TupleElements;
private static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, EscapingTextWriter trapFile, ISymbol symbolBeingDefined, bool constructUnderlyingTupleType)
{
if (!constructUnderlyingTupleType && named.IsTupleType)
{
trapFile.Write('(');
- trapFile.BuildList(",", named.TupleElementsAdjusted(),
- f =>
+ trapFile.BuildList(",", named.GetTupleElementsMaybeNull(),
+ (i, f) =>
{
- trapFile.Write((f.CorrespondingTupleField ?? f).Name);
- trapFile.Write(":");
- f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
+ if (f is null)
+ {
+ trapFile.Write($"null({i})");
+ }
+ else
+ {
+ trapFile.Write((f.CorrespondingTupleField ?? f).Name);
+ trapFile.Write(":");
+ f.Type.BuildOrWriteId(cx, trapFile, symbolBeingDefined, constructUnderlyingTupleType: false);
+ }
}
);
trapFile.Write(")");
@@ -470,8 +477,14 @@ namespace Semmle.Extraction.CSharp
trapFile.Write('(');
trapFile.BuildList(
",",
- namedType.TupleElementsAdjusted().Select(f => f.Type),
- t => t.BuildDisplayName(cx, trapFile));
+ namedType.GetTupleElementsMaybeNull(),
+ (i, f) =>
+ {
+ if (f is null)
+ trapFile.Write($"null({i})");
+ else
+ f.Type.BuildDisplayName(cx, trapFile);
+ });
trapFile.Write(")");
return;
}
diff --git a/csharp/extractor/Semmle.Extraction/TrapExtensions.cs b/csharp/extractor/Semmle.Extraction/TrapExtensions.cs
index e1343019335..5c65e41f0ab 100644
--- a/csharp/extractor/Semmle.Extraction/TrapExtensions.cs
+++ b/csharp/extractor/Semmle.Extraction/TrapExtensions.cs
@@ -232,19 +232,33 @@ namespace Semmle.Extraction
/// The list of items.
/// The action on each item.
/// The original trap builder (fluent interface).
- public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action)
+ public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action)
where T1 : TextWriter
{
var first = true;
+ var i = 0;
foreach (var item in items)
{
if (first)
first = false;
else
trapFile.Write(separator);
- action(item);
+ action(i++, item);
}
return trapFile;
}
+
+ ///
+ /// Builds a trap builder using a separator and an action for each item in the list.
+ ///
+ /// The type of the items.
+ /// The trap builder to append to.
+ /// The separator string (e.g. ",")
+ /// The list of items.
+ /// The action on each item.
+ /// The original trap builder (fluent interface).
+ public static T1 BuildList(this T1 trapFile, string separator, IEnumerable items, Action action)
+ where T1 : TextWriter =>
+ trapFile.BuildList(separator, items, (_, item) => action(item));
}
}
From e4203a41098121f35f544f6ee32e9d3f9053ec2d Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 19 Jan 2022 14:26:34 +0100
Subject: [PATCH 072/196] add CWE-471 to the prototype-pollution queries
---
.../ql/src/Security/CWE-915/PrototypePollutingAssignment.ql | 1 +
javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql | 1 +
2 files changed, 2 insertions(+)
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql
index 0557b575adb..2b916426169 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingAssignment.ql
@@ -13,6 +13,7 @@
* external/cwe/cwe-079
* external/cwe/cwe-094
* external/cwe/cwe-400
+ * external/cwe/cwe-471
* external/cwe/cwe-915
*/
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
index b279c6cbe12..f3143d1cf06 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingFunction.ql
@@ -12,6 +12,7 @@
* external/cwe/cwe-079
* external/cwe/cwe-094
* external/cwe/cwe-400
+ * external/cwe/cwe-471
* external/cwe/cwe-915
*/
From b27d315ff4215a1b48c20130adb1e0aa6d93bc72 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Wed, 19 Jan 2022 13:30:27 +0000
Subject: [PATCH 073/196] Ruby: add an example of `protect_from_forgery with:
:exception`
---
.../cwe-352/railsapp/app/controllers/articles_controller.rb | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
index 2a0037f4b25..6b1d1411a39 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
@@ -1,5 +1,9 @@
class ArticlesController < ApplicationController
- prepend_before_action :user_authored_article?, only: [:delete_authored_article]
+ prepend_before_action :user_authored_article?, only: [:delete_authored_article, :change_title]
+
+ # GOOD: `with: :exception` provides more effective CSRF protection than
+ # `with: :null_session` or `with: :reset_session`.
+ protect_from_forgery with: :exception, only: [:change_title]
def delete_authored_article
article.destroy
From 45ed5a806c04bcfb0194e1b16e34015b73057743 Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Wed, 19 Jan 2022 13:37:28 +0000
Subject: [PATCH 074/196] Ruby: changenote for rb/csrf-protection-disabled
enhancement
---
.../src/change-notes/2022-01-19-csrf-protection-weakened.md | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md
diff --git a/ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md b/ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md
new file mode 100644
index 00000000000..55477a11cec
--- /dev/null
+++ b/ruby/ql/src/change-notes/2022-01-19-csrf-protection-weakened.md
@@ -0,0 +1,5 @@
+---
+category: minorAnalysis
+---
+lgtm,codescanning
+* The query `rb/csrf-protection-disabled` has been extended to find calls to the Rails method `protect_from_forgery` that may weaken CSRF protection.
From 0aab670b17eb710825bd77c8379e157bd524d1fc Mon Sep 17 00:00:00 2001
From: Alex Ford
Date: Wed, 19 Jan 2022 13:47:00 +0000
Subject: [PATCH 075/196] Ruby: add missing example rails action
---
.../cwe-352/railsapp/app/controllers/articles_controller.rb | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
index 6b1d1411a39..e4b43e00e7a 100644
--- a/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
+++ b/ruby/ql/test/query-tests/security/cwe-352/railsapp/app/controllers/articles_controller.rb
@@ -9,6 +9,11 @@ class ArticlesController < ApplicationController
article.destroy
end
+ def change_title
+ article.title = params[:article_title]
+ article.save!
+ end
+
def article
@article ||= Article.find(params[:article_id])
end
From cb9e14f54410a184eeea94792ea712df136e8d12 Mon Sep 17 00:00:00 2001
From: Erik Krogh Kristensen
Date: Wed, 19 Jan 2022 14:54:57 +0100
Subject: [PATCH 076/196] add cwe-471 to js/prototype-pollution
---
.../ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql | 1 +
1 file changed, 1 insertion(+)
diff --git a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
index f74699dcfed..e3cebbc3f7c 100644
--- a/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
+++ b/javascript/ql/src/Security/CWE-915/PrototypePollutingMergeCall.ql
@@ -13,6 +13,7 @@
* external/cwe/cwe-079
* external/cwe/cwe-094
* external/cwe/cwe-400
+ * external/cwe/cwe-471
* external/cwe/cwe-915
*/
From f0645a34b97cfc63158476b70821011e26b31f48 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 19 Jan 2022 14:06:40 +0000
Subject: [PATCH 077/196] Remove security-severity tag instead
This leaves the Java query in the same state as its C# cousin.
---
java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql | 2 --
1 file changed, 2 deletions(-)
diff --git a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
index 6bf44839dd4..a18df356899 100644
--- a/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
+++ b/java/ql/src/Likely Bugs/Arithmetic/RandomUsedOnce.ql
@@ -4,12 +4,10 @@
* guarantee an evenly distributed sequence of random numbers.
* @kind problem
* @problem.severity warning
- * @security-severity 9.8
* @precision medium
* @id java/random-used-once
* @tags reliability
* maintainability
- * security
* external/cwe/cwe-335
*/
From f3daff4e5a2e246e3455cec88b84c02299367635 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 19 Jan 2022 15:13:06 +0100
Subject: [PATCH 078/196] Python: Add FP tests for cleartext logging
---
.../dataflow/sensitive-data/test.py | 13 ++++++++
.../CleartextLogging.expected | 20 +++++++++++++
.../Security/CWE-312-CleartextLogging/test.py | 30 +++++++++++++++++++
.../CleartextStorage.expected | 4 +++
.../Security/CWE-312-CleartextStorage/test.py | 11 +++++++
5 files changed, 78 insertions(+)
diff --git a/python/ql/test/experimental/dataflow/sensitive-data/test.py b/python/ql/test/experimental/dataflow/sensitive-data/test.py
index a831115e01d..626bc771118 100644
--- a/python/ql/test/experimental/dataflow/sensitive-data/test.py
+++ b/python/ql/test/experimental/dataflow/sensitive-data/test.py
@@ -112,3 +112,16 @@ print(foo) # $ SensitiveUse=password
harmless = lambda: "bar"
bar = call_wrapper(harmless)
print(bar) # $ SPURIOUS: SensitiveUse=password
+
+# ------------------------------------------------------------------------------
+# cross-talk in dictionary.
+# ------------------------------------------------------------------------------
+
+from unknown_settings import password # $ SensitiveDataSource=password
+
+print(password) # $ SensitiveUse=password
+_config = {"sleep_timer": 5, "mysql_password": password}
+
+# since we have taint-step from store of `password`, we will consider any item in the
+# dictionary to be a password :(
+print(_config["sleep_timer"]) # $ SPURIOUS: SensitiveUse=password
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
index 3aacfa32aa5..51ee9af5309 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
@@ -4,6 +4,11 @@ edges
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password |
+| test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account |
+| test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring |
+| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x |
+| test.py:65:14:68:5 | ControlFlowNode for Dict | test.py:69:11:69:31 | ControlFlowNode for Subscript |
+| test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:65:14:68:5 | ControlFlowNode for Dict |
nodes
| test.py:19:16:19:29 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:20:48:20:55 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
@@ -15,6 +20,16 @@ nodes
| test.py:37:11:37:24 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
+| test.py:43:9:43:15 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
+| test.py:43:18:43:27 | ControlFlowNode for account_id | semmle.label | ControlFlowNode for account_id |
+| test.py:46:11:46:17 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
+| test.py:50:18:50:51 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
+| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
+| test.py:56:11:56:11 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
+| test.py:60:50:60:70 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| test.py:65:14:68:5 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict |
+| test.py:67:21:67:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
+| test.py:69:11:69:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
subpaths
#select
| test.py:20:48:20:55 | ControlFlowNode for password | test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:20:48:20:55 | ControlFlowNode for password | $@ is logged here. | test.py:19:16:19:29 | ControlFlowNode for get_password() | Sensitive data (password) |
@@ -26,3 +41,8 @@ subpaths
| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | $@ is logged here. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) |
+| test.py:46:11:46:17 | ControlFlowNode for account | test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account | $@ is logged here. | test.py:43:9:43:15 | ControlFlowNode for account | Sensitive data (id) |
+| test.py:50:18:50:51 | ControlFlowNode for Fstring | test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring | $@ is logged here. | test.py:43:18:43:27 | ControlFlowNode for account_id | Sensitive data (id) |
+| test.py:56:11:56:11 | ControlFlowNode for x | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x | $@ is logged here. | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
+| test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | $@ is logged here. | test.py:60:50:60:70 | ControlFlowNode for Attribute | Sensitive data (id) |
+| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | $@ is logged here. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) |
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py
index a20f2cc708c..f3dd31543a6 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/test.py
@@ -39,6 +39,36 @@ def print_password():
sys.stdout.write(get_password()) # NOT OK
sys.stderr.write(get_password()) # NOT OK
+
+def FPs(account, account_id):
+ # we assume that any account parameter is sensitive (id/username)
+ # https://github.com/github/codeql/issues/6363
+ print(account) # OK
+
+ # https://github.com/github/codeql/issues/6927
+ arn = f"arn:aws:iam::{account_id}:role/cfripper-access"
+ logging.info(f"Preparing to assume role: {arn}") # OK
+
+ # Harmless UUIDs
+ # https://github.com/github/codeql/issues/6726
+ # https://github.com/github/codeql/issues/7497
+ x = generate_uuid4()
+ print(x) # OK
+
+ # username not considered sensitive
+ # https://github.com/github/codeql/issues/7116
+ logging.error("Misc Exception. User %s: %s", request.user.username)
+
+ # dictionary taint-flow corss-talk
+ # https://github.com/github/codeql/issues/6380
+ import settings
+ config = {
+ "sleep_timer": 5,
+ "password": settings.password
+ }
+ print(config["sleep_timer"]) # OK
+
+
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
log_password()
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
index 518935eb677..3f453244813 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
@@ -4,6 +4,7 @@ edges
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:9:17:9:29 | ControlFlowNode for List |
| test.py:9:17:9:29 | ControlFlowNode for List | test.py:10:25:10:29 | ControlFlowNode for lines |
+| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x |
nodes
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
@@ -13,9 +14,12 @@ nodes
| test.py:8:20:8:23 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
| test.py:9:17:9:29 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
+| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
+| test.py:21:20:21:20 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
subpaths
#select
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
+| test.py:21:20:21:20 | ControlFlowNode for x | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x | $@ is stored here. | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py
index c085806d389..f232f1a2ad6 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/test.py
@@ -8,3 +8,14 @@ def write_cert(filename):
file.write(cert) # NOT OK
lines = [cert + "\n"]
file.writelines(lines) # NOT OK
+
+def FPs():
+ # just like for cleartext-logging see that file for more elaborate tests
+ #
+ # this part is just to make sure the two queries are in line with what is considered
+ # sensitive information.
+
+ with open(filename, "w") as file:
+ # Harmless UUIDs
+ x = generate_uuid4()
+ file.write(x) # OK
From c63fcb2c696061154d46d31cc8f69f0639783415 Mon Sep 17 00:00:00 2001
From: Chris Smowton
Date: Wed, 19 Jan 2022 14:13:45 +0000
Subject: [PATCH 079/196] Add change note
---
java/ql/src/change-notes/2022-01-19-random-used-once.md | 4 ++++
1 file changed, 4 insertions(+)
create mode 100644 java/ql/src/change-notes/2022-01-19-random-used-once.md
diff --git a/java/ql/src/change-notes/2022-01-19-random-used-once.md b/java/ql/src/change-notes/2022-01-19-random-used-once.md
new file mode 100644
index 00000000000..f9a00c6528f
--- /dev/null
+++ b/java/ql/src/change-notes/2022-01-19-random-used-once.md
@@ -0,0 +1,4 @@
+---
+category: queryMetadata
+---
+* The "Random used only once" (`java/random-used-once`) query no longer has a `security-severity` score. This has been causing some tools to categorise it as a security query, when it is more useful as a code-quality query.
From e82e648ca15714c0a6f38b900fa7a15841f3c9c8 Mon Sep 17 00:00:00 2001
From: Rasmus Wriedt Larsen
Date: Wed, 19 Jan 2022 15:25:21 +0100
Subject: [PATCH 080/196] Python: Remove usernames as sensitive source for
cleartext queries
Closes #6363, #6927, #6726, #7497, #7116
---
.../dataflow/CleartextLoggingCustomizations.qll | 4 ++++
.../dataflow/CleartextStorageCustomizations.qll | 4 ++++
.../2021-01-19-remove-cleartext-fps.md | 4 ++++
.../CleartextLogging.expected | 14 --------------
.../CleartextStorage.expected | 4 ----
5 files changed, 12 insertions(+), 18 deletions(-)
create mode 100644 python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md
diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll
index 72530536d8e..fcf8885f3f4 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CleartextLoggingCustomizations.qll
@@ -40,6 +40,10 @@ module CleartextLogging {
* A source of sensitive data, considered as a flow source.
*/
class SensitiveDataSourceAsSource extends Source, SensitiveDataSource {
+ SensitiveDataSourceAsSource() {
+ not SensitiveDataSource.super.getClassification() = SensitiveDataClassification::id()
+ }
+
override SensitiveDataClassification getClassification() {
result = SensitiveDataSource.super.getClassification()
}
diff --git a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll
index 3aaf7acf89f..3c7bc43ffa2 100644
--- a/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll
+++ b/python/ql/lib/semmle/python/security/dataflow/CleartextStorageCustomizations.qll
@@ -39,6 +39,10 @@ module CleartextStorage {
* A source of sensitive data, considered as a flow source.
*/
class SensitiveDataSourceAsSource extends Source, SensitiveDataSource {
+ SensitiveDataSourceAsSource() {
+ not SensitiveDataSource.super.getClassification() = SensitiveDataClassification::id()
+ }
+
override SensitiveDataClassification getClassification() {
result = SensitiveDataSource.super.getClassification()
}
diff --git a/python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md b/python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md
new file mode 100644
index 00000000000..0ddb4d804fd
--- /dev/null
+++ b/python/ql/src/change-notes/2021-01-19-remove-cleartext-fps.md
@@ -0,0 +1,4 @@
+---
+category: majorAnalysis
+---
+* No longer consider usernames or other account information as sensitive data for the queries `py/clear-text-logging-sensitive-data` and `py/clear-text-storage-sensitive-data`, since this has lead to many false positives.
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
index 51ee9af5309..f5fb2ac8dfb 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextLogging/CleartextLogging.expected
@@ -4,9 +4,6 @@ edges
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:23:58:23:65 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:27:40:27:47 | ControlFlowNode for password |
| test.py:19:16:19:29 | ControlFlowNode for get_password() | test.py:30:58:30:65 | ControlFlowNode for password |
-| test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account |
-| test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring |
-| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x |
| test.py:65:14:68:5 | ControlFlowNode for Dict | test.py:69:11:69:31 | ControlFlowNode for Subscript |
| test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:65:14:68:5 | ControlFlowNode for Dict |
nodes
@@ -20,13 +17,6 @@ nodes
| test.py:37:11:37:24 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | semmle.label | ControlFlowNode for get_password() |
-| test.py:43:9:43:15 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
-| test.py:43:18:43:27 | ControlFlowNode for account_id | semmle.label | ControlFlowNode for account_id |
-| test.py:46:11:46:17 | ControlFlowNode for account | semmle.label | ControlFlowNode for account |
-| test.py:50:18:50:51 | ControlFlowNode for Fstring | semmle.label | ControlFlowNode for Fstring |
-| test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
-| test.py:56:11:56:11 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
-| test.py:60:50:60:70 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:65:14:68:5 | ControlFlowNode for Dict | semmle.label | ControlFlowNode for Dict |
| test.py:67:21:67:37 | ControlFlowNode for Attribute | semmle.label | ControlFlowNode for Attribute |
| test.py:69:11:69:31 | ControlFlowNode for Subscript | semmle.label | ControlFlowNode for Subscript |
@@ -41,8 +31,4 @@ subpaths
| test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | test.py:37:11:37:24 | ControlFlowNode for get_password() | $@ is logged here. | test.py:37:11:37:24 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | test.py:39:22:39:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:39:22:39:35 | ControlFlowNode for get_password() | Sensitive data (password) |
| test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | test.py:40:22:40:35 | ControlFlowNode for get_password() | $@ is logged here. | test.py:40:22:40:35 | ControlFlowNode for get_password() | Sensitive data (password) |
-| test.py:46:11:46:17 | ControlFlowNode for account | test.py:43:9:43:15 | ControlFlowNode for account | test.py:46:11:46:17 | ControlFlowNode for account | $@ is logged here. | test.py:43:9:43:15 | ControlFlowNode for account | Sensitive data (id) |
-| test.py:50:18:50:51 | ControlFlowNode for Fstring | test.py:43:18:43:27 | ControlFlowNode for account_id | test.py:50:18:50:51 | ControlFlowNode for Fstring | $@ is logged here. | test.py:43:18:43:27 | ControlFlowNode for account_id | Sensitive data (id) |
-| test.py:56:11:56:11 | ControlFlowNode for x | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | test.py:56:11:56:11 | ControlFlowNode for x | $@ is logged here. | test.py:55:9:55:24 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
-| test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | test.py:60:50:60:70 | ControlFlowNode for Attribute | $@ is logged here. | test.py:60:50:60:70 | ControlFlowNode for Attribute | Sensitive data (id) |
| test.py:69:11:69:31 | ControlFlowNode for Subscript | test.py:67:21:67:37 | ControlFlowNode for Attribute | test.py:69:11:69:31 | ControlFlowNode for Subscript | $@ is logged here. | test.py:67:21:67:37 | ControlFlowNode for Attribute | Sensitive data (password) |
diff --git a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
index 3f453244813..518935eb677 100644
--- a/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
+++ b/python/ql/test/query-tests/Security/CWE-312-CleartextStorage/CleartextStorage.expected
@@ -4,7 +4,6 @@ edges
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert |
| test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:9:17:9:29 | ControlFlowNode for List |
| test.py:9:17:9:29 | ControlFlowNode for List | test.py:10:25:10:29 | ControlFlowNode for lines |
-| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x |
nodes
| password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | semmle.label | ControlFlowNode for Attribute() |
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | semmle.label | ControlFlowNode for password |
@@ -14,12 +13,9 @@ nodes
| test.py:8:20:8:23 | ControlFlowNode for cert | semmle.label | ControlFlowNode for cert |
| test.py:9:17:9:29 | ControlFlowNode for List | semmle.label | ControlFlowNode for List |
| test.py:10:25:10:29 | ControlFlowNode for lines | semmle.label | ControlFlowNode for lines |
-| test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | semmle.label | ControlFlowNode for generate_uuid4() |
-| test.py:21:20:21:20 | ControlFlowNode for x | semmle.label | ControlFlowNode for x |
subpaths
#select
| password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | password_in_cookie.py:9:33:9:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:7:16:7:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | password_in_cookie.py:16:33:16:40 | ControlFlowNode for password | $@ is stored here. | password_in_cookie.py:14:16:14:43 | ControlFlowNode for Attribute() | Sensitive data (password) |
| test.py:8:20:8:23 | ControlFlowNode for cert | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:8:20:8:23 | ControlFlowNode for cert | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
| test.py:10:25:10:29 | ControlFlowNode for lines | test.py:6:12:6:21 | ControlFlowNode for get_cert() | test.py:10:25:10:29 | ControlFlowNode for lines | $@ is stored here. | test.py:6:12:6:21 | ControlFlowNode for get_cert() | Sensitive data (certificate) |
-| test.py:21:20:21:20 | ControlFlowNode for x | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | test.py:21:20:21:20 | ControlFlowNode for x | $@ is stored here. | test.py:20:13:20:28 | ControlFlowNode for generate_uuid4() | Sensitive data (id) |
From c134e6c9efcf44804ea9a58eb03c730bbc879e5e Mon Sep 17 00:00:00 2001
From: Henry Mercer
Date: Wed, 19 Jan 2022 14:40:42 +0000
Subject: [PATCH 081/196] JS: Bump ML-powered query packs to v0.0.6
---
.../ql/experimental/adaptivethreatmodeling/lib/qlpack.yml | 2 +-
.../ql/experimental/adaptivethreatmodeling/src/qlpack.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
index 963899246f7..9389534628f 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/javascript-experimental-atm-lib
-version: 0.0.5
+version: 0.0.6
extractor: javascript
library: true
groups:
diff --git a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
index 9fb0fc7ad93..bb7dfce5202 100644
--- a/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
+++ b/javascript/ql/experimental/adaptivethreatmodeling/src/qlpack.yml
@@ -1,6 +1,6 @@
name: codeql/javascript-experimental-atm-queries
language: javascript
-version: 0.0.5
+version: 0.0.6
suites: codeql-suites
defaultSuiteFile: codeql-suites/javascript-atm-code-scanning.qls
groups:
From 520d8f5ec5152b7387664296c6f20e6f9059fadf Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Wed, 20 Oct 2021 12:00:12 +0200
Subject: [PATCH 082/196] Add stubs
---
.../android/app/Fragment.java | 24 +-
.../android/view/View.java | 1971 +++++++++++++++++
2 files changed, 1987 insertions(+), 8 deletions(-)
diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java
index e06f81dcef1..2ebe4db7e13 100644
--- a/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java
+++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java
@@ -15,31 +15,30 @@
package android.app;
import android.annotation.Nullable;
+import android.content.ComponentCallbacks2;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
-
-public class Fragment {
-
+public class Fragment implements ComponentCallbacks2 {
public static class SavedState implements Parcelable {
-
- @Override
- public void writeToParcel(Parcel dest, int flags) {}
-
@Override
public int describeContents() {
return 0;
}
+
+ @Override
+ public void writeToParcel(Parcel dest, int flags) {}
+
}
static public class InstantiationException {
public InstantiationException(String msg, Exception cause) {}
-
}
+
public Fragment() {}
public static Fragment instantiate(Context context, String fname) {
@@ -65,4 +64,13 @@ public class Fragment {
return null;
}
+ @Override
+ public void onConfigurationChanged(Configuration p0) {}
+
+ @Override
+ public void onLowMemory() {}
+
+ @Override
+ public void onTrimMemory(int p0) {}
+
}
diff --git a/java/ql/test/stubs/google-android-9.0.0/android/view/View.java b/java/ql/test/stubs/google-android-9.0.0/android/view/View.java
index 2004c624c6e..39f4a905a07 100644
--- a/java/ql/test/stubs/google-android-9.0.0/android/view/View.java
+++ b/java/ql/test/stubs/google-android-9.0.0/android/view/View.java
@@ -71,6 +71,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
+<<<<<<< HEAD
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -995,5 +996,1975 @@ public class View implements AccessibilityEventSource, Drawable.Callback, KeyEve
static public interface OnUnhandledKeyEventListener
{
boolean onUnhandledKeyEvent(View p0, KeyEvent p1);
+=======
+import java.util.function.Predicate;
+import android.annotation.Nullable;
+import android.content.ClipData;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.ColorStateList;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
+import android.graphics.Bitmap;
+import android.graphics.BlendMode;
+import android.graphics.Canvas;
+import android.graphics.Insets;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Point;
+import android.graphics.PorterDuff;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.graphics.Region;
+import android.graphics.RenderNode;
+import android.graphics.drawable.Drawable;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.IBinder;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.AttributeSet;
+import android.util.SparseArray;
+
+public class View implements Drawable.Callback {
+ public @interface Focusable {
+ }
+
+ public @interface Visibility {
+ }
+
+ public @interface AutofillType {
+ }
+ public @interface AutofillImportance {
+ }
+ public @interface AutofillFlags {
+ }
+ public @interface ContentCaptureImportance {
+ }
+ public @interface ScrollCaptureHint {
+ }
+ public @interface DrawingCacheQuality {
+ }
+ public @interface ScrollBarStyle {
+ }
+ public @interface FocusableMode {
+ }
+ public @interface FocusDirection {
+ }
+ public @interface FocusRealDirection {
+ }
+ public @interface LayoutDir {
+ }
+ public @interface ResolvedLayoutDir {
+ }
+ public @interface TextAlignment {
+ }
+ public @interface ScrollIndicators {
+ }
+ public @interface ViewStructureType {
+ }
+ public @interface FindViewFlags {
+ }
+ public @interface LayerType {
+ }
+
+ public View(Context context) {}
+
+ public View(Context context, AttributeSet attrs) {}
+
+ public View(Context context, AttributeSet attrs, int defStyleAttr) {}
+
+ public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {}
+
+ public int[] getAttributeResolutionStack(int attribute) {
+ return null;
+ }
+
+ public Map getAttributeSourceResourceMap() {
+ return null;
+ }
+
+ public int getExplicitStyle() {
+ return 0;
+ }
+
+ public final boolean isShowingLayoutBounds() {
+ return false;
+ }
+
+ public final void setShowingLayoutBounds(boolean debugLayout) {}
+
+ public final void saveAttributeDataForStyleable(Context context, int[] styleable,
+ AttributeSet attrs, TypedArray t, int defStyleAttr, int defStyleRes) {}
+
+ @Override
+ public String toString() {
+ return null;
+ }
+
+ public int getVerticalFadingEdgeLength() {
+ return 0;
+ }
+
+ public void setFadingEdgeLength(int length) {}
+
+ public int getHorizontalFadingEdgeLength() {
+ return 0;
+ }
+
+ public int getVerticalScrollbarWidth() {
+ return 0;
+ }
+
+ public void setVerticalScrollbarThumbDrawable(Drawable drawable) {}
+
+ public void setVerticalScrollbarTrackDrawable(Drawable drawable) {}
+
+ public void setHorizontalScrollbarThumbDrawable(Drawable drawable) {}
+
+ public void setHorizontalScrollbarTrackDrawable(Drawable drawable) {}
+
+ public Drawable getVerticalScrollbarThumbDrawable() {
+ return null;
+ }
+
+ public Drawable getVerticalScrollbarTrackDrawable() {
+ return null;
+ }
+
+ public Drawable getHorizontalScrollbarThumbDrawable() {
+ return null;
+ }
+
+ public Drawable getHorizontalScrollbarTrackDrawable() {
+ return null;
+ }
+
+ public void setVerticalScrollbarPosition(int position) {}
+
+ public int getVerticalScrollbarPosition() {
+ return 0;
+ }
+
+ public void setScrollIndicators(int indicators) {}
+
+ public void setScrollIndicators(int indicators, int mask) {}
+
+ public int getScrollIndicators() {
+ return 0;
+ }
+
+ public void setOnScrollChangeListener(OnScrollChangeListener l) {}
+
+ public void setOnFocusChangeListener(OnFocusChangeListener l) {}
+
+ public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {}
+
+ public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {}
+
+ public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {}
+
+ public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {}
+
+ public OnFocusChangeListener getOnFocusChangeListener() {
+ return null;
+ }
+
+ public void setOnClickListener(OnClickListener l) {}
+
+ public boolean hasOnClickListeners() {
+ return false;
+ }
+
+ public void setOnLongClickListener(OnLongClickListener l) {}
+
+ public boolean hasOnLongClickListeners() {
+ return false;
+ }
+
+ public OnLongClickListener getOnLongClickListener() {
+ return null;
+ }
+
+ public void setOnContextClickListener(OnContextClickListener l) {}
+
+ public void setNotifyAutofillManagerOnClick(boolean notify) {}
+
+ public boolean performClick() {
+ return false;
+ }
+
+ public boolean callOnClick() {
+ return false;
+ }
+
+ public boolean performLongClick() {
+ return false;
+ }
+
+ public boolean performLongClick(float x, float y) {
+ return false;
+ }
+
+ public boolean performContextClick(float x, float y) {
+ return false;
+ }
+
+ public boolean performContextClick() {
+ return false;
+ }
+
+ public boolean showContextMenu() {
+ return false;
+ }
+
+ public boolean showContextMenu(float x, float y) {
+ return false;
+ }
+
+ public void startActivityForResult(Intent intent, int requestCode) {}
+
+ public boolean dispatchActivityResult(String who, int requestCode, int resultCode,
+ Intent data) {
+ return false;
+ }
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {}
+
+ public final void setRevealOnFocusHint(boolean revealOnFocus) {}
+
+ public final boolean getRevealOnFocusHint() {
+ return false;
+ }
+
+ public void getHotspotBounds(Rect outRect) {}
+
+ public boolean requestRectangleOnScreen(Rect rectangle) {
+ return false;
+ }
+
+ public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
+ return false;
+ }
+
+ public void clearFocus() {}
+
+ public boolean hasFocus() {
+ return false;
+ }
+
+ public boolean hasFocusable() {
+ return false;
+ }
+
+ public boolean hasExplicitFocusable() {
+ return false;
+ }
+
+ public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {}
+
+ public void setAccessibilityPaneTitle(CharSequence accessibilityPaneTitle) {}
+
+ public CharSequence getAccessibilityPaneTitle() {
+ return null;
+ }
+
+ public void sendAccessibilityEvent(int eventType) {}
+
+ public void announceForAccessibility(CharSequence text) {}
+
+ public void sendAccessibilityEventInternal(int eventType) {}
+
+ public void getBoundsOnScreen(Rect outRect) {}
+
+ public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {}
+
+ public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {}
+
+ public CharSequence getAccessibilityClassName() {
+ return null;
+ }
+
+ public int getAutofillType() {
+ return 0;
+ }
+
+ @Nullable
+ public String[] getAutofillHints() {
+ return null;
+ }
+
+ public boolean isAutofilled() {
+ return false;
+ }
+
+ public boolean hideAutofillHighlight() {
+ return false;
+ }
+
+ public int getImportantForAutofill() {
+ return 0;
+ }
+
+ public void setImportantForAutofill(int mode) {}
+
+ public final boolean isImportantForAutofill() {
+ return false;
+ }
+
+ public int getImportantForContentCapture() {
+ return 0;
+ }
+
+ public void setImportantForContentCapture(int mode) {}
+
+ public final boolean isImportantForContentCapture() {
+ return false;
+ }
+
+ public boolean canNotifyAutofillEnterExitEvent() {
+ return false;
+ }
+
+ public void dispatchInitialProvideContentCaptureStructure() {}
+
+ public boolean isVisibleToUserForAutofill(int virtualId) {
+ return false;
+ }
+
+ public boolean isVisibleToUser() {
+ return false;
+ }
+
+ public AccessibilityDelegate getAccessibilityDelegate() {
+ return null;
+ }
+
+ public void setAccessibilityDelegate(AccessibilityDelegate delegate) {}
+
+ public int getAccessibilityViewId() {
+ return 0;
+ }
+
+ public int getAutofillViewId() {
+ return 0;
+ }
+
+ public int getAccessibilityWindowId() {
+ return 0;
+ }
+
+ public final CharSequence getStateDescription() {
+ return null;
+ }
+
+ public CharSequence getContentDescription() {
+ return null;
+ }
+
+ public void setStateDescription(CharSequence stateDescription) {}
+
+ public void setContentDescription(CharSequence contentDescription) {}
+
+ public void setAccessibilityTraversalBefore(int beforeId) {}
+
+ public int getAccessibilityTraversalBefore() {
+ return 0;
+ }
+
+ public void setAccessibilityTraversalAfter(int afterId) {}
+
+ public int getAccessibilityTraversalAfter() {
+ return 0;
+ }
+
+ public int getLabelFor() {
+ return 0;
+ }
+
+ public void setLabelFor(int id) {}
+
+ public boolean isFocused() {
+ return false;
+ }
+
+ public View findFocus() {
+ return null;
+ }
+
+ public boolean isScrollContainer() {
+ return false;
+ }
+
+ public void setScrollContainer(boolean isScrollContainer) {}
+
+ public int getDrawingCacheQuality() {
+ return 0;
+ }
+
+ public void setDrawingCacheQuality(int quality) {}
+
+ public boolean getKeepScreenOn() {
+ return false;
+ }
+
+ public void setKeepScreenOn(boolean keepScreenOn) {}
+
+ public int getNextFocusLeftId() {
+ return 0;
+ }
+
+ public void setNextFocusLeftId(int nextFocusLeftId) {}
+
+ public int getNextFocusRightId() {
+ return 0;
+ }
+
+ public void setNextFocusRightId(int nextFocusRightId) {}
+
+ public int getNextFocusUpId() {
+ return 0;
+ }
+
+ public void setNextFocusUpId(int nextFocusUpId) {}
+
+ public int getNextFocusDownId() {
+ return 0;
+ }
+
+ public void setNextFocusDownId(int nextFocusDownId) {}
+
+ public int getNextFocusForwardId() {
+ return 0;
+ }
+
+ public void setNextFocusForwardId(int nextFocusForwardId) {}
+
+ public int getNextClusterForwardId() {
+ return 0;
+ }
+
+ public void setNextClusterForwardId(int nextClusterForwardId) {}
+
+ public boolean isShown() {
+ return false;
+ }
+
+ public boolean hasWindowInsetsAnimationCallback() {
+ return false;
+ }
+
+ public void setSystemGestureExclusionRects(List rects) {}
+
+ public List getSystemGestureExclusionRects() {
+ return null;
+ }
+
+ public void getLocationInSurface(int[] location) {}
+
+ public void setFitsSystemWindows(boolean fitSystemWindows) {}
+
+ public boolean getFitsSystemWindows() {
+ return false;
+ }
+
+ public boolean fitsSystemWindows() {
+ return false;
+ }
+
+ public void requestFitSystemWindows() {}
+
+ public void requestApplyInsets() {}
+
+ public void makeOptionalFitsSystemWindows() {}
+
+ public void makeFrameworkOptionalFitsSystemWindows() {}
+
+ public boolean isFrameworkOptionalFitsSystemWindows() {
+ return false;
+ }
+
+ public int getVisibility() {
+ return 0;
+ }
+
+ public void setVisibility(int visibility) {}
+
+ public boolean isEnabled() {
+ return false;
+ }
+
+ public void setEnabled(boolean enabled) {}
+
+ public void setFocusable(boolean focusable) {}
+
+ public void setFocusable(int focusable) {}
+
+ public void setFocusableInTouchMode(boolean focusableInTouchMode) {}
+
+ public void setAutofillHints(String... autofillHints) {}
+
+ public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {}
+
+ public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {}
+
+ public boolean isSoundEffectsEnabled() {
+ return false;
+ }
+
+ public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {}
+
+ public boolean isHapticFeedbackEnabled() {
+ return false;
+ }
+
+ public int getRawLayoutDirection() {
+ return 0;
+ }
+
+ public void setLayoutDirection(int layoutDirection) {}
+
+ public int getLayoutDirection() {
+ return 0;
+ }
+
+ public boolean isLayoutRtl() {
+ return false;
+ }
+
+ public boolean hasTransientState() {
+ return false;
+ }
+
+ public void setHasTransientState(boolean hasTransientState) {}
+
+ public boolean isAttachedToWindow() {
+ return false;
+ }
+
+ public boolean isLaidOut() {
+ return false;
+ }
+
+ public void setWillNotDraw(boolean willNotDraw) {}
+
+ public boolean willNotDraw() {
+ return false;
+ }
+
+ public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {}
+
+ public boolean willNotCacheDrawing() {
+ return false;
+ }
+
+ public boolean isClickable() {
+ return false;
+ }
+
+ public void setClickable(boolean clickable) {}
+
+ public boolean isLongClickable() {
+ return false;
+ }
+
+ public void setLongClickable(boolean longClickable) {}
+
+ public boolean isContextClickable() {
+ return false;
+ }
+
+ public void setContextClickable(boolean contextClickable) {}
+
+ public void setPressed(boolean pressed) {}
+
+ public boolean isPressed() {
+ return false;
+ }
+
+ public boolean isAssistBlocked() {
+ return false;
+ }
+
+ public void setAssistBlocked(boolean enabled) {}
+
+ public boolean isSaveEnabled() {
+ return false;
+ }
+
+ public void setSaveEnabled(boolean enabled) {}
+
+ public boolean getFilterTouchesWhenObscured() {
+ return false;
+ }
+
+ public void setFilterTouchesWhenObscured(boolean enabled) {}
+
+ public boolean isSaveFromParentEnabled() {
+ return false;
+ }
+
+ public void setSaveFromParentEnabled(boolean enabled) {}
+
+ public final boolean isFocusable() {
+ return false;
+ }
+
+ public int getFocusable() {
+ return 0;
+ }
+
+ public final boolean isFocusableInTouchMode() {
+ return false;
+ }
+
+ public boolean isScreenReaderFocusable() {
+ return false;
+ }
+
+ public void setScreenReaderFocusable(boolean screenReaderFocusable) {}
+
+ public boolean isAccessibilityHeading() {
+ return false;
+ }
+
+ public void setAccessibilityHeading(boolean isHeading) {}
+
+ public View focusSearch(int direction) {
+ return null;
+ }
+
+ public final boolean isKeyboardNavigationCluster() {
+ return false;
+ }
+
+ public void setKeyboardNavigationCluster(boolean isCluster) {}
+
+ public final void setFocusedInCluster() {}
+
+ public final boolean isFocusedByDefault() {
+ return false;
+ }
+
+ public void setFocusedByDefault(boolean isFocusedByDefault) {}
+
+ public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
+ return null;
+ }
+
+ public boolean dispatchUnhandledMove(View focused, int direction) {
+ return false;
+ }
+
+ public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {}
+
+ public final boolean getDefaultFocusHighlightEnabled() {
+ return false;
+ }
+
+ public ArrayList getFocusables(int direction) {
+ return null;
+ }
+
+ public void addFocusables(ArrayList views, int direction) {}
+
+ public void addFocusables(ArrayList views, int direction, int focusableMode) {}
+
+ public void addKeyboardNavigationClusters(Collection views, int direction) {}
+
+ public void findViewsWithText(ArrayList outViews, CharSequence searched, int flags) {}
+
+ public ArrayList getTouchables() {
+ return null;
+ }
+
+ public void addTouchables(ArrayList views) {}
+
+ public boolean isAccessibilityFocused() {
+ return false;
+ }
+
+ public boolean requestAccessibilityFocus() {
+ return false;
+ }
+
+ public void clearAccessibilityFocus() {}
+
+ public final boolean requestFocus() {
+ return false;
+ }
+
+ public boolean restoreFocusInCluster(int direction) {
+ return false;
+ }
+
+ public boolean restoreFocusNotInCluster() {
+ return false;
+ }
+
+ public boolean restoreDefaultFocus() {
+ return false;
+ }
+
+ public final boolean requestFocus(int direction) {
+ return false;
+ }
+
+ public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
+ return false;
+ }
+
+ public final boolean requestFocusFromTouch() {
+ return false;
+ }
+
+ public int getImportantForAccessibility() {
+ return 0;
+ }
+
+ public void setAccessibilityLiveRegion(int mode) {}
+
+ public int getAccessibilityLiveRegion() {
+ return 0;
+ }
+
+ public void setImportantForAccessibility(int mode) {}
+
+ public boolean isImportantForAccessibility() {
+ return false;
+ }
+
+ public void addChildrenForAccessibility(ArrayList outChildren) {}
+
+ public boolean includeForAccessibility() {
+ return false;
+ }
+
+ public boolean isActionableForAccessibility() {
+ return false;
+ }
+
+ public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {}
+
+ public void notifySubtreeAccessibilityStateChangedIfNeeded() {}
+
+ public void setTransitionVisibility(int visibility) {}
+
+ public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
+ return false;
+ }
+
+ public boolean performAccessibilityAction(int action, Bundle arguments) {
+ return false;
+ }
+
+ public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
+ return false;
+ }
+
+ public CharSequence getIterableTextForAccessibility() {
+ return null;
+ }
+
+ public boolean isAccessibilitySelectionExtendable() {
+ return false;
+ }
+
+ public int getAccessibilitySelectionStart() {
+ return 0;
+ }
+
+ public int getAccessibilitySelectionEnd() {
+ return 0;
+ }
+
+ public void setAccessibilitySelection(int start, int end) {}
+
+ public final boolean isTemporarilyDetached() {
+ return false;
+ }
+
+ public void dispatchStartTemporaryDetach() {}
+
+ public void onStartTemporaryDetach() {}
+
+ public void dispatchFinishTemporaryDetach() {}
+
+ public void onFinishTemporaryDetach() {}
+
+ public void dispatchWindowFocusChanged(boolean hasFocus) {}
+
+ public void onWindowFocusChanged(boolean hasWindowFocus) {}
+
+ public boolean hasWindowFocus() {
+ return false;
+ }
+
+ public boolean hasImeFocus() {
+ return false;
+ }
+
+ public void dispatchDisplayHint(int hint) {}
+
+ public void dispatchWindowVisibilityChanged(int visibility) {}
+
+ public void onVisibilityAggregated(boolean isVisible) {}
+
+ public int getWindowVisibility() {
+ return 0;
+ }
+
+ public void getWindowVisibleDisplayFrame(Rect outRect) {}
+
+ public void getWindowDisplayFrame(Rect outRect) {}
+
+ public void dispatchConfigurationChanged(Configuration newConfig) {}
+
+ public boolean isInTouchMode() {
+ return false;
+ }
+
+ public final Context getContext() {
+ return null;
+ }
+
+ public boolean onCheckIsTextEditor() {
+ return false;
+ }
+
+ public boolean checkInputConnectionProxy(View view) {
+ return false;
+ }
+
+ public boolean isHovered() {
+ return false;
+ }
+
+ public void setHovered(boolean hovered) {}
+
+ public void onHoverChanged(boolean hovered) {}
+
+ public boolean isInScrollingContainer() {
+ return false;
+ }
+
+ public void cancelLongPress() {}
+
+ public final void requestUnbufferedDispatch(int source) {}
+
+ public void bringToFront() {}
+
+ public interface OnScrollChangeListener {
+ void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
+
+ }
+ public interface OnLayoutChangeListener {
+ void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
+ int oldTop, int oldRight, int oldBottom);
+
+ }
+
+ public void setScrollX(int value) {}
+
+ public void setScrollY(int value) {}
+
+ public final int getScrollX() {
+ return 0;
+ }
+
+ public final int getScrollY() {
+ return 0;
+ }
+
+ public final int getWidth() {
+ return 0;
+ }
+
+ public final int getHeight() {
+ return 0;
+ }
+
+ public void getDrawingRect(Rect outRect) {}
+
+ public final int getMeasuredWidth() {
+ return 0;
+ }
+
+ public final int getMeasuredWidthAndState() {
+ return 0;
+ }
+
+ public final int getMeasuredHeight() {
+ return 0;
+ }
+
+ public final int getMeasuredHeightAndState() {
+ return 0;
+ }
+
+ public final int getMeasuredState() {
+ return 0;
+ }
+
+ public Matrix getMatrix() {
+ return null;
+ }
+
+ public final boolean hasIdentityMatrix() {
+ return false;
+ }
+
+ public final Matrix getInverseMatrix() {
+ return null;
+ }
+
+ public float getCameraDistance() {
+ return 0;
+ }
+
+ public void setCameraDistance(float distance) {}
+
+ public float getRotation() {
+ return 0;
+ }
+
+ public void setRotation(float rotation) {}
+
+ public float getRotationY() {
+ return 0;
+ }
+
+ public void setRotationY(float rotationY) {}
+
+ public float getRotationX() {
+ return 0;
+ }
+
+ public void setRotationX(float rotationX) {}
+
+ public float getScaleX() {
+ return 0;
+ }
+
+ public void setScaleX(float scaleX) {}
+
+ public float getScaleY() {
+ return 0;
+ }
+
+ public void setScaleY(float scaleY) {}
+
+ public float getPivotX() {
+ return 0;
+ }
+
+ public void setPivotX(float pivotX) {}
+
+ public float getPivotY() {
+ return 0;
+ }
+
+ public void setPivotY(float pivotY) {}
+
+ public boolean isPivotSet() {
+ return false;
+ }
+
+ public void resetPivot() {}
+
+ public float getAlpha() {
+ return 0;
+ }
+
+ public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {}
+
+ public final boolean getHasOverlappingRendering() {
+ return false;
+ }
+
+ public boolean hasOverlappingRendering() {
+ return false;
+ }
+
+ public void setAlpha(float alpha) {}
+
+ public void setTransitionAlpha(float alpha) {}
+
+ public float getTransitionAlpha() {
+ return 0;
+ }
+
+ public void setForceDarkAllowed(boolean allow) {}
+
+ public boolean isForceDarkAllowed() {
+ return false;
+ }
+
+ public final int getTop() {
+ return 0;
+ }
+
+ public final void setTop(int top) {}
+
+ public final int getBottom() {
+ return 0;
+ }
+
+ public boolean isDirty() {
+ return false;
+ }
+
+ public final void setBottom(int bottom) {}
+
+ public final int getLeft() {
+ return 0;
+ }
+
+ public final void setLeft(int left) {}
+
+ public final int getRight() {
+ return 0;
+ }
+
+ public final void setRight(int right) {}
+
+ public float getX() {
+ return 0;
+ }
+
+ public void setX(float x) {}
+
+ public float getY() {
+ return 0;
+ }
+
+ public void setY(float y) {}
+
+ public float getZ() {
+ return 0;
+ }
+
+ public void setZ(float z) {}
+
+ public float getElevation() {
+ return 0;
+ }
+
+ public void setElevation(float elevation) {}
+
+ public float getTranslationX() {
+ return 0;
+ }
+
+ public void setTranslationX(float translationX) {}
+
+ public float getTranslationY() {
+ return 0;
+ }
+
+ public void setTranslationY(float translationY) {}
+
+ public float getTranslationZ() {
+ return 0;
+ }
+
+ public void setTranslationZ(float translationZ) {}
+
+ public void setAnimationMatrix(Matrix matrix) {}
+
+ public Matrix getAnimationMatrix() {
+ return null;
+ }
+
+ public final boolean getClipToOutline() {
+ return false;
+ }
+
+ public void setClipToOutline(boolean clipToOutline) {}
+
+ public void invalidateOutline() {}
+
+ public boolean hasShadow() {
+ return false;
+ }
+
+ public void setOutlineSpotShadowColor(int color) {}
+
+ public int getOutlineSpotShadowColor() {
+ return 0;
+ }
+
+ public void setOutlineAmbientShadowColor(int color) {}
+
+ public int getOutlineAmbientShadowColor() {
+ return 0;
+ }
+
+ public void setRevealClip(boolean shouldClip, float x, float y, float radius) {}
+
+ public void getHitRect(Rect outRect) {}
+
+ public boolean pointInView(float localX, float localY, float slop) {
+ return false;
+ }
+
+ public void getFocusedRect(Rect r) {}
+
+ public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
+ return false;
+ }
+
+ public final boolean getGlobalVisibleRect(Rect r) {
+ return false;
+ }
+
+ public final boolean getLocalVisibleRect(Rect r) {
+ return false;
+ }
+
+ public void offsetTopAndBottom(int offset) {}
+
+ public void offsetLeftAndRight(int offset) {}
+
+ public void resolveLayoutParams() {}
+
+ public void scrollTo(int x, int y) {}
+
+ public void scrollBy(int x, int y) {}
+
+ public void invalidate(Rect dirty) {}
+
+ public void invalidate(int l, int t, int r, int b) {}
+
+ public void invalidate() {}
+
+ public void invalidate(boolean invalidateCache) {}
+
+ public boolean isOpaque() {
+ return false;
+ }
+
+ public Handler getHandler() {
+ return null;
+ }
+
+ public boolean post(Runnable action) {
+ return false;
+ }
+
+ public boolean postDelayed(Runnable action, long delayMillis) {
+ return false;
+ }
+
+ public void postOnAnimation(Runnable action) {}
+
+ public void postOnAnimationDelayed(Runnable action, long delayMillis) {}
+
+ public boolean removeCallbacks(Runnable action) {
+ return false;
+ }
+
+ public void postInvalidate() {}
+
+ public void postInvalidate(int left, int top, int right, int bottom) {}
+
+ public void postInvalidateDelayed(long delayMilliseconds) {}
+
+ public void postInvalidateDelayed(long delayMilliseconds, int left, int top, int right,
+ int bottom) {}
+
+ public void postInvalidateOnAnimation() {}
+
+ public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {}
+
+ public void computeScroll() {}
+
+ public boolean isHorizontalFadingEdgeEnabled() {
+ return false;
+ }
+
+ public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {}
+
+ public boolean isVerticalFadingEdgeEnabled() {
+ return false;
+ }
+
+ public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {}
+
+ public int getFadingEdge() {
+ return 0;
+ }
+
+ public int getFadingEdgeLength() {
+ return 0;
+ }
+
+ public boolean isHorizontalScrollBarEnabled() {
+ return false;
+ }
+
+ public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {}
+
+ public boolean isVerticalScrollBarEnabled() {
+ return false;
+ }
+
+ public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {}
+
+ public void setScrollbarFadingEnabled(boolean fadeScrollbars) {}
+
+ public boolean isScrollbarFadingEnabled() {
+ return false;
+ }
+
+ public int getScrollBarDefaultDelayBeforeFade() {
+ return 0;
+ }
+
+ public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {}
+
+ public int getScrollBarFadeDuration() {
+ return 0;
+ }
+
+ public void setScrollBarFadeDuration(int scrollBarFadeDuration) {}
+
+ public int getScrollBarSize() {
+ return 0;
+ }
+
+ public void setScrollBarSize(int scrollBarSize) {}
+
+ public void setScrollBarStyle(int style) {}
+
+ public int getScrollBarStyle() {
+ return 0;
+ }
+
+ public boolean canScrollHorizontally(int direction) {
+ return false;
+ }
+
+ public boolean canScrollVertically(int direction) {
+ return false;
+ }
+
+ public boolean resolveRtlPropertiesIfNeeded() {
+ return false;
+ }
+
+ public void resetRtlProperties() {}
+
+ public void onScreenStateChanged(int screenState) {}
+
+ public void onMovedToDisplay(int displayId, Configuration config) {}
+
+ public void onRtlPropertiesChanged(int layoutDirection) {}
+
+ public boolean resolveLayoutDirection() {
+ return false;
+ }
+
+ public boolean canResolveLayoutDirection() {
+ return false;
+ }
+
+ public void resetResolvedLayoutDirection() {}
+
+ public boolean isLayoutDirectionInherited() {
+ return false;
+ }
+
+ public boolean isLayoutDirectionResolved() {
+ return false;
+ }
+
+ public void resolvePadding() {}
+
+ public void resetResolvedPadding() {}
+
+ public IBinder getWindowToken() {
+ return null;
+ }
+
+ public IBinder getApplicationWindowToken() {
+ return null;
+ }
+
+ public Display getDisplay() {
+ return null;
+ }
+
+ public final void cancelPendingInputEvents() {}
+
+ public void onCancelPendingInputEvents() {}
+
+ public void saveHierarchyState(SparseArray container) {}
+
+ public void restoreHierarchyState(SparseArray container) {}
+
+ public long getDrawingTime() {
+ return 0;
+ }
+
+ public void setDuplicateParentStateEnabled(boolean enabled) {}
+
+ public boolean isDuplicateParentStateEnabled() {
+ return false;
+ }
+
+ public void setLayerType(int layerType, Paint paint) {}
+
+ public void setLayerPaint(Paint paint) {}
+
+ public int getLayerType() {
+ return 0;
+ }
+
+ public void buildLayer() {}
+
+ public void setDrawingCacheEnabled(boolean enabled) {}
+
+ public boolean isDrawingCacheEnabled() {
+ return false;
+ }
+
+ public void outputDirtyFlags(String indent, boolean clear, int clearMask) {}
+
+ public boolean canHaveDisplayList() {
+ return false;
+ }
+
+ public RenderNode updateDisplayListIfDirty() {
+ return null;
+ }
+
+ public Bitmap getDrawingCache() {
+ return null;
+ }
+
+ public Bitmap getDrawingCache(boolean autoScale) {
+ return null;
+ }
+
+ public void destroyDrawingCache() {}
+
+ public void setDrawingCacheBackgroundColor(int color) {}
+
+ public int getDrawingCacheBackgroundColor() {
+ return 0;
+ }
+
+ public void buildDrawingCache() {}
+
+ public void buildDrawingCache(boolean autoScale) {}
+
+ public boolean isInEditMode() {
+ return false;
+ }
+
+ public boolean isHardwareAccelerated() {
+ return false;
+ }
+
+ public void setClipBounds(Rect clipBounds) {}
+
+ public Rect getClipBounds() {
+ return null;
+ }
+
+ public boolean getClipBounds(Rect outRect) {
+ return false;
+ }
+
+ public void draw(Canvas canvas) {}
+
+ public int getSolidColor() {
+ return 0;
+ }
+
+ public boolean isLayoutRequested() {
+ return false;
+ }
+
+ public static boolean isLayoutModeOptical(Object o) {
+ return false;
+ }
+
+ public void layout(int l, int t, int r, int b) {}
+
+ public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {}
+
+ public Resources getResources() {
+ return null;
+ }
+
+ @Override
+ public void invalidateDrawable(Drawable drawable) {}
+
+ @Override
+ public void scheduleDrawable(Drawable who, Runnable what, long when) {}
+
+ @Override
+ public void unscheduleDrawable(Drawable who, Runnable what) {}
+
+ public void unscheduleDrawable(Drawable who) {}
+
+ public void onResolveDrawables(int layoutDirection) {}
+
+ public void drawableHotspotChanged(float x, float y) {}
+
+ public void dispatchDrawableHotspotChanged(float x, float y) {}
+
+ public void refreshDrawableState() {}
+
+ public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
+ return false;
+ }
+
+ public final int[] getDrawableState() {
+ return null;
+ }
+
+ public void jumpDrawablesToCurrentState() {}
+
+ public void setBackgroundColor(int color) {}
+
+ public void setBackgroundResource(int resid) {}
+
+ public void setBackground(Drawable background) {}
+
+ public void setBackgroundDrawable(Drawable background) {}
+
+ public Drawable getBackground() {
+ return null;
+ }
+
+ public void setBackgroundTintList(ColorStateList tint) {}
+
+ public ColorStateList getBackgroundTintList() {
+ return null;
+ }
+
+ public void setBackgroundTintMode(PorterDuff.Mode tintMode) {}
+
+ public void setBackgroundTintBlendMode(BlendMode blendMode) {}
+
+ public PorterDuff.Mode getBackgroundTintMode() {
+ return null;
+ }
+
+ public BlendMode getBackgroundTintBlendMode() {
+ return null;
+ }
+
+ public Drawable getForeground() {
+ return null;
+ }
+
+ public void setForeground(Drawable foreground) {}
+
+ public boolean isForegroundInsidePadding() {
+ return false;
+ }
+
+ public int getForegroundGravity() {
+ return 0;
+ }
+
+ public void setForegroundGravity(int gravity) {}
+
+ public void setForegroundTintList(ColorStateList tint) {}
+
+ public ColorStateList getForegroundTintList() {
+ return null;
+ }
+
+ public void setForegroundTintMode(PorterDuff.Mode tintMode) {}
+
+ public void setForegroundTintBlendMode(BlendMode blendMode) {}
+
+ public PorterDuff.Mode getForegroundTintMode() {
+ return null;
+ }
+
+ public BlendMode getForegroundTintBlendMode() {
+ return null;
+ }
+
+ public void onDrawForeground(Canvas canvas) {}
+
+ public void setPadding(int left, int top, int right, int bottom) {}
+
+ public void setPaddingRelative(int start, int top, int end, int bottom) {}
+
+ public int getSourceLayoutResId() {
+ return 0;
+ }
+
+ public int getPaddingTop() {
+ return 0;
+ }
+
+ public int getPaddingBottom() {
+ return 0;
+ }
+
+ public int getPaddingLeft() {
+ return 0;
+ }
+
+ public int getPaddingStart() {
+ return 0;
+ }
+
+ public int getPaddingRight() {
+ return 0;
+ }
+
+ public int getPaddingEnd() {
+ return 0;
+ }
+
+ public boolean isPaddingRelative() {
+ return false;
+ }
+
+ public void resetPaddingToInitialValues() {}
+
+ public Insets getOpticalInsets() {
+ return null;
+ }
+
+ public void setOpticalInsets(Insets insets) {}
+
+ public void setSelected(boolean selected) {}
+
+ public boolean isSelected() {
+ return false;
+ }
+
+ public void setActivated(boolean activated) {}
+
+ public boolean isActivated() {
+ return false;
+ }
+
+ public View getRootView() {
+ return null;
+ }
+
+ public void transformMatrixToGlobal(Matrix matrix) {}
+
+ public void transformMatrixToLocal(Matrix matrix) {}
+
+ public int[] getLocationOnScreen() {
+ return null;
+ }
+
+ public void getLocationOnScreen(int[] outLocation) {}
+
+ public void getLocationInWindow(int[] outLocation) {}
+
+ public void transformFromViewToWindowSpace(int[] inOutLocation) {}
+
+ public final T findViewById(int id) {
+ return null;
+ }
+
+ public final T requireViewById(int id) {
+ return null;
+ }
+
+ public T findViewByAccessibilityIdTraversal(int accessibilityId) {
+ return null;
+ }
+
+ public T findViewByAutofillIdTraversal(int autofillId) {
+ return null;
+ }
+
+ public final T findViewWithTag(Object tag) {
+ return null;
+ }
+
+ public final T findViewByPredicate(Predicate predicate) {
+ return null;
+ }
+
+ public final T findViewByPredicateInsideOut(View start,
+ Predicate predicate) {
+ return null;
+ }
+
+ public void setId(int id) {}
+
+ public void setIsRootNamespace(boolean isRoot) {}
+
+ public boolean isRootNamespace() {
+ return false;
+ }
+
+ public int getId() {
+ return 0;
+ }
+
+ public long getUniqueDrawingId() {
+ return 0;
+ }
+
+ public Object getTag() {
+ return null;
+ }
+
+ public void setTag(final Object tag) {}
+
+ public Object getTag(int key) {
+ return null;
+ }
+
+ public void setTag(int key, final Object tag) {}
+
+ public void setTagInternal(int key, Object tag) {}
+
+ public void debug() {}
+
+ public int getBaseline() {
+ return 0;
+ }
+
+ public boolean isInLayout() {
+ return false;
+ }
+
+ public void requestLayout() {}
+
+ public void forceLayout() {}
+
+ public final void measure(int widthMeasureSpec, int heightMeasureSpec) {}
+
+ public static int combineMeasuredStates(int curState, int newState) {
+ return 0;
+ }
+
+ public static int resolveSize(int size, int measureSpec) {
+ return 0;
+ }
+
+ public static int resolveSizeAndState(int size, int measureSpec, int childMeasuredState) {
+ return 0;
+ }
+
+ public static int getDefaultSize(int size, int measureSpec) {
+ return 0;
+ }
+
+ public int getMinimumHeight() {
+ return 0;
+ }
+
+ public void setMinimumHeight(int minHeight) {}
+
+ public int getMinimumWidth() {
+ return 0;
+ }
+
+ public void setMinimumWidth(int minWidth) {}
+
+ public void clearAnimation() {}
+
+ public boolean gatherTransparentRegion(Region region) {
+ return false;
+ }
+
+ public void playSoundEffect(int soundConstant) {}
+
+ public boolean performHapticFeedback(int feedbackConstant) {
+ return false;
+ }
+
+ public boolean performHapticFeedback(int feedbackConstant, int flags) {
+ return false;
+ }
+
+ public void setSystemUiVisibility(int visibility) {}
+
+ public int getSystemUiVisibility() {
+ return 0;
+ }
+
+ public int getWindowSystemUiVisibility() {
+ return 0;
+ }
+
+ public void onWindowSystemUiVisibilityChanged(int visible) {}
+
+ public void dispatchWindowSystemUiVisiblityChanged(int visible) {}
+
+ public void setOnSystemUiVisibilityChangeListener(OnSystemUiVisibilityChangeListener l) {}
+
+ public void dispatchSystemUiVisibilityChanged(int visibility) {}
+
+ public void setDisabledSystemUiVisibility(int flags) {}
+
+ public static class DragShadowBuilder {
+ public DragShadowBuilder(View view) {}
+
+ public DragShadowBuilder() {}
+
+ final public View getView() {
+ return null;
+ }
+
+ public void onProvideShadowMetrics(Point outShadowSize, Point outShadowTouchPoint) {}
+
+ public void onDrawShadow(Canvas canvas) {}
+
+ }
+
+ public final boolean startDrag(ClipData data, DragShadowBuilder shadowBuilder,
+ Object myLocalState, int flags) {
+ return false;
+ }
+
+ public final boolean startDragAndDrop(ClipData data, DragShadowBuilder shadowBuilder,
+ Object myLocalState, int flags) {
+ return false;
+ }
+
+ public final void cancelDragAndDrop() {}
+
+ public final void updateDragShadow(DragShadowBuilder shadowBuilder) {}
+
+ public final boolean startMovingTask(float startX, float startY) {
+ return false;
+ }
+
+ public void finishMovingTask() {}
+
+
+ public void onCloseSystemDialogs(String reason) {}
+
+ public void applyDrawableToTransparentRegion(Drawable dr, Region region) {}
+
+ public int getOverScrollMode() {
+ return 0;
+ }
+
+ public void setOverScrollMode(int overScrollMode) {}
+
+ public void setNestedScrollingEnabled(boolean enabled) {}
+
+ public boolean isNestedScrollingEnabled() {
+ return false;
+ }
+
+ public boolean startNestedScroll(int axes) {
+ return false;
+ }
+
+ public void stopNestedScroll() {}
+
+ public boolean hasNestedScrollingParent() {
+ return false;
+ }
+
+ public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
+ int dyUnconsumed, int[] offsetInWindow) {
+ return false;
+ }
+
+ public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow) {
+ return false;
+ }
+
+ public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
+ return false;
+ }
+
+ public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
+ return false;
+ }
+
+ public int getRawTextDirection() {
+ return 0;
+ }
+
+ public void setTextDirection(int textDirection) {}
+
+ public int getTextDirection() {
+ return 0;
+ }
+
+ public boolean resolveTextDirection() {
+ return false;
+ }
+
+ public boolean canResolveTextDirection() {
+ return false;
+ }
+
+ public void resetResolvedTextDirection() {}
+
+ public boolean isTextDirectionInherited() {
+ return false;
+ }
+
+ public boolean isTextDirectionResolved() {
+ return false;
+ }
+
+ public int getRawTextAlignment() {
+ return 0;
+ }
+
+ public void setTextAlignment(int textAlignment) {}
+
+ public int getTextAlignment() {
+ return 0;
+ }
+
+ public boolean resolveTextAlignment() {
+ return false;
+ }
+
+ public boolean canResolveTextAlignment() {
+ return false;
+ }
+
+ public void resetResolvedTextAlignment() {}
+
+ public boolean isTextAlignmentInherited() {
+ return false;
+ }
+
+ public boolean isTextAlignmentResolved() {
+ return false;
+ }
+
+ public static int generateViewId() {
+ return 0;
+ }
+
+ public void captureTransitioningViews(List transitioningViews) {}
+
+ public void findNamedViews(Map namedElements) {}
+
+ public boolean hasPointerCapture() {
+ return false;
+ }
+
+ public void requestPointerCapture() {}
+
+ public void releasePointerCapture() {}
+
+ public void onPointerCaptureChange(boolean hasCapture) {}
+
+ public void dispatchPointerCaptureChanged(boolean hasCapture) {}
+
+ public static class MeasureSpec {
+ public @interface MeasureSpecMode {
+ }
+
+ public static int makeMeasureSpec(int size, int mode) {
+ return 0;
+ }
+
+ public static int makeSafeMeasureSpec(int size, int mode) {
+ return 0;
+ }
+
+ public static int getMode(int measureSpec) {
+ return 0;
+ }
+
+ public static int getSize(int measureSpec) {
+ return 0;
+ }
+
+ public static String toString(int measureSpec) {
+ return null;
+ }
+
+ }
+
+ public final void setTransitionName(String transitionName) {}
+
+ public String getTransitionName() {
+ return null;
+ }
+
+ public interface OnLongClickListener {
+ boolean onLongClick(View v);
+
+ }
+
+ public interface OnFocusChangeListener {
+ void onFocusChange(View v, boolean hasFocus);
+
+ }
+ public interface OnClickListener {
+ void onClick(View v);
+ }
+ public interface OnContextClickListener {
+ boolean onContextClick(View v);
+
+ }
+
+ public interface OnSystemUiVisibilityChangeListener {
+ public void onSystemUiVisibilityChange(int visibility);
+
+ }
+ public interface OnAttachStateChangeListener {
+ public void onViewAttachedToWindow(View v);
+
+ public void onViewDetachedFromWindow(View v);
+
+ }
+
+ public static class BaseSavedState {
+ public BaseSavedState(Parcel source) {}
+
+ public BaseSavedState(Parcel source, ClassLoader loader) {}
+
+ public BaseSavedState(Parcelable superState) {}
+
+ public void writeToParcel(Parcel out, int flags) {}
+
+ }
+ public static class AccessibilityDelegate {
+ public void sendAccessibilityEvent(View host, int eventType) {}
+
+ public boolean performAccessibilityAction(View host, int action, Bundle args) {
+ return false;
+ }
+ }
+
+ public int getScrollCaptureHint() {
+ return 0;
+ }
+
+ public void setScrollCaptureHint(int hint) {}
+
+ public void setTooltipText(CharSequence tooltipText) {}
+
+ public void setTooltip(CharSequence tooltipText) {}
+
+ public CharSequence getTooltipText() {
+ return null;
+ }
+
+ public CharSequence getTooltip() {
+ return null;
+ }
+
+ public View getTooltipView() {
+ return null;
+ }
+
+ public static boolean isDefaultFocusHighlightEnabled() {
+ return false;
+>>>>>>> 1014462ed3 (Add stubs)
}
}
From 211cb9370f9592b511a7ea459db004f6534b2db7 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Tue, 26 Oct 2021 10:43:10 +0200
Subject: [PATCH 083/196] Add the Intent parameter of onActivityResult as a
source
---
.../semmle/code/java/dataflow/FlowSources.qll | 11 +++
.../code/java/frameworks/android/Fragment.qll | 10 ++-
.../android/OnActivityResultSource.qll | 70 +++++++++++++++++++
.../OnActivityResultSourceTest.expected | 0
.../sources/OnActivityResultSourceTest.ql | 11 +++
.../frameworks/android/sources/Safe.java | 21 ++++++
.../frameworks/android/sources/Safe2.java | 20 ++++++
.../frameworks/android/sources/Test.java | 21 ++++++
.../android/sources/TestFragment.java | 22 ++++++
.../android/sources/TestMissing.java | 28 ++++++++
.../frameworks/android/sources/options | 1 +
.../android/app/Fragment.java | 6 ++
12 files changed, 215 insertions(+), 6 deletions(-)
create mode 100644 java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/Safe.java
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/Safe2.java
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/Test.java
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/TestFragment.java
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/TestMissing.java
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/options
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
index d8d02f995a6..289a5a6d906 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
@@ -17,6 +17,7 @@ import semmle.code.java.frameworks.android.WebView
import semmle.code.java.frameworks.JaxWS
import semmle.code.java.frameworks.javase.WebSocket
import semmle.code.java.frameworks.android.Android
+import semmle.code.java.frameworks.android.OnActivityResultSource
import semmle.code.java.frameworks.android.Intent
import semmle.code.java.frameworks.play.Play
import semmle.code.java.frameworks.spring.SpringWeb
@@ -264,3 +265,13 @@ class ExportedAndroidContentProviderInput extends RemoteFlowSource, AndroidConte
override string getSourceType() { result = "Exported Android content provider source" }
}
+
+/**
+ * The data Intent parameter in the `onActivityResult` method in an Activity or Fragment that
+ * calls `startActivityForResult` with an implicit Intent.
+ */
+class OnActivityResultIntentSource extends OnActivityResultIncomingIntent, RemoteFlowSource {
+ OnActivityResultIntentSource() { isRemoteSource() }
+
+ override string getSourceType() { result = "Android onActivityResult incoming Intent" }
+}
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
index 528162fe4d4..76aa630ce47 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
@@ -1,16 +1,14 @@
-/** Provides classes and predicates to track Android fragments. */
-
import java
-/** The class `android.app.Fragment` */
-class Fragment extends Class {
- Fragment() { this.hasQualifiedName("android.app", "Fragment") }
+/** An Android Fragment. */
+class AndroidFragment extends Class {
+ AndroidFragment() { this.getASupertype*().hasQualifiedName("android.app", "Fragment") }
}
/** The method `instantiate` of the class `android.app.Fragment`. */
class FragmentInstantiateMethod extends Method {
FragmentInstantiateMethod() {
- this.getDeclaringType() instanceof Fragment and
+ this.getDeclaringType() instanceof AndroidFragment and
this.hasName("instantiate")
}
}
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
new file mode 100644
index 00000000000..21b02b0879c
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -0,0 +1,70 @@
+/** Provides a remote flow source for Android's `Activity.onActivityResult` method. */
+
+import java
+private import semmle.code.java.dataflow.DataFlow
+private import semmle.code.java.dataflow.DataFlow5
+private import semmle.code.java.frameworks.android.Android
+private import semmle.code.java.frameworks.android.Fragment
+private import semmle.code.java.frameworks.android.Intent
+
+/**
+ * The data Intent parameter in the `onActivityResult` method.
+ */
+class OnActivityResultIncomingIntent extends DataFlow::Node {
+ OnActivityResultIncomingIntent() {
+ exists(Method onActivityResult |
+ onActivityResult.getDeclaringType() instanceof ActivityOrFragment and
+ onActivityResult.hasName("onActivityResult") and
+ this.asParameter() = onActivityResult.getParameter(2)
+ )
+ }
+
+ /**
+ * Holds if this node is a remote flow source.
+ *
+ * This is only a source when the Activity or Fragment that implements `onActivityResult` is
+ * also using an implicit Intent to start another Activity with `startActivityForResult`. This
+ * means that a malicious application can intercept it to start itself and return an arbitrary
+ * Intent to `onActivityResult`.
+ */
+ predicate isRemoteSource() {
+ exists(ImplicitStartActivityForResultConf conf, DataFlow::Node sink |
+ conf.hasFlowTo(sink) and
+ DataFlow::getInstanceArgument(sink.asExpr().(Argument).getCall()).getType() =
+ this.getEnclosingCallable().getDeclaringType()
+ )
+ }
+}
+
+/**
+ * A data flow configuration for implicit intents being used in `startActivityForResult`.
+ */
+private class ImplicitStartActivityForResultConf extends DataFlow5::Configuration {
+ ImplicitStartActivityForResultConf() { this = "ImplicitStartActivityForResultConf" }
+
+ override predicate isSource(DataFlow::Node source) {
+ exists(ClassInstanceExpr cc |
+ cc.getConstructedType() instanceof TypeIntent and source.asExpr() = cc
+ )
+ }
+
+ override predicate isSink(DataFlow::Node sink) {
+ exists(ActivityOrFragment actOrFrag, MethodAccess startActivityForResult |
+ startActivityForResult.getMethod().hasName("startActivityForResult") and
+ startActivityForResult.getEnclosingCallable() = actOrFrag.getACallable() and
+ sink.asExpr() = startActivityForResult.getArgument(0)
+ )
+ }
+
+ override predicate isBarrier(DataFlow::Node barrier) {
+ barrier instanceof ExplicitIntentSanitizer
+ }
+}
+
+/** An Android Activity or Fragment. */
+private class ActivityOrFragment extends Class {
+ ActivityOrFragment() {
+ this instanceof AndroidActivity or
+ this instanceof AndroidFragment
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.expected
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql
new file mode 100644
index 00000000000..77821961902
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/OnActivityResultSourceTest.ql
@@ -0,0 +1,11 @@
+import java
+import semmle.code.java.dataflow.FlowSources
+import TestUtilities.InlineFlowTest
+
+class SourceValueFlowConf extends DefaultValueFlowConf {
+ override predicate isSource(DataFlow::Node sink) { sink instanceof RemoteFlowSource }
+}
+
+class SourceInlineFlowTest extends InlineFlowTest {
+ override DataFlow::Configuration getTaintFlowConfig() { none() }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/Safe.java b/java/ql/test/library-tests/frameworks/android/sources/Safe.java
new file mode 100644
index 00000000000..7a213f5edb0
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/Safe.java
@@ -0,0 +1,21 @@
+package com.example.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class Safe extends Activity {
+
+ void sink(Object o) {}
+
+ public void onCreate(Bundle saved) {
+ Intent explicitIntent = new Intent(this, Activity.class);
+ startActivityForResult(explicitIntent, 0);
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ sink(requestCode); // safe
+ sink(resultCode); // safe
+ sink(data); // Safe
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/Safe2.java b/java/ql/test/library-tests/frameworks/android/sources/Safe2.java
new file mode 100644
index 00000000000..9a2e4a6074f
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/Safe2.java
@@ -0,0 +1,20 @@
+package com.example.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class Safe2 extends Activity {
+
+ void sink(Object o) {}
+
+ public void onCreate(Bundle saved) {
+ // activityForResult not called
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ sink(requestCode); // safe
+ sink(resultCode); // safe
+ sink(data); // Safe
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/Test.java b/java/ql/test/library-tests/frameworks/android/sources/Test.java
new file mode 100644
index 00000000000..ee694ef7697
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/Test.java
@@ -0,0 +1,21 @@
+package com.example.app;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class Test extends Activity {
+
+ void sink(Object o) {}
+
+ public void onCreate(Bundle saved) {
+ Intent implicitIntent = new Intent("SOME_ACTION");
+ startActivityForResult(implicitIntent, 0);
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ sink(requestCode); // safe
+ sink(resultCode); // safe
+ sink(data); // $ hasValueFlow
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/TestFragment.java b/java/ql/test/library-tests/frameworks/android/sources/TestFragment.java
new file mode 100644
index 00000000000..a2073f9b781
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/TestFragment.java
@@ -0,0 +1,22 @@
+package com.example.app;
+
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class TestFragment extends Fragment {
+
+ void sink(Object o) {}
+
+ public void onCreate(Bundle savedInstance) {
+ Intent implicitIntent = new Intent("SOME_ACTION");
+ startActivityForResult(implicitIntent, 0);
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ sink(requestCode); // safe
+ sink(resultCode); // safe
+ sink(data); // $ hasValueFlow
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/TestMissing.java b/java/ql/test/library-tests/frameworks/android/sources/TestMissing.java
new file mode 100644
index 00000000000..4dbbfd9ca24
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/TestMissing.java
@@ -0,0 +1,28 @@
+package com.example.app;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+
+public class TestMissing extends Activity {
+
+ void sink(Object o) {}
+
+ public void onCreate(Bundle saved) {
+ Helper.startNewActivity(this);
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ sink(requestCode); // safe
+ sink(resultCode); // safe
+ sink(data); // $ MISSING: $hasValueFlow
+ }
+
+ static class Helper {
+ public static void startNewActivity(Activity ctx) {
+ Intent implicitIntent = new Intent("SOME_ACTION");
+ ctx.startActivityForResult(implicitIntent, 0);
+ }
+ }
+}
diff --git a/java/ql/test/library-tests/frameworks/android/sources/options b/java/ql/test/library-tests/frameworks/android/sources/options
new file mode 100644
index 00000000000..33cdc1ea940
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/options
@@ -0,0 +1 @@
+//semmle-extractor-options: --javac-args -cp ${testdir}/../../../../stubs/google-android-9.0.0
diff --git a/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java b/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java
index 2ebe4db7e13..5e5f71dcd25 100644
--- a/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java
+++ b/java/ql/test/stubs/google-android-9.0.0/android/app/Fragment.java
@@ -17,6 +17,7 @@ package android.app;
import android.annotation.Nullable;
import android.content.ComponentCallbacks2;
import android.content.Context;
+import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Parcel;
@@ -73,4 +74,9 @@ public class Fragment implements ComponentCallbacks2 {
@Override
public void onTrimMemory(int p0) {}
+ public void startActivityForResult(Intent intent, int requestCode) {}
+
+ public void startActivityForResult(Intent intent, int requestCode, Bundle options) {}
+
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {}
}
From 9ae1f1cf857e06b7b77cc3f7e67aaf262ea7daef Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Tue, 26 Oct 2021 11:26:32 +0200
Subject: [PATCH 084/196] QLDoc
---
java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll | 2 ++
1 file changed, 2 insertions(+)
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
index 76aa630ce47..f5484017393 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
@@ -1,3 +1,5 @@
+/** Provides classes and predicates related to Android Fragments. */
+
import java
/** An Android Fragment. */
From c67502853759f669393e4f113e356866b2830296 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Tue, 9 Nov 2021 17:23:16 +0100
Subject: [PATCH 085/196] Add Fragment and Activity edge case
---
.../android/OnActivityResultSource.qll | 48 +++++++++++++++++--
.../sources/TestActivityAndFragment.java | 32 +++++++++++++
2 files changed, 75 insertions(+), 5 deletions(-)
create mode 100644 java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
index 21b02b0879c..3a637f35510 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -28,10 +28,26 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
* Intent to `onActivityResult`.
*/
predicate isRemoteSource() {
- exists(ImplicitStartActivityForResultConf conf, DataFlow::Node sink |
+ exists(ImplicitStartActivityForResultConf conf, RefType startingType, DataFlow::Node sink |
conf.hasFlowTo(sink) and
- DataFlow::getInstanceArgument(sink.asExpr().(Argument).getCall()).getType() =
- this.getEnclosingCallable().getDeclaringType()
+ startingType = sink.asExpr().(Argument).getCall().getEnclosingCallable().getDeclaringType()
+ |
+ startingType = this.getEnclosingCallable().getDeclaringType()
+ or
+ // A fragment calls `startActivityForResult`
+ // and the activity it belongs to defines `onActivityResult`.
+ exists(MethodAccess ma |
+ ma.getMethod().hasName(["add", "attach", "replace"]) and
+ ma.getMethod().getDeclaringType().hasName("FragmentTransaction") and
+ any(Argument arg | arg = ma.getAnArgument()).getType() = startingType
+ or
+ ma.getMethod().hasName("show") and
+ ma.getMethod().getDeclaringType().getASupertype*().hasName("DialogFragment") and
+ startingType = ma.getQualifier().getType()
+ |
+ ma.getEnclosingCallable().getDeclaringType() =
+ this.getEnclosingCallable().getDeclaringType()
+ )
)
}
}
@@ -49,9 +65,10 @@ private class ImplicitStartActivityForResultConf extends DataFlow5::Configuratio
}
override predicate isSink(DataFlow::Node sink) {
- exists(ActivityOrFragment actOrFrag, MethodAccess startActivityForResult |
+ exists(MethodAccess startActivityForResult |
startActivityForResult.getMethod().hasName("startActivityForResult") and
- startActivityForResult.getEnclosingCallable() = actOrFrag.getACallable() and
+ startActivityForResult.getMethod().getDeclaringType().getASupertype*() instanceof
+ ActivityOrFragment and
sink.asExpr() = startActivityForResult.getArgument(0)
)
}
@@ -59,6 +76,27 @@ private class ImplicitStartActivityForResultConf extends DataFlow5::Configuratio
override predicate isBarrier(DataFlow::Node barrier) {
barrier instanceof ExplicitIntentSanitizer
}
+
+ override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
+ // Wrapping the Intent in a chooser
+ exists(MethodAccess ma, Method m |
+ ma.getMethod() = m and
+ m.hasName("createChooser") and
+ m.getDeclaringType() instanceof TypeIntent
+ |
+ node1.asExpr() = ma.getArgument(0) and
+ node2.asExpr() = ma
+ )
+ or
+ // Using the copy constructor
+ exists(ClassInstanceExpr cie |
+ cie.getConstructedType() instanceof TypeIntent and
+ cie.getArgument(0).getType() instanceof TypeIntent
+ |
+ node1.asExpr() = cie.getArgument(0) and
+ node2.asExpr() = cie
+ )
+ }
}
/** An Android Activity or Fragment. */
diff --git a/java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java b/java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java
new file mode 100644
index 00000000000..bfa657c6d00
--- /dev/null
+++ b/java/ql/test/library-tests/frameworks/android/sources/TestActivityAndFragment.java
@@ -0,0 +1,32 @@
+import android.app.Activity;
+import android.app.Fragment;
+import android.content.Intent;
+import android.os.Bundle;
+import androidx.fragment.app.FragmentTransaction;
+
+public class TestActivityAndFragment extends Activity {
+
+ private TestFragment frag;
+
+ void sink(Object o) {}
+
+ public void onCreate(Bundle saved) {
+ FragmentTransaction ft = null;
+ ft.add(0, frag);
+
+ }
+
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ sink(requestCode); // safe
+ sink(resultCode); // safe
+ sink(data); // $ hasValueFlow
+ }
+
+ private class TestFragment extends Fragment {
+ public void onCreate(Bundle savedInstance) {
+ Intent implicitIntent = new Intent("SOME_ACTION");
+ startActivityForResult(implicitIntent, 0);
+ }
+
+ }
+}
From 4b3029564cec887f460e424f947aaf1a47650e3e Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 17 Jan 2022 09:27:16 +0100
Subject: [PATCH 086/196] Apply suggestions from code review
Co-authored-by: Chris Smowton
---
.../lib/semmle/code/java/frameworks/android/Fragment.qll | 2 +-
.../java/frameworks/android/OnActivityResultSource.qll | 8 +++++---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
index f5484017393..c003c908900 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
@@ -2,7 +2,7 @@
import java
-/** An Android Fragment. */
+/** The class `android.app.Fragment`. */
class AndroidFragment extends Class {
AndroidFragment() { this.getASupertype*().hasQualifiedName("android.app", "Fragment") }
}
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
index 3a637f35510..5797b81f4a6 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -28,10 +28,12 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
* Intent to `onActivityResult`.
*/
predicate isRemoteSource() {
- exists(ImplicitStartActivityForResultConf conf, RefType startingType, DataFlow::Node sink |
- conf.hasFlowTo(sink) and
- startingType = sink.asExpr().(Argument).getCall().getEnclosingCallable().getDeclaringType()
+ exists(ImplicitStartActivityForResultConf conf, RefType startingType, Expr startActivityForResultArg |
+ conf.hasFlowToExpr(startActivityForResultArg) and
+ // startingType is the class enclosing the method that calls `startActivityForResult`.
+ startingType = startActivityForResultArg.getEnclosingCallable().getDeclaringType()
|
+ // startingType itself defines an `onActivityResult` method:
startingType = this.getEnclosingCallable().getDeclaringType()
or
// A fragment calls `startActivityForResult`
From aef63f69b00013500c8e31d96e26386adeb60668 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 17 Jan 2022 12:16:24 +0100
Subject: [PATCH 087/196] Formatting
---
.../code/java/frameworks/android/OnActivityResultSource.qll | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
index 5797b81f4a6..65f971d64ec 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -28,7 +28,9 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
* Intent to `onActivityResult`.
*/
predicate isRemoteSource() {
- exists(ImplicitStartActivityForResultConf conf, RefType startingType, Expr startActivityForResultArg |
+ exists(
+ ImplicitStartActivityForResultConf conf, RefType startingType, Expr startActivityForResultArg
+ |
conf.hasFlowToExpr(startActivityForResultArg) and
// startingType is the class enclosing the method that calls `startActivityForResult`.
startingType = startActivityForResultArg.getEnclosingCallable().getDeclaringType()
From d9d9ad7d63012a32a713d097d64548d48b82d177 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 17 Jan 2022 16:24:39 +0100
Subject: [PATCH 088/196] Use dedicated instance of DataFlow
---
.../internal/DataFlowForOnActivityResult.qll | 19 +
.../DataFlowImplForOnActivityResult.qll | 4656 +++++++++++++++++
.../android/OnActivityResultSource.qll | 4 +-
3 files changed, 4677 insertions(+), 2 deletions(-)
create mode 100644 java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll
create mode 100644 java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll
new file mode 100644
index 00000000000..b66c1aa3c2f
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowForOnActivityResult.qll
@@ -0,0 +1,19 @@
+/**
+ * Provides classes for performing local (intra-procedural) and
+ * global (inter-procedural) data flow analyses (for internal use only).
+ *
+ * This copy of the library is exclusively for use by `OnActivityResultSource.qll` and
+ * related libraries. Configurations computed using this instance of the library
+ * are in scope whenever `java.qll` is imported, and are used to compute among
+ * other things `RemoteFlowSource`s.
+ */
+
+import java
+
+/**
+ * Provides classes for performing local (intra-procedural) and
+ * global (inter-procedural) data flow analyses (for internal use only).
+ */
+module DataFlowForOnActivityResult {
+ import semmle.code.java.dataflow.internal.DataFlowImplForOnActivityResult
+}
diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
new file mode 100644
index 00000000000..4daf617a404
--- /dev/null
+++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
@@ -0,0 +1,4656 @@
+/**
+ * Provides an implementation of global (interprocedural) data flow. This file
+ * re-exports the local (intraprocedural) data flow analysis from
+ * `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed
+ * through the `Configuration` class. This file exists in several identical
+ * copies, allowing queries to use multiple `Configuration` classes that depend
+ * on each other without introducing mutual recursion among those configurations.
+ */
+
+private import DataFlowImplCommon
+private import DataFlowImplSpecific::Private
+import DataFlowImplSpecific::Public
+import DataFlowImplCommonPublic
+
+/**
+ * A configuration of interprocedural data flow analysis. This defines
+ * sources, sinks, and any other configurable aspect of the analysis. Each
+ * use of the global data flow library must define its own unique extension
+ * of this abstract class. To create a configuration, extend this class with
+ * a subclass whose characteristic predicate is a unique singleton string.
+ * For example, write
+ *
+ * ```ql
+ * class MyAnalysisConfiguration extends DataFlow::Configuration {
+ * MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
+ * // Override `isSource` and `isSink`.
+ * // Optionally override `isBarrier`.
+ * // Optionally override `isAdditionalFlowStep`.
+ * }
+ * ```
+ * Conceptually, this defines a graph where the nodes are `DataFlow::Node`s and
+ * the edges are those data-flow steps that preserve the value of the node
+ * along with any additional edges defined by `isAdditionalFlowStep`.
+ * Specifying nodes in `isBarrier` will remove those nodes from the graph, and
+ * specifying nodes in `isBarrierIn` and/or `isBarrierOut` will remove in-going
+ * and/or out-going edges from those nodes, respectively.
+ *
+ * Then, to query whether there is flow between some `source` and `sink`,
+ * write
+ *
+ * ```ql
+ * exists(MyAnalysisConfiguration cfg | cfg.hasFlow(source, sink))
+ * ```
+ *
+ * Multiple configurations can coexist, but two classes extending
+ * `DataFlow::Configuration` should never depend on each other. One of them
+ * should instead depend on a `DataFlow2::Configuration`, a
+ * `DataFlow3::Configuration`, or a `DataFlow4::Configuration`.
+ */
+abstract class Configuration extends string {
+ bindingset[this]
+ Configuration() { any() }
+
+ /**
+ * Holds if `source` is a relevant data flow source.
+ */
+ abstract predicate isSource(Node source);
+
+ /**
+ * Holds if `sink` is a relevant data flow sink.
+ */
+ abstract predicate isSink(Node sink);
+
+ /**
+ * Holds if data flow through `node` is prohibited. This completely removes
+ * `node` from the data flow graph.
+ */
+ predicate isBarrier(Node node) { none() }
+
+ /** Holds if data flow into `node` is prohibited. */
+ predicate isBarrierIn(Node node) { none() }
+
+ /** Holds if data flow out of `node` is prohibited. */
+ predicate isBarrierOut(Node node) { none() }
+
+ /** Holds if data flow through nodes guarded by `guard` is prohibited. */
+ predicate isBarrierGuard(BarrierGuard guard) { none() }
+
+ /**
+ * Holds if the additional flow step from `node1` to `node2` must be taken
+ * into account in the analysis.
+ */
+ predicate isAdditionalFlowStep(Node node1, Node node2) { none() }
+
+ /**
+ * Holds if an arbitrary number of implicit read steps of content `c` may be
+ * taken at `node`.
+ */
+ predicate allowImplicitRead(Node node, Content c) { none() }
+
+ /**
+ * Gets the virtual dispatch branching limit when calculating field flow.
+ * This can be overridden to a smaller value to improve performance (a
+ * value of 0 disables field flow), or a larger value to get more results.
+ */
+ int fieldFlowBranchLimit() { result = 2 }
+
+ /**
+ * Gets a data flow configuration feature to add restrictions to the set of
+ * valid flow paths.
+ *
+ * - `FeatureHasSourceCallContext`:
+ * Assume that sources have some existing call context to disallow
+ * conflicting return-flow directly following the source.
+ * - `FeatureHasSinkCallContext`:
+ * Assume that sinks have some existing call context to disallow
+ * conflicting argument-to-parameter flow directly preceding the sink.
+ * - `FeatureEqualSourceSinkCallContext`:
+ * Implies both of the above and additionally ensures that the entire flow
+ * path preserves the call context.
+ */
+ FlowFeature getAFeature() { none() }
+
+ /**
+ * Holds if data may flow from `source` to `sink` for this configuration.
+ */
+ predicate hasFlow(Node source, Node sink) { flowsTo(source, sink, this) }
+
+ /**
+ * Holds if data may flow from `source` to `sink` for this configuration.
+ *
+ * The corresponding paths are generated from the end-points and the graph
+ * included in the module `PathGraph`.
+ */
+ predicate hasFlowPath(PathNode source, PathNode sink) { flowsTo(source, sink, _, _, this) }
+
+ /**
+ * Holds if data may flow from some source to `sink` for this configuration.
+ */
+ predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
+
+ /**
+ * Holds if data may flow from some source to `sink` for this configuration.
+ */
+ predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
+
+ /**
+ * Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
+ * measured in approximate number of interprocedural steps.
+ */
+ int explorationLimit() { none() }
+
+ /**
+ * Holds if there is a partial data flow path from `source` to `node`. The
+ * approximate distance between `node` and the closest source is `dist` and
+ * is restricted to be less than or equal to `explorationLimit()`. This
+ * predicate completely disregards sink definitions.
+ *
+ * This predicate is intended for data-flow exploration and debugging and may
+ * perform poorly if the number of sources is too big and/or the exploration
+ * limit is set too high without using barriers.
+ *
+ * This predicate is disabled (has no results) by default. Override
+ * `explorationLimit()` with a suitable number to enable this predicate.
+ *
+ * To use this in a `path-problem` query, import the module `PartialPathGraph`.
+ */
+ final predicate hasPartialFlow(PartialPathNode source, PartialPathNode node, int dist) {
+ partialFlow(source, node, this) and
+ dist = node.getSourceDistance()
+ }
+
+ /**
+ * Holds if there is a partial data flow path from `node` to `sink`. The
+ * approximate distance between `node` and the closest sink is `dist` and
+ * is restricted to be less than or equal to `explorationLimit()`. This
+ * predicate completely disregards source definitions.
+ *
+ * This predicate is intended for data-flow exploration and debugging and may
+ * perform poorly if the number of sinks is too big and/or the exploration
+ * limit is set too high without using barriers.
+ *
+ * This predicate is disabled (has no results) by default. Override
+ * `explorationLimit()` with a suitable number to enable this predicate.
+ *
+ * To use this in a `path-problem` query, import the module `PartialPathGraph`.
+ *
+ * Note that reverse flow has slightly lower precision than the corresponding
+ * forward flow, as reverse flow disregards type pruning among other features.
+ */
+ final predicate hasPartialFlowRev(PartialPathNode node, PartialPathNode sink, int dist) {
+ revPartialFlow(node, sink, this) and
+ dist = node.getSinkDistance()
+ }
+}
+
+/**
+ * This class exists to prevent mutual recursion between the user-overridden
+ * member predicates of `Configuration` and the rest of the data-flow library.
+ * Good performance cannot be guaranteed in the presence of such recursion, so
+ * it should be replaced by using more than one copy of the data flow library.
+ */
+abstract private class ConfigurationRecursionPrevention extends Configuration {
+ bindingset[this]
+ ConfigurationRecursionPrevention() { any() }
+
+ override predicate hasFlow(Node source, Node sink) {
+ strictcount(Node n | this.isSource(n)) < 0
+ or
+ strictcount(Node n | this.isSink(n)) < 0
+ or
+ strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0
+ or
+ super.hasFlow(source, sink)
+ }
+}
+
+private newtype TNodeEx =
+ TNodeNormal(Node n) or
+ TNodeImplicitRead(Node n, boolean hasRead) {
+ any(Configuration c).allowImplicitRead(n, _) and hasRead = [false, true]
+ }
+
+private class NodeEx extends TNodeEx {
+ string toString() {
+ result = this.asNode().toString()
+ or
+ exists(Node n | this.isImplicitReadNode(n, _) | result = n.toString() + " [Ext]")
+ }
+
+ Node asNode() { this = TNodeNormal(result) }
+
+ predicate isImplicitReadNode(Node n, boolean hasRead) { this = TNodeImplicitRead(n, hasRead) }
+
+ Node projectToNode() { this = TNodeNormal(result) or this = TNodeImplicitRead(result, _) }
+
+ pragma[nomagic]
+ private DataFlowCallable getEnclosingCallable0() {
+ nodeEnclosingCallable(this.projectToNode(), result)
+ }
+
+ pragma[inline]
+ DataFlowCallable getEnclosingCallable() {
+ pragma[only_bind_out](this).getEnclosingCallable0() = pragma[only_bind_into](result)
+ }
+
+ pragma[nomagic]
+ private DataFlowType getDataFlowType0() { nodeDataFlowType(this.asNode(), result) }
+
+ pragma[inline]
+ DataFlowType getDataFlowType() {
+ pragma[only_bind_out](this).getDataFlowType0() = pragma[only_bind_into](result)
+ }
+
+ predicate hasLocationInfo(
+ string filepath, int startline, int startcolumn, int endline, int endcolumn
+ ) {
+ this.projectToNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
+ }
+}
+
+private class ArgNodeEx extends NodeEx {
+ ArgNodeEx() { this.asNode() instanceof ArgNode }
+}
+
+private class ParamNodeEx extends NodeEx {
+ ParamNodeEx() { this.asNode() instanceof ParamNode }
+
+ predicate isParameterOf(DataFlowCallable c, int i) {
+ this.asNode().(ParamNode).isParameterOf(c, i)
+ }
+
+ int getPosition() { this.isParameterOf(_, result) }
+
+ predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
+}
+
+private class RetNodeEx extends NodeEx {
+ RetNodeEx() { this.asNode() instanceof ReturnNodeExt }
+
+ ReturnPosition getReturnPosition() { result = getReturnPosition(this.asNode()) }
+
+ ReturnKindExt getKind() { result = this.asNode().(ReturnNodeExt).getKind() }
+}
+
+private predicate inBarrier(NodeEx node, Configuration config) {
+ exists(Node n |
+ node.asNode() = n and
+ config.isBarrierIn(n) and
+ config.isSource(n)
+ )
+}
+
+private predicate outBarrier(NodeEx node, Configuration config) {
+ exists(Node n |
+ node.asNode() = n and
+ config.isBarrierOut(n) and
+ config.isSink(n)
+ )
+}
+
+private predicate fullBarrier(NodeEx node, Configuration config) {
+ exists(Node n | node.asNode() = n |
+ config.isBarrier(n)
+ or
+ config.isBarrierIn(n) and
+ not config.isSource(n)
+ or
+ config.isBarrierOut(n) and
+ not config.isSink(n)
+ or
+ exists(BarrierGuard g |
+ config.isBarrierGuard(g) and
+ n = g.getAGuardedNode()
+ )
+ )
+}
+
+pragma[nomagic]
+private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
+
+pragma[nomagic]
+private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
+
+/**
+ * Holds if data can flow in one local step from `node1` to `node2`.
+ */
+private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config) {
+ exists(Node n1, Node n2 |
+ node1.asNode() = n1 and
+ node2.asNode() = n2 and
+ simpleLocalFlowStepExt(n1, n2) and
+ not outBarrier(node1, config) and
+ not inBarrier(node2, config) and
+ not fullBarrier(node1, config) and
+ not fullBarrier(node2, config)
+ )
+ or
+ exists(Node n |
+ config.allowImplicitRead(n, _) and
+ node1.asNode() = n and
+ node2.isImplicitReadNode(n, false)
+ )
+}
+
+/**
+ * Holds if the additional step from `node1` to `node2` does not jump between callables.
+ */
+private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configuration config) {
+ exists(Node n1, Node n2 |
+ node1.asNode() = n1 and
+ node2.asNode() = n2 and
+ config.isAdditionalFlowStep(n1, n2) and
+ getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
+ not outBarrier(node1, config) and
+ not inBarrier(node2, config) and
+ not fullBarrier(node1, config) and
+ not fullBarrier(node2, config)
+ )
+ or
+ exists(Node n |
+ config.allowImplicitRead(n, _) and
+ node1.isImplicitReadNode(n, true) and
+ node2.asNode() = n
+ )
+}
+
+/**
+ * Holds if data can flow from `node1` to `node2` in a way that discards call contexts.
+ */
+private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
+ exists(Node n1, Node n2 |
+ node1.asNode() = n1 and
+ node2.asNode() = n2 and
+ jumpStepCached(n1, n2) and
+ not outBarrier(node1, config) and
+ not inBarrier(node2, config) and
+ not fullBarrier(node1, config) and
+ not fullBarrier(node2, config) and
+ not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
+ )
+}
+
+/**
+ * Holds if the additional step from `node1` to `node2` jumps between callables.
+ */
+private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration config) {
+ exists(Node n1, Node n2 |
+ node1.asNode() = n1 and
+ node2.asNode() = n2 and
+ config.isAdditionalFlowStep(n1, n2) and
+ getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
+ not outBarrier(node1, config) and
+ not inBarrier(node2, config) and
+ not fullBarrier(node1, config) and
+ not fullBarrier(node2, config) and
+ not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
+ )
+}
+
+private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
+ read(node1.asNode(), c, node2.asNode())
+ or
+ exists(Node n |
+ node2.isImplicitReadNode(n, true) and
+ node1.isImplicitReadNode(n, _) and
+ config.allowImplicitRead(n, c)
+ )
+}
+
+private predicate store(
+ NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
+) {
+ store(node1.asNode(), tc, node2.asNode(), contentType) and
+ read(_, tc.getContent(), _, config)
+}
+
+pragma[nomagic]
+private predicate viableReturnPosOutEx(DataFlowCall call, ReturnPosition pos, NodeEx out) {
+ viableReturnPosOut(call, pos, out.asNode())
+}
+
+pragma[nomagic]
+private predicate viableParamArgEx(DataFlowCall call, ParamNodeEx p, ArgNodeEx arg) {
+ viableParamArg(call, p.asNode(), arg.asNode())
+}
+
+/**
+ * Holds if field flow should be used for the given configuration.
+ */
+private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 }
+
+private predicate hasSourceCallCtx(Configuration config) {
+ exists(FlowFeature feature | feature = config.getAFeature() |
+ feature instanceof FeatureHasSourceCallContext or
+ feature instanceof FeatureEqualSourceSinkCallContext
+ )
+}
+
+private predicate hasSinkCallCtx(Configuration config) {
+ exists(FlowFeature feature | feature = config.getAFeature() |
+ feature instanceof FeatureHasSinkCallContext or
+ feature instanceof FeatureEqualSourceSinkCallContext
+ )
+}
+
+private module Stage1 {
+ class ApApprox = Unit;
+
+ class Ap = Unit;
+
+ class ApOption = Unit;
+
+ class Cc = boolean;
+
+ /* Begin: Stage 1 logic. */
+ /**
+ * Holds if `node` is reachable from a source in the configuration `config`.
+ *
+ * The Boolean `cc` records whether the node is reached through an
+ * argument in a call.
+ */
+ predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
+ not fullBarrier(node, config) and
+ (
+ sourceNode(node, config) and
+ if hasSourceCallCtx(config) then cc = true else cc = false
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, cc, config) and
+ localFlowStep(mid, node, config)
+ )
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, cc, config) and
+ additionalLocalFlowStep(mid, node, config)
+ )
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, _, config) and
+ jumpStep(mid, node, config) and
+ cc = false
+ )
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, _, config) and
+ additionalJumpStep(mid, node, config) and
+ cc = false
+ )
+ or
+ // store
+ exists(NodeEx mid |
+ useFieldFlow(config) and
+ fwdFlow(mid, cc, config) and
+ store(mid, _, node, _, config) and
+ not outBarrier(mid, config)
+ )
+ or
+ // read
+ exists(Content c |
+ fwdFlowRead(c, node, cc, config) and
+ fwdFlowConsCand(c, config) and
+ not inBarrier(node, config)
+ )
+ or
+ // flow into a callable
+ exists(NodeEx arg |
+ fwdFlow(arg, _, config) and
+ viableParamArgEx(_, node, arg) and
+ cc = true
+ )
+ or
+ // flow out of a callable
+ exists(DataFlowCall call |
+ fwdFlowOut(call, node, false, config) and
+ cc = false
+ or
+ fwdFlowOutFromArg(call, node, config) and
+ fwdFlowIsEntered(call, cc, config)
+ )
+ )
+ }
+
+ private predicate fwdFlow(NodeEx node, Configuration config) { fwdFlow(node, _, config) }
+
+ pragma[nomagic]
+ private predicate fwdFlowRead(Content c, NodeEx node, Cc cc, Configuration config) {
+ exists(NodeEx mid |
+ fwdFlow(mid, cc, config) and
+ read(mid, c, node, config)
+ )
+ }
+
+ /**
+ * Holds if `c` is the target of a store in the flow covered by `fwdFlow`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowConsCand(Content c, Configuration config) {
+ exists(NodeEx mid, NodeEx node, TypedContent tc |
+ not fullBarrier(node, config) and
+ useFieldFlow(config) and
+ fwdFlow(mid, _, config) and
+ store(mid, tc, node, _, config) and
+ c = tc.getContent()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowReturnPosition(ReturnPosition pos, Cc cc, Configuration config) {
+ exists(RetNodeEx ret |
+ fwdFlow(ret, cc, config) and
+ ret.getReturnPosition() = pos
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
+ exists(ReturnPosition pos |
+ fwdFlowReturnPosition(pos, cc, config) and
+ viableReturnPosOutEx(call, pos, out)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutFromArg(DataFlowCall call, NodeEx out, Configuration config) {
+ fwdFlowOut(call, out, true, config)
+ }
+
+ /**
+ * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowIsEntered(DataFlowCall call, Cc cc, Configuration config) {
+ exists(ArgNodeEx arg |
+ fwdFlow(arg, cc, config) and
+ viableParamArgEx(call, _, arg)
+ )
+ }
+
+ /**
+ * Holds if `node` is part of a path from a source to a sink in the
+ * configuration `config`.
+ *
+ * The Boolean `toReturn` records whether the node must be returned from
+ * the enclosing callable in order to reach a sink.
+ */
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, boolean toReturn, Configuration config) {
+ revFlow0(node, toReturn, config) and
+ fwdFlow(node, config)
+ }
+
+ pragma[nomagic]
+ private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) {
+ fwdFlow(node, config) and
+ sinkNode(node, config) and
+ if hasSinkCallCtx(config) then toReturn = true else toReturn = false
+ or
+ exists(NodeEx mid |
+ localFlowStep(node, mid, config) and
+ revFlow(mid, toReturn, config)
+ )
+ or
+ exists(NodeEx mid |
+ additionalLocalFlowStep(node, mid, config) and
+ revFlow(mid, toReturn, config)
+ )
+ or
+ exists(NodeEx mid |
+ jumpStep(node, mid, config) and
+ revFlow(mid, _, config) and
+ toReturn = false
+ )
+ or
+ exists(NodeEx mid |
+ additionalJumpStep(node, mid, config) and
+ revFlow(mid, _, config) and
+ toReturn = false
+ )
+ or
+ // store
+ exists(Content c |
+ revFlowStore(c, node, toReturn, config) and
+ revFlowConsCand(c, config)
+ )
+ or
+ // read
+ exists(NodeEx mid, Content c |
+ read(node, c, mid, config) and
+ fwdFlowConsCand(c, pragma[only_bind_into](config)) and
+ revFlow(mid, toReturn, pragma[only_bind_into](config))
+ )
+ or
+ // flow into a callable
+ exists(DataFlowCall call |
+ revFlowIn(call, node, false, config) and
+ toReturn = false
+ or
+ revFlowInToReturn(call, node, config) and
+ revFlowIsReturned(call, toReturn, config)
+ )
+ or
+ // flow out of a callable
+ exists(ReturnPosition pos |
+ revFlowOut(pos, config) and
+ node.(RetNodeEx).getReturnPosition() = pos and
+ toReturn = true
+ )
+ }
+
+ /**
+ * Holds if `c` is the target of a read in the flow covered by `revFlow`.
+ */
+ pragma[nomagic]
+ private predicate revFlowConsCand(Content c, Configuration config) {
+ exists(NodeEx mid, NodeEx node |
+ fwdFlow(node, pragma[only_bind_into](config)) and
+ read(node, c, mid, config) and
+ fwdFlowConsCand(c, pragma[only_bind_into](config)) and
+ revFlow(pragma[only_bind_into](mid), _, pragma[only_bind_into](config))
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowStore(Content c, NodeEx node, boolean toReturn, Configuration config) {
+ exists(NodeEx mid, TypedContent tc |
+ revFlow(mid, toReturn, pragma[only_bind_into](config)) and
+ fwdFlowConsCand(c, pragma[only_bind_into](config)) and
+ store(node, tc, mid, _, config) and
+ c = tc.getContent()
+ )
+ }
+
+ /**
+ * Holds if `c` is the target of both a read and a store in the flow covered
+ * by `revFlow`.
+ */
+ private predicate revFlowIsReadAndStored(Content c, Configuration conf) {
+ revFlowConsCand(c, conf) and
+ revFlowStore(c, _, _, conf)
+ }
+
+ pragma[nomagic]
+ predicate viableReturnPosOutNodeCandFwd1(
+ DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
+ ) {
+ fwdFlowReturnPosition(pos, _, config) and
+ viableReturnPosOutEx(call, pos, out)
+ }
+
+ pragma[nomagic]
+ private predicate revFlowOut(ReturnPosition pos, Configuration config) {
+ exists(DataFlowCall call, NodeEx out |
+ revFlow(out, _, config) and
+ viableReturnPosOutNodeCandFwd1(call, pos, out, config)
+ )
+ }
+
+ pragma[nomagic]
+ predicate viableParamArgNodeCandFwd1(
+ DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
+ ) {
+ viableParamArgEx(call, p, arg) and
+ fwdFlow(arg, config)
+ }
+
+ pragma[nomagic]
+ private predicate revFlowIn(
+ DataFlowCall call, ArgNodeEx arg, boolean toReturn, Configuration config
+ ) {
+ exists(ParamNodeEx p |
+ revFlow(p, toReturn, config) and
+ viableParamArgNodeCandFwd1(call, p, arg, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInToReturn(DataFlowCall call, ArgNodeEx arg, Configuration config) {
+ revFlowIn(call, arg, true, config)
+ }
+
+ /**
+ * Holds if an output from `call` is reached in the flow covered by `revFlow`
+ * and data might flow through the target callable resulting in reverse flow
+ * reaching an argument of `call`.
+ */
+ pragma[nomagic]
+ private predicate revFlowIsReturned(DataFlowCall call, boolean toReturn, Configuration config) {
+ exists(NodeEx out |
+ revFlow(out, toReturn, config) and
+ fwdFlowOutFromArg(call, out, config)
+ )
+ }
+
+ pragma[nomagic]
+ predicate storeStepCand(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
+ Configuration config
+ ) {
+ exists(Content c |
+ revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
+ revFlow(node2, pragma[only_bind_into](config)) and
+ store(node1, tc, node2, contentType, config) and
+ c = tc.getContent() and
+ exists(ap1)
+ )
+ }
+
+ pragma[nomagic]
+ predicate readStepCand(NodeEx n1, Content c, NodeEx n2, Configuration config) {
+ revFlowIsReadAndStored(c, pragma[only_bind_into](config)) and
+ revFlow(n2, pragma[only_bind_into](config)) and
+ read(n1, c, n2, pragma[only_bind_into](config))
+ }
+
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) }
+
+ predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
+ revFlow(node, toReturn, config) and exists(returnAp) and exists(ap)
+ }
+
+ private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
+ revFlow(node, true, config) and
+ fwdFlow(node, true, config) and
+ not inBarrier(node, config) and
+ not outBarrier(node, config)
+ }
+
+ /** Holds if flow may return from `callable`. */
+ pragma[nomagic]
+ private predicate returnFlowCallableNodeCand(
+ DataFlowCallable callable, ReturnKindExt kind, Configuration config
+ ) {
+ exists(RetNodeEx ret |
+ throughFlowNodeCand(ret, config) and
+ callable = ret.getEnclosingCallable() and
+ kind = ret.getKind()
+ )
+ }
+
+ /**
+ * Holds if flow may enter through `p` and reach a return node making `p` a
+ * candidate for the origin of a summary.
+ */
+ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
+ exists(ReturnKindExt kind |
+ throughFlowNodeCand(p, config) and
+ returnFlowCallableNodeCand(c, kind, config) and
+ p.getEnclosingCallable() = c and
+ exists(ap) and
+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
+ (
+ not kind.(ParamUpdateReturnKind).getPosition() = p.getPosition()
+ or
+ p.allowParameterReturnInSelf()
+ )
+ )
+ }
+
+ pragma[nomagic]
+ predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
+ exists(ArgNodeEx arg, boolean toReturn |
+ revFlow(arg, toReturn, config) and
+ revFlowInToReturn(call, arg, config) and
+ revFlowIsReturned(call, toReturn, config)
+ )
+ }
+
+ predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ fwd = true and
+ nodes = count(NodeEx node | fwdFlow(node, config)) and
+ fields = count(Content f0 | fwdFlowConsCand(f0, config)) and
+ conscand = -1 and
+ tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config))
+ or
+ fwd = false and
+ nodes = count(NodeEx node | revFlow(node, _, config)) and
+ fields = count(Content f0 | revFlowConsCand(f0, config)) and
+ conscand = -1 and
+ tuples = count(NodeEx n, boolean b | revFlow(n, b, config))
+ }
+ /* End: Stage 1 logic. */
+}
+
+pragma[noinline]
+private predicate localFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) {
+ Stage1::revFlow(node2, config) and
+ localFlowStep(node1, node2, config)
+}
+
+pragma[noinline]
+private predicate additionalLocalFlowStepNodeCand1(NodeEx node1, NodeEx node2, Configuration config) {
+ Stage1::revFlow(node2, config) and
+ additionalLocalFlowStep(node1, node2, config)
+}
+
+pragma[nomagic]
+private predicate viableReturnPosOutNodeCand1(
+ DataFlowCall call, ReturnPosition pos, NodeEx out, Configuration config
+) {
+ Stage1::revFlow(out, config) and
+ Stage1::viableReturnPosOutNodeCandFwd1(call, pos, out, config)
+}
+
+/**
+ * Holds if data can flow out of `call` from `ret` to `out`, either
+ * through a `ReturnNode` or through an argument that has been mutated, and
+ * that this step is part of a path from a source to a sink.
+ */
+pragma[nomagic]
+private predicate flowOutOfCallNodeCand1(
+ DataFlowCall call, RetNodeEx ret, NodeEx out, Configuration config
+) {
+ viableReturnPosOutNodeCand1(call, ret.getReturnPosition(), out, config) and
+ Stage1::revFlow(ret, config) and
+ not outBarrier(ret, config) and
+ not inBarrier(out, config)
+}
+
+pragma[nomagic]
+private predicate viableParamArgNodeCand1(
+ DataFlowCall call, ParamNodeEx p, ArgNodeEx arg, Configuration config
+) {
+ Stage1::viableParamArgNodeCandFwd1(call, p, arg, config) and
+ Stage1::revFlow(arg, config)
+}
+
+/**
+ * Holds if data can flow into `call` and that this step is part of a
+ * path from a source to a sink.
+ */
+pragma[nomagic]
+private predicate flowIntoCallNodeCand1(
+ DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, Configuration config
+) {
+ viableParamArgNodeCand1(call, p, arg, config) and
+ Stage1::revFlow(p, config) and
+ not outBarrier(arg, config) and
+ not inBarrier(p, config)
+}
+
+/**
+ * Gets the amount of forward branching on the origin of a cross-call path
+ * edge in the graph of paths between sources and sinks that ignores call
+ * contexts.
+ */
+private int branch(NodeEx n1, Configuration conf) {
+ result =
+ strictcount(NodeEx n |
+ flowOutOfCallNodeCand1(_, n1, n, conf) or flowIntoCallNodeCand1(_, n1, n, conf)
+ )
+}
+
+/**
+ * Gets the amount of backward branching on the target of a cross-call path
+ * edge in the graph of paths between sources and sinks that ignores call
+ * contexts.
+ */
+private int join(NodeEx n2, Configuration conf) {
+ result =
+ strictcount(NodeEx n |
+ flowOutOfCallNodeCand1(_, n, n2, conf) or flowIntoCallNodeCand1(_, n, n2, conf)
+ )
+}
+
+/**
+ * Holds if data can flow out of `call` from `ret` to `out`, either
+ * through a `ReturnNode` or through an argument that has been mutated, and
+ * that this step is part of a path from a source to a sink. The
+ * `allowsFieldFlow` flag indicates whether the branching is within the limit
+ * specified by the configuration.
+ */
+pragma[nomagic]
+private predicate flowOutOfCallNodeCand1(
+ DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+) {
+ flowOutOfCallNodeCand1(call, ret, out, config) and
+ exists(int b, int j |
+ b = branch(ret, config) and
+ j = join(out, config) and
+ if b.minimum(j) <= config.fieldFlowBranchLimit()
+ then allowsFieldFlow = true
+ else allowsFieldFlow = false
+ )
+}
+
+/**
+ * Holds if data can flow into `call` and that this step is part of a
+ * path from a source to a sink. The `allowsFieldFlow` flag indicates whether
+ * the branching is within the limit specified by the configuration.
+ */
+pragma[nomagic]
+private predicate flowIntoCallNodeCand1(
+ DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
+) {
+ flowIntoCallNodeCand1(call, arg, p, config) and
+ exists(int b, int j |
+ b = branch(arg, config) and
+ j = join(p, config) and
+ if b.minimum(j) <= config.fieldFlowBranchLimit()
+ then allowsFieldFlow = true
+ else allowsFieldFlow = false
+ )
+}
+
+private module Stage2 {
+ module PrevStage = Stage1;
+
+ class ApApprox = PrevStage::Ap;
+
+ class Ap = boolean;
+
+ class ApNil extends Ap {
+ ApNil() { this = false }
+ }
+
+ bindingset[result, ap]
+ private ApApprox getApprox(Ap ap) { any() }
+
+ private ApNil getApNil(NodeEx node) { PrevStage::revFlow(node, _) and exists(result) }
+
+ bindingset[tc, tail]
+ private Ap apCons(TypedContent tc, Ap tail) { result = true and exists(tc) and exists(tail) }
+
+ pragma[inline]
+ private Content getHeadContent(Ap ap) { exists(result) and ap = true }
+
+ class ApOption = BooleanOption;
+
+ ApOption apNone() { result = TBooleanNone() }
+
+ ApOption apSome(Ap ap) { result = TBooleanSome(ap) }
+
+ class Cc = CallContext;
+
+ class CcCall = CallContextCall;
+
+ class CcNoCall = CallContextNoCall;
+
+ Cc ccNone() { result instanceof CallContextAny }
+
+ CcCall ccSomeCall() { result instanceof CallContextSomeCall }
+
+ private class LocalCc = Unit;
+
+ bindingset[call, c, outercc]
+ private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
+ checkCallContextCall(outercc, call, c) and
+ if recordDataFlowCallSiteDispatch(call, c)
+ then result = TSpecificCall(call)
+ else result = TSomeCall()
+ }
+
+ bindingset[call, c, innercc]
+ private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
+ checkCallContextReturn(innercc, c, call) and
+ if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
+ }
+
+ bindingset[node, cc, config]
+ private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
+
+ private predicate localStep(
+ NodeEx node1, NodeEx node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc
+ ) {
+ (
+ preservesValue = true and
+ localFlowStepNodeCand1(node1, node2, config)
+ or
+ preservesValue = false and
+ additionalLocalFlowStepNodeCand1(node1, node2, config)
+ ) and
+ exists(ap) and
+ exists(lcc)
+ }
+
+ private predicate flowOutOfCall = flowOutOfCallNodeCand1/5;
+
+ private predicate flowIntoCall = flowIntoCallNodeCand1/5;
+
+ bindingset[ap, contentType]
+ private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
+
+ /* Begin: Stage 2 logic. */
+ private predicate flowCand(NodeEx node, ApApprox apa, Configuration config) {
+ PrevStage::revFlow(node, _, _, apa, config)
+ }
+
+ pragma[nomagic]
+ private predicate flowThroughOutOfCall(
+ DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
+ PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
+ PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
+ pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if `node` is reachable with access path `ap` from a source in the
+ * configuration `config`.
+ *
+ * The call context `cc` records whether the node is reached through an
+ * argument in a call, and if so, `argAp` records the access path of that
+ * argument.
+ */
+ pragma[nomagic]
+ predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ flowCand(node, _, config) and
+ sourceNode(node, config) and
+ (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
+ argAp = apNone() and
+ ap = getApNil(node)
+ or
+ exists(NodeEx mid, Ap ap0, LocalCc localCc |
+ fwdFlow(mid, cc, argAp, ap0, config) and
+ localCc = getLocalCc(mid, cc, config)
+ |
+ localStep(mid, node, true, _, config, localCc) and
+ ap = ap0
+ or
+ localStep(mid, node, false, ap, config, localCc) and
+ ap0 instanceof ApNil
+ )
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, _, _, ap, pragma[only_bind_into](config)) and
+ flowCand(node, _, pragma[only_bind_into](config)) and
+ jumpStep(mid, node, config) and
+ cc = ccNone() and
+ argAp = apNone()
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(mid, _, _, nil, pragma[only_bind_into](config)) and
+ flowCand(node, _, pragma[only_bind_into](config)) and
+ additionalJumpStep(mid, node, config) and
+ cc = ccNone() and
+ argAp = apNone() and
+ ap = getApNil(node)
+ )
+ or
+ // store
+ exists(TypedContent tc, Ap ap0 |
+ fwdFlowStore(_, ap0, tc, node, cc, argAp, config) and
+ ap = apCons(tc, ap0)
+ )
+ or
+ // read
+ exists(Ap ap0, Content c |
+ fwdFlowRead(ap0, c, _, node, cc, argAp, config) and
+ fwdFlowConsCand(ap0, c, ap, config)
+ )
+ or
+ // flow into a callable
+ exists(ApApprox apa |
+ fwdFlowIn(_, node, _, cc, _, ap, config) and
+ apa = getApprox(ap) and
+ if PrevStage::parameterMayFlowThrough(node, _, apa, config)
+ then argAp = apSome(ap)
+ else argAp = apNone()
+ )
+ or
+ // flow out of a callable
+ fwdFlowOutNotFromArg(node, cc, argAp, ap, config)
+ or
+ exists(DataFlowCall call, Ap argAp0 |
+ fwdFlowOutFromArg(call, node, argAp0, ap, config) and
+ fwdFlowIsEntered(call, cc, argAp, argAp0, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowStore(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ ) {
+ exists(DataFlowType contentType |
+ fwdFlow(node1, cc, argAp, ap1, config) and
+ PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
+ typecheckStore(ap1, contentType)
+ )
+ }
+
+ /**
+ * Holds if forward flow with access path `tail` reaches a store of `c`
+ * resulting in access path `cons`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
+ exists(TypedContent tc |
+ fwdFlowStore(_, tail, tc, _, _, _, config) and
+ tc.getContent() = c and
+ cons = apCons(tc, tail)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowRead(
+ Ap ap, Content c, NodeEx node1, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ ) {
+ fwdFlow(node1, cc, argAp, ap, config) and
+ PrevStage::readStepCand(node1, c, node2, config) and
+ getHeadContent(ap) = c
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowIn(
+ DataFlowCall call, ParamNodeEx p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ Configuration config
+ ) {
+ exists(ArgNodeEx arg, boolean allowsFieldFlow |
+ fwdFlow(arg, outercc, argAp, ap, config) and
+ flowIntoCall(call, arg, p, allowsFieldFlow, config) and
+ innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutNotFromArg(
+ NodeEx out, Cc ccOut, ApOption argAp, Ap ap, Configuration config
+ ) {
+ exists(
+ DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
+ DataFlowCallable inner
+ |
+ fwdFlow(ret, innercc, argAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ inner = ret.getEnclosingCallable() and
+ ccOut = getCallContextReturn(inner, call, innercc)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutFromArg(
+ DataFlowCall call, NodeEx out, Ap argAp, Ap ap, Configuration config
+ ) {
+ exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
+ fwdFlow(ret, ccc, apSome(argAp), ap, config) and
+ flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ ccc.matchesCall(call)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ /**
+ * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`
+ * and data might flow through the target callable and back out at `call`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowIsEntered(
+ DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p |
+ fwdFlowIn(call, p, cc, _, argAp, ap, config) and
+ PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate storeStepFwd(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config
+ ) {
+ fwdFlowStore(node1, ap1, tc, node2, _, _, config) and
+ ap2 = apCons(tc, ap1) and
+ fwdFlowRead(ap2, tc.getContent(), _, _, _, _, config)
+ }
+
+ private predicate readStepFwd(
+ NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config
+ ) {
+ fwdFlowRead(ap1, c, n1, n2, _, _, config) and
+ fwdFlowConsCand(ap1, c, ap2, config)
+ }
+
+ pragma[nomagic]
+ private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) {
+ exists(Ap argAp0, NodeEx out, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
+ pragma[only_bind_into](config)) and
+ fwdFlowOutFromArg(call, out, argAp0, ap, config) and
+ fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
+ pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
+ pragma[only_bind_into](config))
+ )
+ }
+
+ pragma[nomagic]
+ private predicate flowThroughIntoCall(
+ DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowIntoCall(call, arg, p, allowsFieldFlow, config) and
+ fwdFlow(arg, _, _, _, pragma[only_bind_into](config)) and
+ PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and
+ callMayFlowThroughFwd(call, pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if `node` with access path `ap` is part of a path from a source to a
+ * sink in the configuration `config`.
+ *
+ * The Boolean `toReturn` records whether the node must be returned from the
+ * enclosing callable in order to reach a sink, and if so, `returnAp` records
+ * the access path of the returned value.
+ */
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
+ revFlow0(node, toReturn, returnAp, ap, config) and
+ fwdFlow(node, _, _, ap, config)
+ }
+
+ pragma[nomagic]
+ private predicate revFlow0(
+ NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ fwdFlow(node, _, _, ap, config) and
+ sinkNode(node, config) and
+ (if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ or
+ exists(NodeEx mid |
+ localStep(node, mid, true, _, config, _) and
+ revFlow(mid, toReturn, returnAp, ap, config)
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ localStep(node, mid, false, _, config, _) and
+ revFlow(mid, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
+ ap instanceof ApNil
+ )
+ or
+ exists(NodeEx mid |
+ jumpStep(node, mid, config) and
+ revFlow(mid, _, _, ap, config) and
+ toReturn = false and
+ returnAp = apNone()
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ additionalJumpStep(node, mid, config) and
+ revFlow(pragma[only_bind_into](mid), _, _, nil, pragma[only_bind_into](config)) and
+ toReturn = false and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ )
+ or
+ // store
+ exists(Ap ap0, Content c |
+ revFlowStore(ap0, c, ap, node, _, _, toReturn, returnAp, config) and
+ revFlowConsCand(ap0, c, ap, config)
+ )
+ or
+ // read
+ exists(NodeEx mid, Ap ap0 |
+ revFlow(mid, toReturn, returnAp, ap0, config) and
+ readStepFwd(node, ap, _, mid, ap0, config)
+ )
+ or
+ // flow into a callable
+ revFlowInNotToReturn(node, returnAp, ap, config) and
+ toReturn = false
+ or
+ exists(DataFlowCall call, Ap returnAp0 |
+ revFlowInToReturn(call, node, returnAp0, ap, config) and
+ revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
+ )
+ or
+ // flow out of a callable
+ revFlowOut(_, node, _, _, ap, config) and
+ toReturn = true and
+ if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
+ then returnAp = apSome(ap)
+ else returnAp = apNone()
+ }
+
+ pragma[nomagic]
+ private predicate revFlowStore(
+ Ap ap0, Content c, Ap ap, NodeEx node, TypedContent tc, NodeEx mid, boolean toReturn,
+ ApOption returnAp, Configuration config
+ ) {
+ revFlow(mid, toReturn, returnAp, ap0, config) and
+ storeStepFwd(node, ap, tc, mid, ap0, config) and
+ tc.getContent() = c
+ }
+
+ /**
+ * Holds if reverse flow with access path `tail` reaches a read of `c`
+ * resulting in access path `cons`.
+ */
+ pragma[nomagic]
+ private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
+ exists(NodeEx mid, Ap tail0 |
+ revFlow(mid, _, _, tail, config) and
+ tail = pragma[only_bind_into](tail0) and
+ readStepFwd(_, cons, c, mid, tail0, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowOut(
+ DataFlowCall call, RetNodeEx ret, boolean toReturn, ApOption returnAp, Ap ap,
+ Configuration config
+ ) {
+ exists(NodeEx out, boolean allowsFieldFlow |
+ revFlow(out, toReturn, returnAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInNotToReturn(
+ ArgNodeEx arg, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p, boolean allowsFieldFlow |
+ revFlow(p, false, returnAp, ap, config) and
+ flowIntoCall(_, arg, p, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInToReturn(
+ DataFlowCall call, ArgNodeEx arg, Ap returnAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p, boolean allowsFieldFlow |
+ revFlow(p, true, apSome(returnAp), ap, config) and
+ flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ /**
+ * Holds if an output from `call` is reached in the flow covered by `revFlow`
+ * and data might flow through the target callable resulting in reverse flow
+ * reaching an argument of `call`.
+ */
+ pragma[nomagic]
+ private predicate revFlowIsReturned(
+ DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ exists(RetNodeEx ret, CcCall ccc |
+ revFlowOut(call, ret, toReturn, returnAp, ap, config) and
+ fwdFlow(ret, ccc, apSome(_), ap, config) and
+ ccc.matchesCall(call)
+ )
+ }
+
+ pragma[nomagic]
+ predicate storeStepCand(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
+ Configuration config
+ ) {
+ exists(Ap ap2, Content c |
+ store(node1, tc, node2, contentType, config) and
+ revFlowStore(ap2, c, ap1, node1, tc, node2, _, _, config) and
+ revFlowConsCand(ap2, c, ap1, config)
+ )
+ }
+
+ predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) {
+ exists(Ap ap1, Ap ap2 |
+ revFlow(node2, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
+ readStepFwd(node1, ap1, c, node2, ap2, config) and
+ revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _,
+ pragma[only_bind_into](config))
+ )
+ }
+
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, config) }
+
+ private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) {
+ storeStepFwd(_, ap, tc, _, _, config)
+ }
+
+ predicate consCand(TypedContent tc, Ap ap, Configuration config) {
+ storeStepCand(_, ap, tc, _, _, config)
+ }
+
+ pragma[noinline]
+ private predicate parameterFlow(
+ ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ) {
+ revFlow(p, true, apSome(ap0), ap, config) and
+ c = p.getEnclosingCallable()
+ }
+
+ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
+ exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
+ parameterFlow(p, ap, ap0, c, config) and
+ c = ret.getEnclosingCallable() and
+ revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
+ pragma[only_bind_into](config)) and
+ fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
+ kind = ret.getKind() and
+ p.getPosition() = pos and
+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
+ (
+ not kind.(ParamUpdateReturnKind).getPosition() = pos
+ or
+ p.allowParameterReturnInSelf()
+ )
+ )
+ }
+
+ pragma[nomagic]
+ predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
+ exists(Ap returnAp0, ArgNodeEx arg, boolean toReturn, ApOption returnAp, Ap ap |
+ revFlow(arg, toReturn, returnAp, ap, config) and
+ revFlowInToReturn(call, arg, returnAp0, ap, config) and
+ revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
+ )
+ }
+
+ predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ fwd = true and
+ nodes = count(NodeEx node | fwdFlow(node, _, _, _, config)) and
+ fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and
+ conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
+ tuples = count(NodeEx n, Cc cc, ApOption argAp, Ap ap | fwdFlow(n, cc, argAp, ap, config))
+ or
+ fwd = false and
+ nodes = count(NodeEx node | revFlow(node, _, _, _, config)) and
+ fields = count(TypedContent f0 | consCand(f0, _, config)) and
+ conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and
+ tuples = count(NodeEx n, boolean b, ApOption retAp, Ap ap | revFlow(n, b, retAp, ap, config))
+ }
+ /* End: Stage 2 logic. */
+}
+
+pragma[nomagic]
+private predicate flowOutOfCallNodeCand2(
+ DataFlowCall call, RetNodeEx node1, NodeEx node2, boolean allowsFieldFlow, Configuration config
+) {
+ flowOutOfCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
+ Stage2::revFlow(node2, pragma[only_bind_into](config)) and
+ Stage2::revFlow(node1, pragma[only_bind_into](config))
+}
+
+pragma[nomagic]
+private predicate flowIntoCallNodeCand2(
+ DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow,
+ Configuration config
+) {
+ flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
+ Stage2::revFlow(node2, pragma[only_bind_into](config)) and
+ Stage2::revFlow(node1, pragma[only_bind_into](config))
+}
+
+private module LocalFlowBigStep {
+ /**
+ * A node where some checking is required, and hence the big-step relation
+ * is not allowed to step over.
+ */
+ private class FlowCheckNode extends NodeEx {
+ FlowCheckNode() {
+ castNode(this.asNode()) or
+ clearsContentCached(this.asNode(), _)
+ }
+ }
+
+ /**
+ * Holds if `node` can be the first node in a maximal subsequence of local
+ * flow steps in a dataflow path.
+ */
+ predicate localFlowEntry(NodeEx node, Configuration config) {
+ Stage2::revFlow(node, config) and
+ (
+ sourceNode(node, config) or
+ jumpStep(_, node, config) or
+ additionalJumpStep(_, node, config) or
+ node instanceof ParamNodeEx or
+ node.asNode() instanceof OutNodeExt or
+ store(_, _, node, _, config) or
+ read(_, _, node, config) or
+ node instanceof FlowCheckNode
+ )
+ }
+
+ /**
+ * Holds if `node` can be the last node in a maximal subsequence of local
+ * flow steps in a dataflow path.
+ */
+ private predicate localFlowExit(NodeEx node, Configuration config) {
+ exists(NodeEx next | Stage2::revFlow(next, config) |
+ jumpStep(node, next, config) or
+ additionalJumpStep(node, next, config) or
+ flowIntoCallNodeCand1(_, node, next, config) or
+ flowOutOfCallNodeCand1(_, node, next, config) or
+ store(node, _, next, _, config) or
+ read(node, _, next, config)
+ )
+ or
+ node instanceof FlowCheckNode
+ or
+ sinkNode(node, config)
+ }
+
+ pragma[noinline]
+ private predicate additionalLocalFlowStepNodeCand2(
+ NodeEx node1, NodeEx node2, Configuration config
+ ) {
+ additionalLocalFlowStepNodeCand1(node1, node2, config) and
+ Stage2::revFlow(node1, _, _, false, pragma[only_bind_into](config)) and
+ Stage2::revFlow(node2, _, _, false, pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if the local path from `node1` to `node2` is a prefix of a maximal
+ * subsequence of local flow steps in a dataflow path.
+ *
+ * This is the transitive closure of `[additional]localFlowStep` beginning
+ * at `localFlowEntry`.
+ */
+ pragma[nomagic]
+ private predicate localFlowStepPlus(
+ NodeEx node1, NodeEx node2, boolean preservesValue, DataFlowType t, Configuration config,
+ LocalCallContext cc
+ ) {
+ not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
+ (
+ localFlowEntry(node1, pragma[only_bind_into](config)) and
+ (
+ localFlowStepNodeCand1(node1, node2, config) and
+ preservesValue = true and
+ t = node1.getDataFlowType() // irrelevant dummy value
+ or
+ additionalLocalFlowStepNodeCand2(node1, node2, config) and
+ preservesValue = false and
+ t = node2.getDataFlowType()
+ ) and
+ node1 != node2 and
+ cc.relevantFor(node1.getEnclosingCallable()) and
+ not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
+ Stage2::revFlow(node2, pragma[only_bind_into](config))
+ or
+ exists(NodeEx mid |
+ localFlowStepPlus(node1, mid, preservesValue, t, pragma[only_bind_into](config), cc) and
+ localFlowStepNodeCand1(mid, node2, config) and
+ not mid instanceof FlowCheckNode and
+ Stage2::revFlow(node2, pragma[only_bind_into](config))
+ )
+ or
+ exists(NodeEx mid |
+ localFlowStepPlus(node1, mid, _, _, pragma[only_bind_into](config), cc) and
+ additionalLocalFlowStepNodeCand2(mid, node2, config) and
+ not mid instanceof FlowCheckNode and
+ preservesValue = false and
+ t = node2.getDataFlowType() and
+ Stage2::revFlow(node2, pragma[only_bind_into](config))
+ )
+ )
+ }
+
+ /**
+ * Holds if `node1` can step to `node2` in one or more local steps and this
+ * path can occur as a maximal subsequence of local steps in a dataflow path.
+ */
+ pragma[nomagic]
+ predicate localFlowBigStep(
+ NodeEx node1, NodeEx node2, boolean preservesValue, AccessPathFrontNil apf,
+ Configuration config, LocalCallContext callContext
+ ) {
+ localFlowStepPlus(node1, node2, preservesValue, apf.getType(), config, callContext) and
+ localFlowExit(node2, config)
+ }
+}
+
+private import LocalFlowBigStep
+
+private module Stage3 {
+ module PrevStage = Stage2;
+
+ class ApApprox = PrevStage::Ap;
+
+ class Ap = AccessPathFront;
+
+ class ApNil = AccessPathFrontNil;
+
+ private ApApprox getApprox(Ap ap) { result = ap.toBoolNonEmpty() }
+
+ private ApNil getApNil(NodeEx node) {
+ PrevStage::revFlow(node, _) and result = TFrontNil(node.getDataFlowType())
+ }
+
+ bindingset[tc, tail]
+ private Ap apCons(TypedContent tc, Ap tail) { result.getHead() = tc and exists(tail) }
+
+ pragma[noinline]
+ private Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
+
+ class ApOption = AccessPathFrontOption;
+
+ ApOption apNone() { result = TAccessPathFrontNone() }
+
+ ApOption apSome(Ap ap) { result = TAccessPathFrontSome(ap) }
+
+ class Cc = boolean;
+
+ class CcCall extends Cc {
+ CcCall() { this = true }
+
+ /** Holds if this call context may be `call`. */
+ predicate matchesCall(DataFlowCall call) { any() }
+ }
+
+ class CcNoCall extends Cc {
+ CcNoCall() { this = false }
+ }
+
+ Cc ccNone() { result = false }
+
+ CcCall ccSomeCall() { result = true }
+
+ private class LocalCc = Unit;
+
+ bindingset[call, c, outercc]
+ private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) { any() }
+
+ bindingset[call, c, innercc]
+ private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) { any() }
+
+ bindingset[node, cc, config]
+ private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
+
+ private predicate localStep(
+ NodeEx node1, NodeEx node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc
+ ) {
+ localFlowBigStep(node1, node2, preservesValue, ap, config, _) and exists(lcc)
+ }
+
+ private predicate flowOutOfCall = flowOutOfCallNodeCand2/5;
+
+ private predicate flowIntoCall = flowIntoCallNodeCand2/5;
+
+ pragma[nomagic]
+ private predicate clear(NodeEx node, Ap ap) { ap.isClearedAt(node.asNode()) }
+
+ pragma[nomagic]
+ private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
+
+ bindingset[node, ap]
+ private predicate filter(NodeEx node, Ap ap) {
+ not clear(node, ap) and
+ if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
+ }
+
+ bindingset[ap, contentType]
+ private predicate typecheckStore(Ap ap, DataFlowType contentType) {
+ // We need to typecheck stores here, since reverse flow through a getter
+ // might have a different type here compared to inside the getter.
+ compatibleTypes(ap.getType(), contentType)
+ }
+
+ /* Begin: Stage 3 logic. */
+ private predicate flowCand(NodeEx node, ApApprox apa, Configuration config) {
+ PrevStage::revFlow(node, _, _, apa, config)
+ }
+
+ bindingset[result, apa]
+ private ApApprox unbindApa(ApApprox apa) {
+ exists(ApApprox apa0 |
+ apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate flowThroughOutOfCall(
+ DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
+ PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
+ PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
+ pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if `node` is reachable with access path `ap` from a source in the
+ * configuration `config`.
+ *
+ * The call context `cc` records whether the node is reached through an
+ * argument in a call, and if so, `argAp` records the access path of that
+ * argument.
+ */
+ pragma[nomagic]
+ predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ fwdFlow0(node, cc, argAp, ap, config) and
+ flowCand(node, unbindApa(getApprox(ap)), config) and
+ filter(node, ap)
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ flowCand(node, _, config) and
+ sourceNode(node, config) and
+ (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
+ argAp = apNone() and
+ ap = getApNil(node)
+ or
+ exists(NodeEx mid, Ap ap0, LocalCc localCc |
+ fwdFlow(mid, cc, argAp, ap0, config) and
+ localCc = getLocalCc(mid, cc, config)
+ |
+ localStep(mid, node, true, _, config, localCc) and
+ ap = ap0
+ or
+ localStep(mid, node, false, ap, config, localCc) and
+ ap0 instanceof ApNil
+ )
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, _, _, ap, pragma[only_bind_into](config)) and
+ flowCand(node, _, pragma[only_bind_into](config)) and
+ jumpStep(mid, node, config) and
+ cc = ccNone() and
+ argAp = apNone()
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(mid, _, _, nil, pragma[only_bind_into](config)) and
+ flowCand(node, _, pragma[only_bind_into](config)) and
+ additionalJumpStep(mid, node, config) and
+ cc = ccNone() and
+ argAp = apNone() and
+ ap = getApNil(node)
+ )
+ or
+ // store
+ exists(TypedContent tc, Ap ap0 |
+ fwdFlowStore(_, ap0, tc, node, cc, argAp, config) and
+ ap = apCons(tc, ap0)
+ )
+ or
+ // read
+ exists(Ap ap0, Content c |
+ fwdFlowRead(ap0, c, _, node, cc, argAp, config) and
+ fwdFlowConsCand(ap0, c, ap, config)
+ )
+ or
+ // flow into a callable
+ exists(ApApprox apa |
+ fwdFlowIn(_, node, _, cc, _, ap, config) and
+ apa = getApprox(ap) and
+ if PrevStage::parameterMayFlowThrough(node, _, apa, config)
+ then argAp = apSome(ap)
+ else argAp = apNone()
+ )
+ or
+ // flow out of a callable
+ fwdFlowOutNotFromArg(node, cc, argAp, ap, config)
+ or
+ exists(DataFlowCall call, Ap argAp0 |
+ fwdFlowOutFromArg(call, node, argAp0, ap, config) and
+ fwdFlowIsEntered(call, cc, argAp, argAp0, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowStore(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ ) {
+ exists(DataFlowType contentType |
+ fwdFlow(node1, cc, argAp, ap1, config) and
+ PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
+ typecheckStore(ap1, contentType)
+ )
+ }
+
+ /**
+ * Holds if forward flow with access path `tail` reaches a store of `c`
+ * resulting in access path `cons`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
+ exists(TypedContent tc |
+ fwdFlowStore(_, tail, tc, _, _, _, config) and
+ tc.getContent() = c and
+ cons = apCons(tc, tail)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowRead(
+ Ap ap, Content c, NodeEx node1, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ ) {
+ fwdFlow(node1, cc, argAp, ap, config) and
+ PrevStage::readStepCand(node1, c, node2, config) and
+ getHeadContent(ap) = c
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowIn(
+ DataFlowCall call, ParamNodeEx p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ Configuration config
+ ) {
+ exists(ArgNodeEx arg, boolean allowsFieldFlow |
+ fwdFlow(arg, outercc, argAp, ap, config) and
+ flowIntoCall(call, arg, p, allowsFieldFlow, config) and
+ innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutNotFromArg(
+ NodeEx out, Cc ccOut, ApOption argAp, Ap ap, Configuration config
+ ) {
+ exists(
+ DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
+ DataFlowCallable inner
+ |
+ fwdFlow(ret, innercc, argAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ inner = ret.getEnclosingCallable() and
+ ccOut = getCallContextReturn(inner, call, innercc)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutFromArg(
+ DataFlowCall call, NodeEx out, Ap argAp, Ap ap, Configuration config
+ ) {
+ exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
+ fwdFlow(ret, ccc, apSome(argAp), ap, config) and
+ flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ ccc.matchesCall(call)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ /**
+ * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`
+ * and data might flow through the target callable and back out at `call`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowIsEntered(
+ DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p |
+ fwdFlowIn(call, p, cc, _, argAp, ap, config) and
+ PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate storeStepFwd(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config
+ ) {
+ fwdFlowStore(node1, ap1, tc, node2, _, _, config) and
+ ap2 = apCons(tc, ap1) and
+ fwdFlowRead(ap2, tc.getContent(), _, _, _, _, config)
+ }
+
+ private predicate readStepFwd(
+ NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config
+ ) {
+ fwdFlowRead(ap1, c, n1, n2, _, _, config) and
+ fwdFlowConsCand(ap1, c, ap2, config)
+ }
+
+ pragma[nomagic]
+ private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) {
+ exists(Ap argAp0, NodeEx out, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
+ pragma[only_bind_into](config)) and
+ fwdFlowOutFromArg(call, out, argAp0, ap, config) and
+ fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
+ pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
+ pragma[only_bind_into](config))
+ )
+ }
+
+ pragma[nomagic]
+ private predicate flowThroughIntoCall(
+ DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowIntoCall(call, arg, p, allowsFieldFlow, config) and
+ fwdFlow(arg, _, _, _, pragma[only_bind_into](config)) and
+ PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and
+ callMayFlowThroughFwd(call, pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if `node` with access path `ap` is part of a path from a source to a
+ * sink in the configuration `config`.
+ *
+ * The Boolean `toReturn` records whether the node must be returned from the
+ * enclosing callable in order to reach a sink, and if so, `returnAp` records
+ * the access path of the returned value.
+ */
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
+ revFlow0(node, toReturn, returnAp, ap, config) and
+ fwdFlow(node, _, _, ap, config)
+ }
+
+ pragma[nomagic]
+ private predicate revFlow0(
+ NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ fwdFlow(node, _, _, ap, config) and
+ sinkNode(node, config) and
+ (if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ or
+ exists(NodeEx mid |
+ localStep(node, mid, true, _, config, _) and
+ revFlow(mid, toReturn, returnAp, ap, config)
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ localStep(node, mid, false, _, config, _) and
+ revFlow(mid, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
+ ap instanceof ApNil
+ )
+ or
+ exists(NodeEx mid |
+ jumpStep(node, mid, config) and
+ revFlow(mid, _, _, ap, config) and
+ toReturn = false and
+ returnAp = apNone()
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ additionalJumpStep(node, mid, config) and
+ revFlow(pragma[only_bind_into](mid), _, _, nil, pragma[only_bind_into](config)) and
+ toReturn = false and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ )
+ or
+ // store
+ exists(Ap ap0, Content c |
+ revFlowStore(ap0, c, ap, node, _, _, toReturn, returnAp, config) and
+ revFlowConsCand(ap0, c, ap, config)
+ )
+ or
+ // read
+ exists(NodeEx mid, Ap ap0 |
+ revFlow(mid, toReturn, returnAp, ap0, config) and
+ readStepFwd(node, ap, _, mid, ap0, config)
+ )
+ or
+ // flow into a callable
+ revFlowInNotToReturn(node, returnAp, ap, config) and
+ toReturn = false
+ or
+ exists(DataFlowCall call, Ap returnAp0 |
+ revFlowInToReturn(call, node, returnAp0, ap, config) and
+ revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
+ )
+ or
+ // flow out of a callable
+ revFlowOut(_, node, _, _, ap, config) and
+ toReturn = true and
+ if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
+ then returnAp = apSome(ap)
+ else returnAp = apNone()
+ }
+
+ pragma[nomagic]
+ private predicate revFlowStore(
+ Ap ap0, Content c, Ap ap, NodeEx node, TypedContent tc, NodeEx mid, boolean toReturn,
+ ApOption returnAp, Configuration config
+ ) {
+ revFlow(mid, toReturn, returnAp, ap0, config) and
+ storeStepFwd(node, ap, tc, mid, ap0, config) and
+ tc.getContent() = c
+ }
+
+ /**
+ * Holds if reverse flow with access path `tail` reaches a read of `c`
+ * resulting in access path `cons`.
+ */
+ pragma[nomagic]
+ private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
+ exists(NodeEx mid, Ap tail0 |
+ revFlow(mid, _, _, tail, config) and
+ tail = pragma[only_bind_into](tail0) and
+ readStepFwd(_, cons, c, mid, tail0, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowOut(
+ DataFlowCall call, RetNodeEx ret, boolean toReturn, ApOption returnAp, Ap ap,
+ Configuration config
+ ) {
+ exists(NodeEx out, boolean allowsFieldFlow |
+ revFlow(out, toReturn, returnAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInNotToReturn(
+ ArgNodeEx arg, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p, boolean allowsFieldFlow |
+ revFlow(p, false, returnAp, ap, config) and
+ flowIntoCall(_, arg, p, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInToReturn(
+ DataFlowCall call, ArgNodeEx arg, Ap returnAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p, boolean allowsFieldFlow |
+ revFlow(p, true, apSome(returnAp), ap, config) and
+ flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ /**
+ * Holds if an output from `call` is reached in the flow covered by `revFlow`
+ * and data might flow through the target callable resulting in reverse flow
+ * reaching an argument of `call`.
+ */
+ pragma[nomagic]
+ private predicate revFlowIsReturned(
+ DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ exists(RetNodeEx ret, CcCall ccc |
+ revFlowOut(call, ret, toReturn, returnAp, ap, config) and
+ fwdFlow(ret, ccc, apSome(_), ap, config) and
+ ccc.matchesCall(call)
+ )
+ }
+
+ pragma[nomagic]
+ predicate storeStepCand(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
+ Configuration config
+ ) {
+ exists(Ap ap2, Content c |
+ store(node1, tc, node2, contentType, config) and
+ revFlowStore(ap2, c, ap1, node1, tc, node2, _, _, config) and
+ revFlowConsCand(ap2, c, ap1, config)
+ )
+ }
+
+ predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) {
+ exists(Ap ap1, Ap ap2 |
+ revFlow(node2, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
+ readStepFwd(node1, ap1, c, node2, ap2, config) and
+ revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _,
+ pragma[only_bind_into](config))
+ )
+ }
+
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, config) }
+
+ private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) {
+ storeStepFwd(_, ap, tc, _, _, config)
+ }
+
+ predicate consCand(TypedContent tc, Ap ap, Configuration config) {
+ storeStepCand(_, ap, tc, _, _, config)
+ }
+
+ pragma[noinline]
+ private predicate parameterFlow(
+ ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ) {
+ revFlow(p, true, apSome(ap0), ap, config) and
+ c = p.getEnclosingCallable()
+ }
+
+ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
+ exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
+ parameterFlow(p, ap, ap0, c, config) and
+ c = ret.getEnclosingCallable() and
+ revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
+ pragma[only_bind_into](config)) and
+ fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
+ kind = ret.getKind() and
+ p.getPosition() = pos and
+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
+ (
+ not kind.(ParamUpdateReturnKind).getPosition() = pos
+ or
+ p.allowParameterReturnInSelf()
+ )
+ )
+ }
+
+ pragma[nomagic]
+ predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
+ exists(Ap returnAp0, ArgNodeEx arg, boolean toReturn, ApOption returnAp, Ap ap |
+ revFlow(arg, toReturn, returnAp, ap, config) and
+ revFlowInToReturn(call, arg, returnAp0, ap, config) and
+ revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
+ )
+ }
+
+ predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ fwd = true and
+ nodes = count(NodeEx node | fwdFlow(node, _, _, _, config)) and
+ fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and
+ conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
+ tuples = count(NodeEx n, Cc cc, ApOption argAp, Ap ap | fwdFlow(n, cc, argAp, ap, config))
+ or
+ fwd = false and
+ nodes = count(NodeEx node | revFlow(node, _, _, _, config)) and
+ fields = count(TypedContent f0 | consCand(f0, _, config)) and
+ conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and
+ tuples = count(NodeEx n, boolean b, ApOption retAp, Ap ap | revFlow(n, b, retAp, ap, config))
+ }
+ /* End: Stage 3 logic. */
+}
+
+/**
+ * Holds if `argApf` is recorded as the summary context for flow reaching `node`
+ * and remains relevant for the following pruning stage.
+ */
+private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
+ exists(AccessPathFront apf |
+ Stage3::revFlow(node, true, _, apf, config) and
+ Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
+ )
+}
+
+/**
+ * Holds if a length 2 access path approximation with the head `tc` is expected
+ * to be expensive.
+ */
+private predicate expensiveLen2unfolding(TypedContent tc, Configuration config) {
+ exists(int tails, int nodes, int apLimit, int tupleLimit |
+ tails = strictcount(AccessPathFront apf | Stage3::consCand(tc, apf, config)) and
+ nodes =
+ strictcount(NodeEx n |
+ Stage3::revFlow(n, _, _, any(AccessPathFrontHead apf | apf.getHead() = tc), config)
+ or
+ flowCandSummaryCtx(n, any(AccessPathFrontHead apf | apf.getHead() = tc), config)
+ ) and
+ accessPathApproxCostLimits(apLimit, tupleLimit) and
+ apLimit < tails and
+ tupleLimit < (tails - 1) * nodes and
+ not tc.forceHighPrecision()
+ )
+}
+
+private newtype TAccessPathApprox =
+ TNil(DataFlowType t) or
+ TConsNil(TypedContent tc, DataFlowType t) {
+ Stage3::consCand(tc, TFrontNil(t), _) and
+ not expensiveLen2unfolding(tc, _)
+ } or
+ TConsCons(TypedContent tc1, TypedContent tc2, int len) {
+ Stage3::consCand(tc1, TFrontHead(tc2), _) and
+ len in [2 .. accessPathLimit()] and
+ not expensiveLen2unfolding(tc1, _)
+ } or
+ TCons1(TypedContent tc, int len) {
+ len in [1 .. accessPathLimit()] and
+ expensiveLen2unfolding(tc, _)
+ }
+
+/**
+ * Conceptually a list of `TypedContent`s followed by a `DataFlowType`, but only
+ * the first two elements of the list and its length are tracked. If data flows
+ * from a source to a given node with a given `AccessPathApprox`, this indicates
+ * the sequence of dereference operations needed to get from the value in the node
+ * to the tracked object. The final type indicates the type of the tracked object.
+ */
+abstract private class AccessPathApprox extends TAccessPathApprox {
+ abstract string toString();
+
+ abstract TypedContent getHead();
+
+ abstract int len();
+
+ abstract DataFlowType getType();
+
+ abstract AccessPathFront getFront();
+
+ /** Gets the access path obtained by popping `head` from this path, if any. */
+ abstract AccessPathApprox pop(TypedContent head);
+}
+
+private class AccessPathApproxNil extends AccessPathApprox, TNil {
+ private DataFlowType t;
+
+ AccessPathApproxNil() { this = TNil(t) }
+
+ override string toString() { result = concat(": " + ppReprType(t)) }
+
+ override TypedContent getHead() { none() }
+
+ override int len() { result = 0 }
+
+ override DataFlowType getType() { result = t }
+
+ override AccessPathFront getFront() { result = TFrontNil(t) }
+
+ override AccessPathApprox pop(TypedContent head) { none() }
+}
+
+abstract private class AccessPathApproxCons extends AccessPathApprox { }
+
+private class AccessPathApproxConsNil extends AccessPathApproxCons, TConsNil {
+ private TypedContent tc;
+ private DataFlowType t;
+
+ AccessPathApproxConsNil() { this = TConsNil(tc, t) }
+
+ override string toString() {
+ // The `concat` becomes "" if `ppReprType` has no result.
+ result = "[" + tc.toString() + "]" + concat(" : " + ppReprType(t))
+ }
+
+ override TypedContent getHead() { result = tc }
+
+ override int len() { result = 1 }
+
+ override DataFlowType getType() { result = tc.getContainerType() }
+
+ override AccessPathFront getFront() { result = TFrontHead(tc) }
+
+ override AccessPathApprox pop(TypedContent head) { head = tc and result = TNil(t) }
+}
+
+private class AccessPathApproxConsCons extends AccessPathApproxCons, TConsCons {
+ private TypedContent tc1;
+ private TypedContent tc2;
+ private int len;
+
+ AccessPathApproxConsCons() { this = TConsCons(tc1, tc2, len) }
+
+ override string toString() {
+ if len = 2
+ then result = "[" + tc1.toString() + ", " + tc2.toString() + "]"
+ else result = "[" + tc1.toString() + ", " + tc2.toString() + ", ... (" + len.toString() + ")]"
+ }
+
+ override TypedContent getHead() { result = tc1 }
+
+ override int len() { result = len }
+
+ override DataFlowType getType() { result = tc1.getContainerType() }
+
+ override AccessPathFront getFront() { result = TFrontHead(tc1) }
+
+ override AccessPathApprox pop(TypedContent head) {
+ head = tc1 and
+ (
+ result = TConsCons(tc2, _, len - 1)
+ or
+ len = 2 and
+ result = TConsNil(tc2, _)
+ or
+ result = TCons1(tc2, len - 1)
+ )
+ }
+}
+
+private class AccessPathApproxCons1 extends AccessPathApproxCons, TCons1 {
+ private TypedContent tc;
+ private int len;
+
+ AccessPathApproxCons1() { this = TCons1(tc, len) }
+
+ override string toString() {
+ if len = 1
+ then result = "[" + tc.toString() + "]"
+ else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]"
+ }
+
+ override TypedContent getHead() { result = tc }
+
+ override int len() { result = len }
+
+ override DataFlowType getType() { result = tc.getContainerType() }
+
+ override AccessPathFront getFront() { result = TFrontHead(tc) }
+
+ override AccessPathApprox pop(TypedContent head) {
+ head = tc and
+ (
+ exists(TypedContent tc2 | Stage3::consCand(tc, TFrontHead(tc2), _) |
+ result = TConsCons(tc2, _, len - 1)
+ or
+ len = 2 and
+ result = TConsNil(tc2, _)
+ or
+ result = TCons1(tc2, len - 1)
+ )
+ or
+ exists(DataFlowType t |
+ len = 1 and
+ Stage3::consCand(tc, TFrontNil(t), _) and
+ result = TNil(t)
+ )
+ )
+ }
+}
+
+/** Gets the access path obtained by popping `tc` from `ap`, if any. */
+private AccessPathApprox pop(TypedContent tc, AccessPathApprox apa) { result = apa.pop(tc) }
+
+/** Gets the access path obtained by pushing `tc` onto `ap`. */
+private AccessPathApprox push(TypedContent tc, AccessPathApprox apa) { apa = pop(tc, result) }
+
+private newtype TAccessPathApproxOption =
+ TAccessPathApproxNone() or
+ TAccessPathApproxSome(AccessPathApprox apa)
+
+private class AccessPathApproxOption extends TAccessPathApproxOption {
+ string toString() {
+ this = TAccessPathApproxNone() and result = ""
+ or
+ this = TAccessPathApproxSome(any(AccessPathApprox apa | result = apa.toString()))
+ }
+}
+
+private module Stage4 {
+ module PrevStage = Stage3;
+
+ class ApApprox = PrevStage::Ap;
+
+ class Ap = AccessPathApprox;
+
+ class ApNil = AccessPathApproxNil;
+
+ private ApApprox getApprox(Ap ap) { result = ap.getFront() }
+
+ private ApNil getApNil(NodeEx node) {
+ PrevStage::revFlow(node, _) and result = TNil(node.getDataFlowType())
+ }
+
+ bindingset[tc, tail]
+ private Ap apCons(TypedContent tc, Ap tail) { result = push(tc, tail) }
+
+ pragma[noinline]
+ private Content getHeadContent(Ap ap) { result = ap.getHead().getContent() }
+
+ class ApOption = AccessPathApproxOption;
+
+ ApOption apNone() { result = TAccessPathApproxNone() }
+
+ ApOption apSome(Ap ap) { result = TAccessPathApproxSome(ap) }
+
+ class Cc = CallContext;
+
+ class CcCall = CallContextCall;
+
+ class CcNoCall = CallContextNoCall;
+
+ Cc ccNone() { result instanceof CallContextAny }
+
+ CcCall ccSomeCall() { result instanceof CallContextSomeCall }
+
+ private class LocalCc = LocalCallContext;
+
+ bindingset[call, c, outercc]
+ private CcCall getCallContextCall(DataFlowCall call, DataFlowCallable c, Cc outercc) {
+ checkCallContextCall(outercc, call, c) and
+ if recordDataFlowCallSite(call, c) then result = TSpecificCall(call) else result = TSomeCall()
+ }
+
+ bindingset[call, c, innercc]
+ private CcNoCall getCallContextReturn(DataFlowCallable c, DataFlowCall call, Cc innercc) {
+ checkCallContextReturn(innercc, c, call) and
+ if reducedViableImplInReturn(c, call) then result = TReturn(c, call) else result = ccNone()
+ }
+
+ bindingset[node, cc, config]
+ private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
+ localFlowEntry(node, config) and
+ result =
+ getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
+ node.getEnclosingCallable())
+ }
+
+ private predicate localStep(
+ NodeEx node1, NodeEx node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc
+ ) {
+ localFlowBigStep(node1, node2, preservesValue, ap.getFront(), config, lcc)
+ }
+
+ pragma[nomagic]
+ private predicate flowOutOfCall(
+ DataFlowCall call, RetNodeEx node1, NodeEx node2, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowOutOfCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
+ PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
+ PrevStage::revFlow(node1, _, _, _, pragma[only_bind_into](config))
+ }
+
+ pragma[nomagic]
+ private predicate flowIntoCall(
+ DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow,
+ Configuration config
+ ) {
+ flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
+ PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
+ PrevStage::revFlow(node1, _, _, _, pragma[only_bind_into](config))
+ }
+
+ bindingset[node, ap]
+ private predicate filter(NodeEx node, Ap ap) { any() }
+
+ // Type checking is not necessary here as it has already been done in stage 3.
+ bindingset[ap, contentType]
+ private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
+
+ /* Begin: Stage 4 logic. */
+ private predicate flowCand(NodeEx node, ApApprox apa, Configuration config) {
+ PrevStage::revFlow(node, _, _, apa, config)
+ }
+
+ bindingset[result, apa]
+ private ApApprox unbindApa(ApApprox apa) {
+ exists(ApApprox apa0 |
+ apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate flowThroughOutOfCall(
+ DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
+ PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
+ PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
+ pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if `node` is reachable with access path `ap` from a source in the
+ * configuration `config`.
+ *
+ * The call context `cc` records whether the node is reached through an
+ * argument in a call, and if so, `argAp` records the access path of that
+ * argument.
+ */
+ pragma[nomagic]
+ predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ fwdFlow0(node, cc, argAp, ap, config) and
+ flowCand(node, unbindApa(getApprox(ap)), config) and
+ filter(node, ap)
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ flowCand(node, _, config) and
+ sourceNode(node, config) and
+ (if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
+ argAp = apNone() and
+ ap = getApNil(node)
+ or
+ exists(NodeEx mid, Ap ap0, LocalCc localCc |
+ fwdFlow(mid, cc, argAp, ap0, config) and
+ localCc = getLocalCc(mid, cc, config)
+ |
+ localStep(mid, node, true, _, config, localCc) and
+ ap = ap0
+ or
+ localStep(mid, node, false, ap, config, localCc) and
+ ap0 instanceof ApNil
+ )
+ or
+ exists(NodeEx mid |
+ fwdFlow(mid, _, _, ap, pragma[only_bind_into](config)) and
+ flowCand(node, _, pragma[only_bind_into](config)) and
+ jumpStep(mid, node, config) and
+ cc = ccNone() and
+ argAp = apNone()
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(mid, _, _, nil, pragma[only_bind_into](config)) and
+ flowCand(node, _, pragma[only_bind_into](config)) and
+ additionalJumpStep(mid, node, config) and
+ cc = ccNone() and
+ argAp = apNone() and
+ ap = getApNil(node)
+ )
+ or
+ // store
+ exists(TypedContent tc, Ap ap0 |
+ fwdFlowStore(_, ap0, tc, node, cc, argAp, config) and
+ ap = apCons(tc, ap0)
+ )
+ or
+ // read
+ exists(Ap ap0, Content c |
+ fwdFlowRead(ap0, c, _, node, cc, argAp, config) and
+ fwdFlowConsCand(ap0, c, ap, config)
+ )
+ or
+ // flow into a callable
+ exists(ApApprox apa |
+ fwdFlowIn(_, node, _, cc, _, ap, config) and
+ apa = getApprox(ap) and
+ if PrevStage::parameterMayFlowThrough(node, _, apa, config)
+ then argAp = apSome(ap)
+ else argAp = apNone()
+ )
+ or
+ // flow out of a callable
+ fwdFlowOutNotFromArg(node, cc, argAp, ap, config)
+ or
+ exists(DataFlowCall call, Ap argAp0 |
+ fwdFlowOutFromArg(call, node, argAp0, ap, config) and
+ fwdFlowIsEntered(call, cc, argAp, argAp0, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowStore(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ ) {
+ exists(DataFlowType contentType |
+ fwdFlow(node1, cc, argAp, ap1, config) and
+ PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
+ typecheckStore(ap1, contentType)
+ )
+ }
+
+ /**
+ * Holds if forward flow with access path `tail` reaches a store of `c`
+ * resulting in access path `cons`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
+ exists(TypedContent tc |
+ fwdFlowStore(_, tail, tc, _, _, _, config) and
+ tc.getContent() = c and
+ cons = apCons(tc, tail)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowRead(
+ Ap ap, Content c, NodeEx node1, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ ) {
+ fwdFlow(node1, cc, argAp, ap, config) and
+ PrevStage::readStepCand(node1, c, node2, config) and
+ getHeadContent(ap) = c
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowIn(
+ DataFlowCall call, ParamNodeEx p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
+ Configuration config
+ ) {
+ exists(ArgNodeEx arg, boolean allowsFieldFlow |
+ fwdFlow(arg, outercc, argAp, ap, config) and
+ flowIntoCall(call, arg, p, allowsFieldFlow, config) and
+ innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutNotFromArg(
+ NodeEx out, Cc ccOut, ApOption argAp, Ap ap, Configuration config
+ ) {
+ exists(
+ DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
+ DataFlowCallable inner
+ |
+ fwdFlow(ret, innercc, argAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ inner = ret.getEnclosingCallable() and
+ ccOut = getCallContextReturn(inner, call, innercc)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlowOutFromArg(
+ DataFlowCall call, NodeEx out, Ap argAp, Ap ap, Configuration config
+ ) {
+ exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
+ fwdFlow(ret, ccc, apSome(argAp), ap, config) and
+ flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ ccc.matchesCall(call)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ /**
+ * Holds if an argument to `call` is reached in the flow covered by `fwdFlow`
+ * and data might flow through the target callable and back out at `call`.
+ */
+ pragma[nomagic]
+ private predicate fwdFlowIsEntered(
+ DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p |
+ fwdFlowIn(call, p, cc, _, argAp, ap, config) and
+ PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate storeStepFwd(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config
+ ) {
+ fwdFlowStore(node1, ap1, tc, node2, _, _, config) and
+ ap2 = apCons(tc, ap1) and
+ fwdFlowRead(ap2, tc.getContent(), _, _, _, _, config)
+ }
+
+ private predicate readStepFwd(
+ NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config
+ ) {
+ fwdFlowRead(ap1, c, n1, n2, _, _, config) and
+ fwdFlowConsCand(ap1, c, ap2, config)
+ }
+
+ pragma[nomagic]
+ private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) {
+ exists(Ap argAp0, NodeEx out, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
+ pragma[only_bind_into](config)) and
+ fwdFlowOutFromArg(call, out, argAp0, ap, config) and
+ fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
+ pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
+ pragma[only_bind_into](config))
+ )
+ }
+
+ pragma[nomagic]
+ private predicate flowThroughIntoCall(
+ DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
+ ) {
+ flowIntoCall(call, arg, p, allowsFieldFlow, config) and
+ fwdFlow(arg, _, _, _, pragma[only_bind_into](config)) and
+ PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and
+ callMayFlowThroughFwd(call, pragma[only_bind_into](config))
+ }
+
+ /**
+ * Holds if `node` with access path `ap` is part of a path from a source to a
+ * sink in the configuration `config`.
+ *
+ * The Boolean `toReturn` records whether the node must be returned from the
+ * enclosing callable in order to reach a sink, and if so, `returnAp` records
+ * the access path of the returned value.
+ */
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
+ revFlow0(node, toReturn, returnAp, ap, config) and
+ fwdFlow(node, _, _, ap, config)
+ }
+
+ pragma[nomagic]
+ private predicate revFlow0(
+ NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ fwdFlow(node, _, _, ap, config) and
+ sinkNode(node, config) and
+ (if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ or
+ exists(NodeEx mid |
+ localStep(node, mid, true, _, config, _) and
+ revFlow(mid, toReturn, returnAp, ap, config)
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ localStep(node, mid, false, _, config, _) and
+ revFlow(mid, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
+ ap instanceof ApNil
+ )
+ or
+ exists(NodeEx mid |
+ jumpStep(node, mid, config) and
+ revFlow(mid, _, _, ap, config) and
+ toReturn = false and
+ returnAp = apNone()
+ )
+ or
+ exists(NodeEx mid, ApNil nil |
+ fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ additionalJumpStep(node, mid, config) and
+ revFlow(pragma[only_bind_into](mid), _, _, nil, pragma[only_bind_into](config)) and
+ toReturn = false and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ )
+ or
+ // store
+ exists(Ap ap0, Content c |
+ revFlowStore(ap0, c, ap, node, _, _, toReturn, returnAp, config) and
+ revFlowConsCand(ap0, c, ap, config)
+ )
+ or
+ // read
+ exists(NodeEx mid, Ap ap0 |
+ revFlow(mid, toReturn, returnAp, ap0, config) and
+ readStepFwd(node, ap, _, mid, ap0, config)
+ )
+ or
+ // flow into a callable
+ revFlowInNotToReturn(node, returnAp, ap, config) and
+ toReturn = false
+ or
+ exists(DataFlowCall call, Ap returnAp0 |
+ revFlowInToReturn(call, node, returnAp0, ap, config) and
+ revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
+ )
+ or
+ // flow out of a callable
+ revFlowOut(_, node, _, _, ap, config) and
+ toReturn = true and
+ if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
+ then returnAp = apSome(ap)
+ else returnAp = apNone()
+ }
+
+ pragma[nomagic]
+ private predicate revFlowStore(
+ Ap ap0, Content c, Ap ap, NodeEx node, TypedContent tc, NodeEx mid, boolean toReturn,
+ ApOption returnAp, Configuration config
+ ) {
+ revFlow(mid, toReturn, returnAp, ap0, config) and
+ storeStepFwd(node, ap, tc, mid, ap0, config) and
+ tc.getContent() = c
+ }
+
+ /**
+ * Holds if reverse flow with access path `tail` reaches a read of `c`
+ * resulting in access path `cons`.
+ */
+ pragma[nomagic]
+ private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
+ exists(NodeEx mid, Ap tail0 |
+ revFlow(mid, _, _, tail, config) and
+ tail = pragma[only_bind_into](tail0) and
+ readStepFwd(_, cons, c, mid, tail0, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowOut(
+ DataFlowCall call, RetNodeEx ret, boolean toReturn, ApOption returnAp, Ap ap,
+ Configuration config
+ ) {
+ exists(NodeEx out, boolean allowsFieldFlow |
+ revFlow(out, toReturn, returnAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInNotToReturn(
+ ArgNodeEx arg, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p, boolean allowsFieldFlow |
+ revFlow(p, false, returnAp, ap, config) and
+ flowIntoCall(_, arg, p, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revFlowInToReturn(
+ DataFlowCall call, ArgNodeEx arg, Ap returnAp, Ap ap, Configuration config
+ ) {
+ exists(ParamNodeEx p, boolean allowsFieldFlow |
+ revFlow(p, true, apSome(returnAp), ap, config) and
+ flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
+ |
+ ap instanceof ApNil or allowsFieldFlow = true
+ )
+ }
+
+ /**
+ * Holds if an output from `call` is reached in the flow covered by `revFlow`
+ * and data might flow through the target callable resulting in reverse flow
+ * reaching an argument of `call`.
+ */
+ pragma[nomagic]
+ private predicate revFlowIsReturned(
+ DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ exists(RetNodeEx ret, CcCall ccc |
+ revFlowOut(call, ret, toReturn, returnAp, ap, config) and
+ fwdFlow(ret, ccc, apSome(_), ap, config) and
+ ccc.matchesCall(call)
+ )
+ }
+
+ pragma[nomagic]
+ predicate storeStepCand(
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
+ Configuration config
+ ) {
+ exists(Ap ap2, Content c |
+ store(node1, tc, node2, contentType, config) and
+ revFlowStore(ap2, c, ap1, node1, tc, node2, _, _, config) and
+ revFlowConsCand(ap2, c, ap1, config)
+ )
+ }
+
+ predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) {
+ exists(Ap ap1, Ap ap2 |
+ revFlow(node2, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
+ readStepFwd(node1, ap1, c, node2, ap2, config) and
+ revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _,
+ pragma[only_bind_into](config))
+ )
+ }
+
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, config) }
+
+ private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) {
+ storeStepFwd(_, ap, tc, _, _, config)
+ }
+
+ predicate consCand(TypedContent tc, Ap ap, Configuration config) {
+ storeStepCand(_, ap, tc, _, _, config)
+ }
+
+ pragma[noinline]
+ private predicate parameterFlow(
+ ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
+ ) {
+ revFlow(p, true, apSome(ap0), ap, config) and
+ c = p.getEnclosingCallable()
+ }
+
+ predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
+ exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
+ parameterFlow(p, ap, ap0, c, config) and
+ c = ret.getEnclosingCallable() and
+ revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
+ pragma[only_bind_into](config)) and
+ fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
+ kind = ret.getKind() and
+ p.getPosition() = pos and
+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
+ (
+ not kind.(ParamUpdateReturnKind).getPosition() = pos
+ or
+ p.allowParameterReturnInSelf()
+ )
+ )
+ }
+
+ pragma[nomagic]
+ predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
+ exists(Ap returnAp0, ArgNodeEx arg, boolean toReturn, ApOption returnAp, Ap ap |
+ revFlow(arg, toReturn, returnAp, ap, config) and
+ revFlowInToReturn(call, arg, returnAp0, ap, config) and
+ revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
+ )
+ }
+
+ predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ fwd = true and
+ nodes = count(NodeEx node | fwdFlow(node, _, _, _, config)) and
+ fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and
+ conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
+ tuples = count(NodeEx n, Cc cc, ApOption argAp, Ap ap | fwdFlow(n, cc, argAp, ap, config))
+ or
+ fwd = false and
+ nodes = count(NodeEx node | revFlow(node, _, _, _, config)) and
+ fields = count(TypedContent f0 | consCand(f0, _, config)) and
+ conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and
+ tuples = count(NodeEx n, boolean b, ApOption retAp, Ap ap | revFlow(n, b, retAp, ap, config))
+ }
+ /* End: Stage 4 logic. */
+}
+
+bindingset[conf, result]
+private Configuration unbindConf(Configuration conf) {
+ exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
+}
+
+private predicate nodeMayUseSummary(NodeEx n, AccessPathApprox apa, Configuration config) {
+ exists(DataFlowCallable c, AccessPathApprox apa0 |
+ Stage4::parameterMayFlowThrough(_, c, apa, _) and
+ Stage4::revFlow(n, true, _, apa0, config) and
+ Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
+ n.getEnclosingCallable() = c
+ )
+}
+
+private newtype TSummaryCtx =
+ TSummaryCtxNone() or
+ TSummaryCtxSome(ParamNodeEx p, AccessPath ap) {
+ Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
+ }
+
+/**
+ * A context for generating flow summaries. This represents flow entry through
+ * a specific parameter with an access path of a specific shape.
+ *
+ * Summaries are only created for parameters that may flow through.
+ */
+abstract private class SummaryCtx extends TSummaryCtx {
+ abstract string toString();
+}
+
+/** A summary context from which no flow summary can be generated. */
+private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
+ override string toString() { result = "" }
+}
+
+/** A summary context from which a flow summary can be generated. */
+private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
+ private ParamNodeEx p;
+ private AccessPath ap;
+
+ SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
+
+ int getParameterPos() { p.isParameterOf(_, result) }
+
+ ParamNodeEx getParamNode() { result = p }
+
+ override string toString() { result = p + ": " + ap }
+
+ predicate hasLocationInfo(
+ string filepath, int startline, int startcolumn, int endline, int endcolumn
+ ) {
+ p.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
+ }
+}
+
+/**
+ * Gets the number of length 2 access path approximations that correspond to `apa`.
+ */
+private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) {
+ exists(TypedContent tc, int len |
+ tc = apa.getHead() and
+ len = apa.len() and
+ result =
+ strictcount(AccessPathFront apf |
+ Stage4::consCand(tc, any(AccessPathApprox ap | ap.getFront() = apf and ap.len() = len - 1),
+ config)
+ )
+ )
+}
+
+private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) {
+ result =
+ strictcount(NodeEx n |
+ Stage4::revFlow(n, _, _, apa, config) or nodeMayUseSummary(n, apa, config)
+ )
+}
+
+/**
+ * Holds if a length 2 access path approximation matching `apa` is expected
+ * to be expensive.
+ */
+private predicate expensiveLen1to2unfolding(AccessPathApproxCons1 apa, Configuration config) {
+ exists(int aps, int nodes, int apLimit, int tupleLimit |
+ aps = count1to2unfold(apa, config) and
+ nodes = countNodesUsingAccessPath(apa, config) and
+ accessPathCostLimits(apLimit, tupleLimit) and
+ apLimit < aps and
+ tupleLimit < (aps - 1) * nodes
+ )
+}
+
+private AccessPathApprox getATail(AccessPathApprox apa, Configuration config) {
+ exists(TypedContent head |
+ apa.pop(head) = result and
+ Stage4::consCand(head, result, config)
+ )
+}
+
+/**
+ * Holds with `unfold = false` if a precise head-tail representation of `apa` is
+ * expected to be expensive. Holds with `unfold = true` otherwise.
+ */
+private predicate evalUnfold(AccessPathApprox apa, boolean unfold, Configuration config) {
+ if apa.getHead().forceHighPrecision()
+ then unfold = true
+ else
+ exists(int aps, int nodes, int apLimit, int tupleLimit |
+ aps = countPotentialAps(apa, config) and
+ nodes = countNodesUsingAccessPath(apa, config) and
+ accessPathCostLimits(apLimit, tupleLimit) and
+ if apLimit < aps and tupleLimit < (aps - 1) * nodes then unfold = false else unfold = true
+ )
+}
+
+/**
+ * Gets the number of `AccessPath`s that correspond to `apa`.
+ */
+private int countAps(AccessPathApprox apa, Configuration config) {
+ evalUnfold(apa, false, config) and
+ result = 1 and
+ (not apa instanceof AccessPathApproxCons1 or expensiveLen1to2unfolding(apa, config))
+ or
+ evalUnfold(apa, false, config) and
+ result = count1to2unfold(apa, config) and
+ not expensiveLen1to2unfolding(apa, config)
+ or
+ evalUnfold(apa, true, config) and
+ result = countPotentialAps(apa, config)
+}
+
+/**
+ * Gets the number of `AccessPath`s that would correspond to `apa` assuming
+ * that it is expanded to a precise head-tail representation.
+ */
+language[monotonicAggregates]
+private int countPotentialAps(AccessPathApprox apa, Configuration config) {
+ apa instanceof AccessPathApproxNil and result = 1
+ or
+ result = strictsum(AccessPathApprox tail | tail = getATail(apa, config) | countAps(tail, config))
+}
+
+private newtype TAccessPath =
+ TAccessPathNil(DataFlowType t) or
+ TAccessPathCons(TypedContent head, AccessPath tail) {
+ exists(AccessPathApproxCons apa |
+ not evalUnfold(apa, false, _) and
+ head = apa.getHead() and
+ tail.getApprox() = getATail(apa, _)
+ )
+ } or
+ TAccessPathCons2(TypedContent head1, TypedContent head2, int len) {
+ exists(AccessPathApproxCons apa |
+ evalUnfold(apa, false, _) and
+ not expensiveLen1to2unfolding(apa, _) and
+ apa.len() = len and
+ head1 = apa.getHead() and
+ head2 = getATail(apa, _).getHead()
+ )
+ } or
+ TAccessPathCons1(TypedContent head, int len) {
+ exists(AccessPathApproxCons apa |
+ evalUnfold(apa, false, _) and
+ expensiveLen1to2unfolding(apa, _) and
+ apa.len() = len and
+ head = apa.getHead()
+ )
+ }
+
+private newtype TPathNode =
+ TPathNodeMid(NodeEx node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) {
+ // A PathNode is introduced by a source ...
+ Stage4::revFlow(node, config) and
+ sourceNode(node, config) and
+ (
+ if hasSourceCallCtx(config)
+ then cc instanceof CallContextSomeCall
+ else cc instanceof CallContextAny
+ ) and
+ sc instanceof SummaryCtxNone and
+ ap = TAccessPathNil(node.getDataFlowType())
+ or
+ // ... or a step from an existing PathNode to another node.
+ exists(PathNodeMid mid |
+ pathStep(mid, node, cc, sc, ap) and
+ pragma[only_bind_into](config) = mid.getConfiguration() and
+ Stage4::revFlow(node, _, _, ap.getApprox(), pragma[only_bind_into](config))
+ )
+ } or
+ TPathNodeSink(NodeEx node, Configuration config) {
+ exists(PathNodeMid sink |
+ sink.isAtSink() and
+ node = sink.getNodeEx() and
+ config = sink.getConfiguration()
+ )
+ }
+
+/**
+ * A list of `TypedContent`s followed by a `DataFlowType`. If data flows from a
+ * source to a given node with a given `AccessPath`, this indicates the sequence
+ * of dereference operations needed to get from the value in the node to the
+ * tracked object. The final type indicates the type of the tracked object.
+ */
+abstract private class AccessPath extends TAccessPath {
+ /** Gets the head of this access path, if any. */
+ abstract TypedContent getHead();
+
+ /** Gets the tail of this access path, if any. */
+ abstract AccessPath getTail();
+
+ /** Gets the front of this access path. */
+ abstract AccessPathFront getFront();
+
+ /** Gets the approximation of this access path. */
+ abstract AccessPathApprox getApprox();
+
+ /** Gets the length of this access path. */
+ abstract int length();
+
+ /** Gets a textual representation of this access path. */
+ abstract string toString();
+
+ /** Gets the access path obtained by popping `tc` from this access path, if any. */
+ final AccessPath pop(TypedContent tc) {
+ result = this.getTail() and
+ tc = this.getHead()
+ }
+
+ /** Gets the access path obtained by pushing `tc` onto this access path. */
+ final AccessPath push(TypedContent tc) { this = result.pop(tc) }
+}
+
+private class AccessPathNil extends AccessPath, TAccessPathNil {
+ private DataFlowType t;
+
+ AccessPathNil() { this = TAccessPathNil(t) }
+
+ DataFlowType getType() { result = t }
+
+ override TypedContent getHead() { none() }
+
+ override AccessPath getTail() { none() }
+
+ override AccessPathFrontNil getFront() { result = TFrontNil(t) }
+
+ override AccessPathApproxNil getApprox() { result = TNil(t) }
+
+ override int length() { result = 0 }
+
+ override string toString() { result = concat(": " + ppReprType(t)) }
+}
+
+private class AccessPathCons extends AccessPath, TAccessPathCons {
+ private TypedContent head;
+ private AccessPath tail;
+
+ AccessPathCons() { this = TAccessPathCons(head, tail) }
+
+ override TypedContent getHead() { result = head }
+
+ override AccessPath getTail() { result = tail }
+
+ override AccessPathFrontHead getFront() { result = TFrontHead(head) }
+
+ override AccessPathApproxCons getApprox() {
+ result = TConsNil(head, tail.(AccessPathNil).getType())
+ or
+ result = TConsCons(head, tail.getHead(), this.length())
+ or
+ result = TCons1(head, this.length())
+ }
+
+ override int length() { result = 1 + tail.length() }
+
+ private string toStringImpl(boolean needsSuffix) {
+ exists(DataFlowType t |
+ tail = TAccessPathNil(t) and
+ needsSuffix = false and
+ result = head.toString() + "]" + concat(" : " + ppReprType(t))
+ )
+ or
+ result = head + ", " + tail.(AccessPathCons).toStringImpl(needsSuffix)
+ or
+ exists(TypedContent tc2, TypedContent tc3, int len | tail = TAccessPathCons2(tc2, tc3, len) |
+ result = head + ", " + tc2 + ", " + tc3 + ", ... (" and len > 2 and needsSuffix = true
+ or
+ result = head + ", " + tc2 + ", " + tc3 + "]" and len = 2 and needsSuffix = false
+ )
+ or
+ exists(TypedContent tc2, int len | tail = TAccessPathCons1(tc2, len) |
+ result = head + ", " + tc2 + ", ... (" and len > 1 and needsSuffix = true
+ or
+ result = head + ", " + tc2 + "]" and len = 1 and needsSuffix = false
+ )
+ }
+
+ override string toString() {
+ result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
+ or
+ result = "[" + this.toStringImpl(false)
+ }
+}
+
+private class AccessPathCons2 extends AccessPath, TAccessPathCons2 {
+ private TypedContent head1;
+ private TypedContent head2;
+ private int len;
+
+ AccessPathCons2() { this = TAccessPathCons2(head1, head2, len) }
+
+ override TypedContent getHead() { result = head1 }
+
+ override AccessPath getTail() {
+ Stage4::consCand(head1, result.getApprox(), _) and
+ result.getHead() = head2 and
+ result.length() = len - 1
+ }
+
+ override AccessPathFrontHead getFront() { result = TFrontHead(head1) }
+
+ override AccessPathApproxCons getApprox() {
+ result = TConsCons(head1, head2, len) or
+ result = TCons1(head1, len)
+ }
+
+ override int length() { result = len }
+
+ override string toString() {
+ if len = 2
+ then result = "[" + head1.toString() + ", " + head2.toString() + "]"
+ else
+ result = "[" + head1.toString() + ", " + head2.toString() + ", ... (" + len.toString() + ")]"
+ }
+}
+
+private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
+ private TypedContent head;
+ private int len;
+
+ AccessPathCons1() { this = TAccessPathCons1(head, len) }
+
+ override TypedContent getHead() { result = head }
+
+ override AccessPath getTail() {
+ Stage4::consCand(head, result.getApprox(), _) and result.length() = len - 1
+ }
+
+ override AccessPathFrontHead getFront() { result = TFrontHead(head) }
+
+ override AccessPathApproxCons getApprox() { result = TCons1(head, len) }
+
+ override int length() { result = len }
+
+ override string toString() {
+ if len = 1
+ then result = "[" + head.toString() + "]"
+ else result = "[" + head.toString() + ", ... (" + len.toString() + ")]"
+ }
+}
+
+/**
+ * A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
+ * Only those `PathNode`s that are reachable from a source are generated.
+ */
+class PathNode extends TPathNode {
+ /** Gets a textual representation of this element. */
+ string toString() { none() }
+
+ /**
+ * Gets a textual representation of this element, including a textual
+ * representation of the call context.
+ */
+ string toStringWithContext() { none() }
+
+ /**
+ * Holds if this element is at the specified location.
+ * The location spans column `startcolumn` of line `startline` to
+ * column `endcolumn` of line `endline` in file `filepath`.
+ * For more information, see
+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
+ */
+ predicate hasLocationInfo(
+ string filepath, int startline, int startcolumn, int endline, int endcolumn
+ ) {
+ none()
+ }
+
+ /** Gets the underlying `Node`. */
+ final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
+
+ /** Gets the associated configuration. */
+ Configuration getConfiguration() { none() }
+
+ private PathNode getASuccessorIfHidden() {
+ this.(PathNodeImpl).isHidden() and
+ result = this.(PathNodeImpl).getASuccessorImpl()
+ }
+
+ /** Gets a successor of this node, if any. */
+ final PathNode getASuccessor() {
+ result = this.(PathNodeImpl).getASuccessorImpl().getASuccessorIfHidden*() and
+ not this.(PathNodeImpl).isHidden() and
+ not result.(PathNodeImpl).isHidden()
+ }
+
+ /** Holds if this node is a source. */
+ predicate isSource() { none() }
+}
+
+abstract private class PathNodeImpl extends PathNode {
+ abstract PathNode getASuccessorImpl();
+
+ abstract NodeEx getNodeEx();
+
+ predicate isHidden() {
+ hiddenNode(this.getNodeEx().asNode()) and
+ not this.isSource() and
+ not this instanceof PathNodeSink
+ or
+ this.getNodeEx() instanceof TNodeImplicitRead
+ }
+
+ private string ppAp() {
+ this instanceof PathNodeSink and result = ""
+ or
+ exists(string s | s = this.(PathNodeMid).getAp().toString() |
+ if s = "" then result = "" else result = " " + s
+ )
+ }
+
+ private string ppCtx() {
+ this instanceof PathNodeSink and result = ""
+ or
+ result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
+ }
+
+ override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
+
+ override string toStringWithContext() {
+ result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
+ }
+
+ override predicate hasLocationInfo(
+ string filepath, int startline, int startcolumn, int endline, int endcolumn
+ ) {
+ this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
+ }
+}
+
+/** Holds if `n` can reach a sink. */
+private predicate directReach(PathNode n) {
+ n instanceof PathNodeSink or directReach(n.getASuccessor())
+}
+
+/** Holds if `n` can reach a sink or is used in a subpath. */
+private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
+
+/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
+private predicate pathSucc(PathNode n1, PathNode n2) { n1.getASuccessor() = n2 and directReach(n2) }
+
+private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
+
+/**
+ * Provides the query predicates needed to include a graph in a path-problem query.
+ */
+module PathGraph {
+ /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
+ query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
+
+ /** Holds if `n` is a node in the graph of data flow path explanations. */
+ query predicate nodes(PathNode n, string key, string val) {
+ reach(n) and key = "semmle.label" and val = n.toString()
+ }
+
+ query predicate subpaths = Subpaths::subpaths/4;
+}
+
+/**
+ * An intermediate flow graph node. This is a triple consisting of a `Node`,
+ * a `CallContext`, and a `Configuration`.
+ */
+private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
+ NodeEx node;
+ CallContext cc;
+ SummaryCtx sc;
+ AccessPath ap;
+ Configuration config;
+
+ PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) }
+
+ override NodeEx getNodeEx() { result = node }
+
+ CallContext getCallContext() { result = cc }
+
+ SummaryCtx getSummaryCtx() { result = sc }
+
+ AccessPath getAp() { result = ap }
+
+ override Configuration getConfiguration() { result = config }
+
+ private PathNodeMid getSuccMid() {
+ pathStep(this, result.getNodeEx(), result.getCallContext(), result.getSummaryCtx(),
+ result.getAp()) and
+ result.getConfiguration() = unbindConf(this.getConfiguration())
+ }
+
+ override PathNodeImpl getASuccessorImpl() {
+ // an intermediate step to another intermediate node
+ result = this.getSuccMid()
+ or
+ // a final step to a sink
+ result = this.getSuccMid().projectToSink()
+ }
+
+ override predicate isSource() {
+ sourceNode(node, config) and
+ (
+ if hasSourceCallCtx(config)
+ then cc instanceof CallContextSomeCall
+ else cc instanceof CallContextAny
+ ) and
+ sc instanceof SummaryCtxNone and
+ ap instanceof AccessPathNil
+ }
+
+ predicate isAtSink() {
+ sinkNode(node, config) and
+ ap instanceof AccessPathNil and
+ if hasSinkCallCtx(config)
+ then
+ // For `FeatureHasSinkCallContext` the condition `cc instanceof CallContextNoCall`
+ // is exactly what we need to check. This also implies
+ // `sc instanceof SummaryCtxNone`.
+ // For `FeatureEqualSourceSinkCallContext` the initial call context was
+ // set to `CallContextSomeCall` and jumps are disallowed, so
+ // `cc instanceof CallContextNoCall` never holds. On the other hand,
+ // in this case there's never any need to enter a call except to identify
+ // a summary, so the condition in `pathIntoCallable` enforces this, which
+ // means that `sc instanceof SummaryCtxNone` holds if and only if we are
+ // in the call context of the source.
+ sc instanceof SummaryCtxNone or
+ cc instanceof CallContextNoCall
+ else any()
+ }
+
+ PathNodeSink projectToSink() {
+ this.isAtSink() and
+ result.getNodeEx() = node and
+ result.getConfiguration() = unbindConf(config)
+ }
+}
+
+/**
+ * A flow graph node corresponding to a sink. This is disjoint from the
+ * intermediate nodes in order to uniquely correspond to a given sink by
+ * excluding the `CallContext`.
+ */
+private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
+ NodeEx node;
+ Configuration config;
+
+ PathNodeSink() { this = TPathNodeSink(node, config) }
+
+ override NodeEx getNodeEx() { result = node }
+
+ override Configuration getConfiguration() { result = config }
+
+ override PathNode getASuccessorImpl() { none() }
+
+ override predicate isSource() { sourceNode(node, config) }
+}
+
+/**
+ * Holds if data may flow from `mid` to `node`. The last step in or out of
+ * a callable is recorded by `cc`.
+ */
+private predicate pathStep(
+ PathNodeMid mid, NodeEx node, CallContext cc, SummaryCtx sc, AccessPath ap
+) {
+ exists(AccessPath ap0, NodeEx midnode, Configuration conf, LocalCallContext localCC |
+ midnode = mid.getNodeEx() and
+ conf = mid.getConfiguration() and
+ cc = mid.getCallContext() and
+ sc = mid.getSummaryCtx() and
+ localCC =
+ getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
+ midnode.getEnclosingCallable()) and
+ ap0 = mid.getAp()
+ |
+ localFlowBigStep(midnode, node, true, _, conf, localCC) and
+ ap = ap0
+ or
+ localFlowBigStep(midnode, node, false, ap.getFront(), conf, localCC) and
+ ap0 instanceof AccessPathNil
+ )
+ or
+ jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and
+ cc instanceof CallContextAny and
+ sc instanceof SummaryCtxNone and
+ ap = mid.getAp()
+ or
+ additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and
+ cc instanceof CallContextAny and
+ sc instanceof SummaryCtxNone and
+ mid.getAp() instanceof AccessPathNil and
+ ap = TAccessPathNil(node.getDataFlowType())
+ or
+ exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
+ sc = mid.getSummaryCtx()
+ or
+ exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
+ sc = mid.getSummaryCtx()
+ or
+ pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
+ or
+ pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
+ or
+ pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx()
+}
+
+pragma[nomagic]
+private predicate pathReadStep(
+ PathNodeMid mid, NodeEx node, AccessPath ap0, TypedContent tc, CallContext cc
+) {
+ ap0 = mid.getAp() and
+ tc = ap0.getHead() and
+ Stage4::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and
+ cc = mid.getCallContext()
+}
+
+pragma[nomagic]
+private predicate pathStoreStep(
+ PathNodeMid mid, NodeEx node, AccessPath ap0, TypedContent tc, CallContext cc
+) {
+ ap0 = mid.getAp() and
+ Stage4::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and
+ cc = mid.getCallContext()
+}
+
+private predicate pathOutOfCallable0(
+ PathNodeMid mid, ReturnPosition pos, CallContext innercc, AccessPathApprox apa,
+ Configuration config
+) {
+ pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and
+ innercc = mid.getCallContext() and
+ innercc instanceof CallContextNoCall and
+ apa = mid.getAp().getApprox() and
+ config = mid.getConfiguration()
+}
+
+pragma[nomagic]
+private predicate pathOutOfCallable1(
+ PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, AccessPathApprox apa,
+ Configuration config
+) {
+ exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
+ pathOutOfCallable0(mid, pos, innercc, apa, config) and
+ c = pos.getCallable() and
+ kind = pos.getKind() and
+ resolveReturn(innercc, c, call)
+ |
+ if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
+ )
+}
+
+pragma[noinline]
+private NodeEx getAnOutNodeFlow(
+ ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config
+) {
+ result.asNode() = kind.getAnOutNode(call) and
+ Stage4::revFlow(result, _, _, apa, config)
+}
+
+/**
+ * Holds if data may flow from `mid` to `out`. The last step of this path
+ * is a return from a callable and is recorded by `cc`, if needed.
+ */
+pragma[noinline]
+private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) {
+ exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config |
+ pathOutOfCallable1(mid, call, kind, cc, apa, config) and
+ out = getAnOutNodeFlow(kind, call, apa, config)
+ )
+}
+
+/**
+ * Holds if data may flow from `mid` to the `i`th argument of `call` in `cc`.
+ */
+pragma[noinline]
+private predicate pathIntoArg(
+ PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
+ Configuration config
+) {
+ exists(ArgNode arg |
+ arg = mid.getNodeEx().asNode() and
+ cc = mid.getCallContext() and
+ arg.argumentOf(call, i) and
+ ap = mid.getAp() and
+ apa = ap.getApprox() and
+ config = mid.getConfiguration()
+ )
+}
+
+pragma[nomagic]
+private predicate parameterCand(
+ DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
+) {
+ exists(ParamNodeEx p |
+ Stage4::revFlow(p, _, _, apa, config) and
+ p.isParameterOf(callable, i)
+ )
+}
+
+pragma[nomagic]
+private predicate pathIntoCallable0(
+ PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
+ AccessPath ap, Configuration config
+) {
+ exists(AccessPathApprox apa |
+ pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
+ pragma[only_bind_into](config)) and
+ callable = resolveCall(call, outercc) and
+ parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
+ pragma[only_bind_into](config))
+ )
+}
+
+/**
+ * Holds if data may flow from `mid` to `p` through `call`. The contexts
+ * before and after entering the callable are `outercc` and `innercc`,
+ * respectively.
+ */
+pragma[nomagic]
+private predicate pathIntoCallable(
+ PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
+ DataFlowCall call, Configuration config
+) {
+ exists(int i, DataFlowCallable callable, AccessPath ap |
+ pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
+ p.isParameterOf(callable, i) and
+ (
+ sc = TSummaryCtxSome(p, ap)
+ or
+ not exists(TSummaryCtxSome(p, ap)) and
+ sc = TSummaryCtxNone() and
+ // When the call contexts of source and sink needs to match then there's
+ // never any reason to enter a callable except to find a summary. See also
+ // the comment in `PathNodeMid::isAtSink`.
+ not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
+ )
+ |
+ if recordDataFlowCallSite(call, callable)
+ then innercc = TSpecificCall(call)
+ else innercc = TSomeCall()
+ )
+}
+
+/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */
+pragma[nomagic]
+private predicate paramFlowsThrough(
+ ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
+ Configuration config
+) {
+ exists(PathNodeMid mid, RetNodeEx ret, int pos |
+ mid.getNodeEx() = ret and
+ kind = ret.getKind() and
+ cc = mid.getCallContext() and
+ sc = mid.getSummaryCtx() and
+ config = mid.getConfiguration() and
+ ap = mid.getAp() and
+ apa = ap.getApprox() and
+ pos = sc.getParameterPos() and
+ // we don't expect a parameter to return stored in itself, unless explicitly allowed
+ (
+ not kind.(ParamUpdateReturnKind).getPosition() = pos
+ or
+ sc.getParamNode().allowParameterReturnInSelf()
+ )
+ )
+}
+
+pragma[nomagic]
+private predicate pathThroughCallable0(
+ DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
+ AccessPathApprox apa, Configuration config
+) {
+ exists(CallContext innercc, SummaryCtx sc |
+ pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
+ paramFlowsThrough(kind, innercc, sc, ap, apa, config)
+ )
+}
+
+/**
+ * Holds if data may flow from `mid` through a callable to the node `out`.
+ * The context `cc` is restored to its value prior to entering the callable.
+ */
+pragma[noinline]
+private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
+ exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
+ pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
+ out = getAnOutNodeFlow(kind, call, apa, config)
+ )
+}
+
+private module Subpaths {
+ /**
+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
+ * `kind`, `sc`, `apout`, and `innercc`.
+ */
+ pragma[nomagic]
+ private predicate subpaths01(
+ PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
+ NodeEx out, AccessPath apout
+ ) {
+ exists(Configuration config |
+ pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
+ pathIntoCallable(arg, par, _, innercc, sc, _, config) and
+ paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
+ )
+ }
+
+ /**
+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
+ * `kind`, `sc`, `apout`, and `innercc`.
+ */
+ pragma[nomagic]
+ private predicate subpaths02(
+ PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
+ NodeEx out, AccessPath apout
+ ) {
+ subpaths01(arg, par, sc, innercc, kind, out, apout) and
+ out.asNode() = kind.getAnOutNode(_)
+ }
+
+ pragma[nomagic]
+ private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
+
+ /**
+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple.
+ */
+ pragma[nomagic]
+ private predicate subpaths03(
+ PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
+ ) {
+ exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
+ subpaths02(arg, par, sc, innercc, kind, out, apout) and
+ ret.getNodeEx() = retnode and
+ kind = retnode.getKind() and
+ innercc = ret.getCallContext() and
+ sc = ret.getSummaryCtx() and
+ ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
+ apout = ret.getAp() and
+ not ret.isHidden()
+ )
+ }
+
+ /**
+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
+ * a subpath between `par` and `ret` with the connecting edges `arg -> par` and
+ * `ret -> out` is summarized as the edge `arg -> out`.
+ */
+ predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
+ exists(ParamNodeEx p, NodeEx o, AccessPath apout |
+ pragma[only_bind_into](arg).getASuccessor() = par and
+ pragma[only_bind_into](arg).getASuccessor() = out and
+ subpaths03(arg, p, ret, o, apout) and
+ par.getNodeEx() = p and
+ out.getNodeEx() = o and
+ out.getAp() = apout
+ )
+ }
+
+ /**
+ * Holds if `n` can reach a return node in a summarized subpath.
+ */
+ predicate retReach(PathNode n) {
+ subpaths(_, _, n, _)
+ or
+ exists(PathNode mid |
+ retReach(mid) and
+ n.getASuccessor() = mid and
+ not subpaths(_, mid, _, _)
+ )
+ }
+}
+
+/**
+ * Holds if data can flow (inter-procedurally) from `source` to `sink`.
+ *
+ * Will only have results if `configuration` has non-empty sources and
+ * sinks.
+ */
+private predicate flowsTo(
+ PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
+) {
+ flowsource.isSource() and
+ flowsource.getConfiguration() = configuration and
+ flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
+ (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
+ flowsink.getNodeEx().asNode() = sink
+}
+
+/**
+ * Holds if data can flow (inter-procedurally) from `source` to `sink`.
+ *
+ * Will only have results if `configuration` has non-empty sources and
+ * sinks.
+ */
+predicate flowsTo(Node source, Node sink, Configuration configuration) {
+ flowsTo(_, _, source, sink, configuration)
+}
+
+private predicate finalStats(boolean fwd, int nodes, int fields, int conscand, int tuples) {
+ fwd = true and
+ nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and
+ fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
+ conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
+ tuples = count(PathNode pn)
+ or
+ fwd = false and
+ nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
+ fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
+ conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
+ tuples = count(PathNode pn | reach(pn))
+}
+
+/**
+ * INTERNAL: Only for debugging.
+ *
+ * Calculates per-stage metrics for data flow.
+ */
+predicate stageStats(
+ int n, string stage, int nodes, int fields, int conscand, int tuples, Configuration config
+) {
+ stage = "1 Fwd" and n = 10 and Stage1::stats(true, nodes, fields, conscand, tuples, config)
+ or
+ stage = "1 Rev" and n = 15 and Stage1::stats(false, nodes, fields, conscand, tuples, config)
+ or
+ stage = "2 Fwd" and n = 20 and Stage2::stats(true, nodes, fields, conscand, tuples, config)
+ or
+ stage = "2 Rev" and n = 25 and Stage2::stats(false, nodes, fields, conscand, tuples, config)
+ or
+ stage = "3 Fwd" and n = 30 and Stage3::stats(true, nodes, fields, conscand, tuples, config)
+ or
+ stage = "3 Rev" and n = 35 and Stage3::stats(false, nodes, fields, conscand, tuples, config)
+ or
+ stage = "4 Fwd" and n = 40 and Stage4::stats(true, nodes, fields, conscand, tuples, config)
+ or
+ stage = "4 Rev" and n = 45 and Stage4::stats(false, nodes, fields, conscand, tuples, config)
+ or
+ stage = "5 Fwd" and n = 50 and finalStats(true, nodes, fields, conscand, tuples)
+ or
+ stage = "5 Rev" and n = 55 and finalStats(false, nodes, fields, conscand, tuples)
+}
+
+private module FlowExploration {
+ private predicate callableStep(DataFlowCallable c1, DataFlowCallable c2, Configuration config) {
+ exists(NodeEx node1, NodeEx node2 |
+ jumpStep(node1, node2, config)
+ or
+ additionalJumpStep(node1, node2, config)
+ or
+ // flow into callable
+ viableParamArgEx(_, node2, node1)
+ or
+ // flow out of a callable
+ viableReturnPosOutEx(_, node1.(RetNodeEx).getReturnPosition(), node2)
+ |
+ c1 = node1.getEnclosingCallable() and
+ c2 = node2.getEnclosingCallable() and
+ c1 != c2
+ )
+ }
+
+ private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
+ exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
+ or
+ exists(DataFlowCallable mid |
+ interestingCallableSrc(mid, config) and callableStep(mid, c, config)
+ )
+ }
+
+ private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
+ exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
+ or
+ exists(DataFlowCallable mid |
+ interestingCallableSink(mid, config) and callableStep(c, mid, config)
+ )
+ }
+
+ private newtype TCallableExt =
+ TCallable(DataFlowCallable c, Configuration config) {
+ interestingCallableSrc(c, config) or
+ interestingCallableSink(c, config)
+ } or
+ TCallableSrc() or
+ TCallableSink()
+
+ private predicate callableExtSrc(TCallableSrc src) { any() }
+
+ private predicate callableExtSink(TCallableSink sink) { any() }
+
+ private predicate callableExtStepFwd(TCallableExt ce1, TCallableExt ce2) {
+ exists(DataFlowCallable c1, DataFlowCallable c2, Configuration config |
+ callableStep(c1, c2, config) and
+ ce1 = TCallable(c1, pragma[only_bind_into](config)) and
+ ce2 = TCallable(c2, pragma[only_bind_into](config))
+ )
+ or
+ exists(Node n, Configuration config |
+ ce1 = TCallableSrc() and
+ config.isSource(n) and
+ ce2 = TCallable(getNodeEnclosingCallable(n), config)
+ )
+ or
+ exists(Node n, Configuration config |
+ ce2 = TCallableSink() and
+ config.isSink(n) and
+ ce1 = TCallable(getNodeEnclosingCallable(n), config)
+ )
+ }
+
+ private predicate callableExtStepRev(TCallableExt ce1, TCallableExt ce2) {
+ callableExtStepFwd(ce2, ce1)
+ }
+
+ private int distSrcExt(TCallableExt c) =
+ shortestDistances(callableExtSrc/1, callableExtStepFwd/2)(_, c, result)
+
+ private int distSinkExt(TCallableExt c) =
+ shortestDistances(callableExtSink/1, callableExtStepRev/2)(_, c, result)
+
+ private int distSrc(DataFlowCallable c, Configuration config) {
+ result = distSrcExt(TCallable(c, config)) - 1
+ }
+
+ private int distSink(DataFlowCallable c, Configuration config) {
+ result = distSinkExt(TCallable(c, config)) - 1
+ }
+
+ private newtype TPartialAccessPath =
+ TPartialNil(DataFlowType t) or
+ TPartialCons(TypedContent tc, int len) { len in [1 .. accessPathLimit()] }
+
+ /**
+ * Conceptually a list of `TypedContent`s followed by a `Type`, but only the first
+ * element of the list and its length are tracked. If data flows from a source to
+ * a given node with a given `AccessPath`, this indicates the sequence of
+ * dereference operations needed to get from the value in the node to the
+ * tracked object. The final type indicates the type of the tracked object.
+ */
+ private class PartialAccessPath extends TPartialAccessPath {
+ abstract string toString();
+
+ TypedContent getHead() { this = TPartialCons(result, _) }
+
+ int len() {
+ this = TPartialNil(_) and result = 0
+ or
+ this = TPartialCons(_, result)
+ }
+
+ DataFlowType getType() {
+ this = TPartialNil(result)
+ or
+ exists(TypedContent head | this = TPartialCons(head, _) | result = head.getContainerType())
+ }
+ }
+
+ private class PartialAccessPathNil extends PartialAccessPath, TPartialNil {
+ override string toString() {
+ exists(DataFlowType t | this = TPartialNil(t) | result = concat(": " + ppReprType(t)))
+ }
+ }
+
+ private class PartialAccessPathCons extends PartialAccessPath, TPartialCons {
+ override string toString() {
+ exists(TypedContent tc, int len | this = TPartialCons(tc, len) |
+ if len = 1
+ then result = "[" + tc.toString() + "]"
+ else result = "[" + tc.toString() + ", ... (" + len.toString() + ")]"
+ )
+ }
+ }
+
+ private newtype TRevPartialAccessPath =
+ TRevPartialNil() or
+ TRevPartialCons(Content c, int len) { len in [1 .. accessPathLimit()] }
+
+ /**
+ * Conceptually a list of `Content`s, but only the first
+ * element of the list and its length are tracked.
+ */
+ private class RevPartialAccessPath extends TRevPartialAccessPath {
+ abstract string toString();
+
+ Content getHead() { this = TRevPartialCons(result, _) }
+
+ int len() {
+ this = TRevPartialNil() and result = 0
+ or
+ this = TRevPartialCons(_, result)
+ }
+ }
+
+ private class RevPartialAccessPathNil extends RevPartialAccessPath, TRevPartialNil {
+ override string toString() { result = "" }
+ }
+
+ private class RevPartialAccessPathCons extends RevPartialAccessPath, TRevPartialCons {
+ override string toString() {
+ exists(Content c, int len | this = TRevPartialCons(c, len) |
+ if len = 1
+ then result = "[" + c.toString() + "]"
+ else result = "[" + c.toString() + ", ... (" + len.toString() + ")]"
+ )
+ }
+ }
+
+ private newtype TSummaryCtx1 =
+ TSummaryCtx1None() or
+ TSummaryCtx1Param(ParamNodeEx p)
+
+ private newtype TSummaryCtx2 =
+ TSummaryCtx2None() or
+ TSummaryCtx2Some(PartialAccessPath ap)
+
+ private newtype TRevSummaryCtx1 =
+ TRevSummaryCtx1None() or
+ TRevSummaryCtx1Some(ReturnPosition pos)
+
+ private newtype TRevSummaryCtx2 =
+ TRevSummaryCtx2None() or
+ TRevSummaryCtx2Some(RevPartialAccessPath ap)
+
+ private newtype TPartialPathNode =
+ TPartialPathNodeFwd(
+ NodeEx node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, PartialAccessPath ap,
+ Configuration config
+ ) {
+ sourceNode(node, config) and
+ cc instanceof CallContextAny and
+ sc1 = TSummaryCtx1None() and
+ sc2 = TSummaryCtx2None() and
+ ap = TPartialNil(node.getDataFlowType()) and
+ not fullBarrier(node, config) and
+ exists(config.explorationLimit())
+ or
+ partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
+ distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
+ } or
+ TPartialPathNodeRev(
+ NodeEx node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
+ Configuration config
+ ) {
+ sinkNode(node, config) and
+ sc1 = TRevSummaryCtx1None() and
+ sc2 = TRevSummaryCtx2None() and
+ ap = TRevPartialNil() and
+ not fullBarrier(node, config) and
+ exists(config.explorationLimit())
+ or
+ exists(PartialPathNodeRev mid |
+ revPartialPathStep(mid, node, sc1, sc2, ap, config) and
+ not clearsContentCached(node.asNode(), ap.getHead()) and
+ not fullBarrier(node, config) and
+ distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate partialPathNodeMk0(
+ NodeEx node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, PartialAccessPath ap,
+ Configuration config
+ ) {
+ exists(PartialPathNodeFwd mid |
+ partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
+ not fullBarrier(node, config) and
+ not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
+ if node.asNode() instanceof CastingNode
+ then compatibleTypes(node.getDataFlowType(), ap.getType())
+ else any()
+ )
+ }
+
+ /**
+ * A `Node` augmented with a call context, an access path, and a configuration.
+ */
+ class PartialPathNode extends TPartialPathNode {
+ /** Gets a textual representation of this element. */
+ string toString() { result = this.getNodeEx().toString() + this.ppAp() }
+
+ /**
+ * Gets a textual representation of this element, including a textual
+ * representation of the call context.
+ */
+ string toStringWithContext() {
+ result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
+ }
+
+ /**
+ * Holds if this element is at the specified location.
+ * The location spans column `startcolumn` of line `startline` to
+ * column `endcolumn` of line `endline` in file `filepath`.
+ * For more information, see
+ * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
+ */
+ predicate hasLocationInfo(
+ string filepath, int startline, int startcolumn, int endline, int endcolumn
+ ) {
+ this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
+ }
+
+ /** Gets the underlying `Node`. */
+ final Node getNode() { this.getNodeEx().projectToNode() = result }
+
+ private NodeEx getNodeEx() {
+ result = this.(PartialPathNodeFwd).getNodeEx() or
+ result = this.(PartialPathNodeRev).getNodeEx()
+ }
+
+ /** Gets the associated configuration. */
+ Configuration getConfiguration() { none() }
+
+ /** Gets a successor of this node, if any. */
+ PartialPathNode getASuccessor() { none() }
+
+ /**
+ * Gets the approximate distance to the nearest source measured in number
+ * of interprocedural steps.
+ */
+ int getSourceDistance() {
+ result = distSrc(this.getNodeEx().getEnclosingCallable(), this.getConfiguration())
+ }
+
+ /**
+ * Gets the approximate distance to the nearest sink measured in number
+ * of interprocedural steps.
+ */
+ int getSinkDistance() {
+ result = distSink(this.getNodeEx().getEnclosingCallable(), this.getConfiguration())
+ }
+
+ private string ppAp() {
+ exists(string s |
+ s = this.(PartialPathNodeFwd).getAp().toString() or
+ s = this.(PartialPathNodeRev).getAp().toString()
+ |
+ if s = "" then result = "" else result = " " + s
+ )
+ }
+
+ private string ppCtx() {
+ result = " <" + this.(PartialPathNodeFwd).getCallContext().toString() + ">"
+ }
+
+ /** Holds if this is a source in a forward-flow path. */
+ predicate isFwdSource() { this.(PartialPathNodeFwd).isSource() }
+
+ /** Holds if this is a sink in a reverse-flow path. */
+ predicate isRevSink() { this.(PartialPathNodeRev).isSink() }
+ }
+
+ /**
+ * Provides the query predicates needed to include a graph in a path-problem query.
+ */
+ module PartialPathGraph {
+ /** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
+ query predicate edges(PartialPathNode a, PartialPathNode b) { a.getASuccessor() = b }
+ }
+
+ private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd {
+ NodeEx node;
+ CallContext cc;
+ TSummaryCtx1 sc1;
+ TSummaryCtx2 sc2;
+ PartialAccessPath ap;
+ Configuration config;
+
+ PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, cc, sc1, sc2, ap, config) }
+
+ NodeEx getNodeEx() { result = node }
+
+ CallContext getCallContext() { result = cc }
+
+ TSummaryCtx1 getSummaryCtx1() { result = sc1 }
+
+ TSummaryCtx2 getSummaryCtx2() { result = sc2 }
+
+ PartialAccessPath getAp() { result = ap }
+
+ override Configuration getConfiguration() { result = config }
+
+ override PartialPathNodeFwd getASuccessor() {
+ partialPathStep(this, result.getNodeEx(), result.getCallContext(), result.getSummaryCtx1(),
+ result.getSummaryCtx2(), result.getAp(), result.getConfiguration())
+ }
+
+ predicate isSource() {
+ sourceNode(node, config) and
+ cc instanceof CallContextAny and
+ sc1 = TSummaryCtx1None() and
+ sc2 = TSummaryCtx2None() and
+ ap instanceof TPartialNil
+ }
+ }
+
+ private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev {
+ NodeEx node;
+ TRevSummaryCtx1 sc1;
+ TRevSummaryCtx2 sc2;
+ RevPartialAccessPath ap;
+ Configuration config;
+
+ PartialPathNodeRev() { this = TPartialPathNodeRev(node, sc1, sc2, ap, config) }
+
+ NodeEx getNodeEx() { result = node }
+
+ TRevSummaryCtx1 getSummaryCtx1() { result = sc1 }
+
+ TRevSummaryCtx2 getSummaryCtx2() { result = sc2 }
+
+ RevPartialAccessPath getAp() { result = ap }
+
+ override Configuration getConfiguration() { result = config }
+
+ override PartialPathNodeRev getASuccessor() {
+ revPartialPathStep(result, this.getNodeEx(), this.getSummaryCtx1(), this.getSummaryCtx2(),
+ this.getAp(), this.getConfiguration())
+ }
+
+ predicate isSink() {
+ sinkNode(node, config) and
+ sc1 = TRevSummaryCtx1None() and
+ sc2 = TRevSummaryCtx2None() and
+ ap = TRevPartialNil()
+ }
+ }
+
+ private predicate partialPathStep(
+ PartialPathNodeFwd mid, NodeEx node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
+ PartialAccessPath ap, Configuration config
+ ) {
+ not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and
+ (
+ localFlowStep(mid.getNodeEx(), node, config) and
+ cc = mid.getCallContext() and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ or
+ additionalLocalFlowStep(mid.getNodeEx(), node, config) and
+ cc = mid.getCallContext() and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ mid.getAp() instanceof PartialAccessPathNil and
+ ap = TPartialNil(node.getDataFlowType()) and
+ config = mid.getConfiguration()
+ )
+ or
+ jumpStep(mid.getNodeEx(), node, config) and
+ cc instanceof CallContextAny and
+ sc1 = TSummaryCtx1None() and
+ sc2 = TSummaryCtx2None() and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ or
+ additionalJumpStep(mid.getNodeEx(), node, config) and
+ cc instanceof CallContextAny and
+ sc1 = TSummaryCtx1None() and
+ sc2 = TSummaryCtx2None() and
+ mid.getAp() instanceof PartialAccessPathNil and
+ ap = TPartialNil(node.getDataFlowType()) and
+ config = mid.getConfiguration()
+ or
+ partialPathStoreStep(mid, _, _, node, ap) and
+ cc = mid.getCallContext() and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ config = mid.getConfiguration()
+ or
+ exists(PartialAccessPath ap0, TypedContent tc |
+ partialPathReadStep(mid, ap0, tc, node, cc, config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ apConsFwd(ap, tc, ap0, config)
+ )
+ or
+ partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
+ or
+ partialPathOutOfCallable(mid, node, cc, ap, config) and
+ sc1 = TSummaryCtx1None() and
+ sc2 = TSummaryCtx2None()
+ or
+ partialPathThroughCallable(mid, node, cc, ap, config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2()
+ }
+
+ bindingset[result, i]
+ private int unbindInt(int i) { i <= result and i >= result }
+
+ pragma[inline]
+ private predicate partialPathStoreStep(
+ PartialPathNodeFwd mid, PartialAccessPath ap1, TypedContent tc, NodeEx node,
+ PartialAccessPath ap2
+ ) {
+ exists(NodeEx midNode, DataFlowType contentType |
+ midNode = mid.getNodeEx() and
+ ap1 = mid.getAp() and
+ store(midNode, tc, node, contentType, mid.getConfiguration()) and
+ ap2.getHead() = tc and
+ ap2.len() = unbindInt(ap1.len() + 1) and
+ compatibleTypes(ap1.getType(), contentType)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate apConsFwd(
+ PartialAccessPath ap1, TypedContent tc, PartialAccessPath ap2, Configuration config
+ ) {
+ exists(PartialPathNodeFwd mid |
+ partialPathStoreStep(mid, ap1, tc, _, ap2) and
+ config = mid.getConfiguration()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate partialPathReadStep(
+ PartialPathNodeFwd mid, PartialAccessPath ap, TypedContent tc, NodeEx node, CallContext cc,
+ Configuration config
+ ) {
+ exists(NodeEx midNode |
+ midNode = mid.getNodeEx() and
+ ap = mid.getAp() and
+ read(midNode, tc.getContent(), node, pragma[only_bind_into](config)) and
+ ap.getHead() = tc and
+ pragma[only_bind_into](config) = mid.getConfiguration() and
+ cc = mid.getCallContext()
+ )
+ }
+
+ private predicate partialPathOutOfCallable0(
+ PartialPathNodeFwd mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
+ Configuration config
+ ) {
+ pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and
+ innercc = mid.getCallContext() and
+ innercc instanceof CallContextNoCall and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ }
+
+ pragma[nomagic]
+ private predicate partialPathOutOfCallable1(
+ PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, CallContext cc,
+ PartialAccessPath ap, Configuration config
+ ) {
+ exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
+ partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
+ c = pos.getCallable() and
+ kind = pos.getKind() and
+ resolveReturn(innercc, c, call)
+ |
+ if reducedViableImplInReturn(c, call) then cc = TReturn(c, call) else cc = TAnyCallContext()
+ )
+ }
+
+ private predicate partialPathOutOfCallable(
+ PartialPathNodeFwd mid, NodeEx out, CallContext cc, PartialAccessPath ap, Configuration config
+ ) {
+ exists(ReturnKindExt kind, DataFlowCall call |
+ partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
+ |
+ out.asNode() = kind.getAnOutNode(call)
+ )
+ }
+
+ pragma[noinline]
+ private predicate partialPathIntoArg(
+ PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
+ Configuration config
+ ) {
+ exists(ArgNode arg |
+ arg = mid.getNodeEx().asNode() and
+ cc = mid.getCallContext() and
+ arg.argumentOf(call, i) and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate partialPathIntoCallable0(
+ PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
+ DataFlowCall call, PartialAccessPath ap, Configuration config
+ ) {
+ partialPathIntoArg(mid, i, outercc, call, ap, config) and
+ callable = resolveCall(call, outercc)
+ }
+
+ private predicate partialPathIntoCallable(
+ PartialPathNodeFwd mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc,
+ TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
+ Configuration config
+ ) {
+ exists(int i, DataFlowCallable callable |
+ partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
+ p.isParameterOf(callable, i) and
+ sc1 = TSummaryCtx1Param(p) and
+ sc2 = TSummaryCtx2Some(ap)
+ |
+ if recordDataFlowCallSite(call, callable)
+ then innercc = TSpecificCall(call)
+ else innercc = TSomeCall()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate paramFlowsThroughInPartialPath(
+ ReturnKindExt kind, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
+ PartialAccessPath ap, Configuration config
+ ) {
+ exists(PartialPathNodeFwd mid, RetNodeEx ret |
+ mid.getNodeEx() = ret and
+ kind = ret.getKind() and
+ cc = mid.getCallContext() and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ config = mid.getConfiguration() and
+ ap = mid.getAp()
+ )
+ }
+
+ pragma[noinline]
+ private predicate partialPathThroughCallable0(
+ DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
+ PartialAccessPath ap, Configuration config
+ ) {
+ exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
+ partialPathIntoCallable(mid, _, cc, innercc, sc1, sc2, call, _, config) and
+ paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
+ )
+ }
+
+ private predicate partialPathThroughCallable(
+ PartialPathNodeFwd mid, NodeEx out, CallContext cc, PartialAccessPath ap, Configuration config
+ ) {
+ exists(DataFlowCall call, ReturnKindExt kind |
+ partialPathThroughCallable0(call, mid, kind, cc, ap, config) and
+ out.asNode() = kind.getAnOutNode(call)
+ )
+ }
+
+ private predicate revPartialPathStep(
+ PartialPathNodeRev mid, NodeEx node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
+ RevPartialAccessPath ap, Configuration config
+ ) {
+ localFlowStep(node, mid.getNodeEx(), config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ or
+ additionalLocalFlowStep(node, mid.getNodeEx(), config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ mid.getAp() instanceof RevPartialAccessPathNil and
+ ap = TRevPartialNil() and
+ config = mid.getConfiguration()
+ or
+ jumpStep(node, mid.getNodeEx(), config) and
+ sc1 = TRevSummaryCtx1None() and
+ sc2 = TRevSummaryCtx2None() and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ or
+ additionalJumpStep(node, mid.getNodeEx(), config) and
+ sc1 = TRevSummaryCtx1None() and
+ sc2 = TRevSummaryCtx2None() and
+ mid.getAp() instanceof RevPartialAccessPathNil and
+ ap = TRevPartialNil() and
+ config = mid.getConfiguration()
+ or
+ revPartialPathReadStep(mid, _, _, node, ap) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ config = mid.getConfiguration()
+ or
+ exists(RevPartialAccessPath ap0, Content c |
+ revPartialPathStoreStep(mid, ap0, c, node, config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ apConsRev(ap, c, ap0, config)
+ )
+ or
+ exists(ParamNodeEx p |
+ mid.getNodeEx() = p and
+ viableParamArgEx(_, p, node) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ sc1 = TRevSummaryCtx1None() and
+ sc2 = TRevSummaryCtx2None() and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ )
+ or
+ exists(ReturnPosition pos |
+ revPartialPathIntoReturn(mid, pos, sc1, sc2, _, ap, config) and
+ pos = getReturnPosition(node.asNode())
+ )
+ or
+ revPartialPathThroughCallable(mid, node, ap, config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2()
+ }
+
+ pragma[inline]
+ private predicate revPartialPathReadStep(
+ PartialPathNodeRev mid, RevPartialAccessPath ap1, Content c, NodeEx node,
+ RevPartialAccessPath ap2
+ ) {
+ exists(NodeEx midNode |
+ midNode = mid.getNodeEx() and
+ ap1 = mid.getAp() and
+ read(node, c, midNode, mid.getConfiguration()) and
+ ap2.getHead() = c and
+ ap2.len() = unbindInt(ap1.len() + 1)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate apConsRev(
+ RevPartialAccessPath ap1, Content c, RevPartialAccessPath ap2, Configuration config
+ ) {
+ exists(PartialPathNodeRev mid |
+ revPartialPathReadStep(mid, ap1, c, _, ap2) and
+ config = mid.getConfiguration()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revPartialPathStoreStep(
+ PartialPathNodeRev mid, RevPartialAccessPath ap, Content c, NodeEx node, Configuration config
+ ) {
+ exists(NodeEx midNode, TypedContent tc |
+ midNode = mid.getNodeEx() and
+ ap = mid.getAp() and
+ store(node, tc, midNode, _, config) and
+ ap.getHead() = c and
+ config = mid.getConfiguration() and
+ tc.getContent() = c
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revPartialPathIntoReturn(
+ PartialPathNodeRev mid, ReturnPosition pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
+ DataFlowCall call, RevPartialAccessPath ap, Configuration config
+ ) {
+ exists(NodeEx out |
+ mid.getNodeEx() = out and
+ viableReturnPosOutEx(call, pos, out) and
+ sc1 = TRevSummaryCtx1Some(pos) and
+ sc2 = TRevSummaryCtx2Some(ap) and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revPartialPathFlowsThrough(
+ int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
+ Configuration config
+ ) {
+ exists(PartialPathNodeRev mid, ParamNodeEx p |
+ mid.getNodeEx() = p and
+ p.getPosition() = pos and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ ap = mid.getAp() and
+ config = mid.getConfiguration()
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revPartialPathThroughCallable0(
+ DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
+ Configuration config
+ ) {
+ exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
+ revPartialPathIntoReturn(mid, _, sc1, sc2, call, _, config) and
+ revPartialPathFlowsThrough(pos, sc1, sc2, ap, config)
+ )
+ }
+
+ pragma[nomagic]
+ private predicate revPartialPathThroughCallable(
+ PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
+ ) {
+ exists(DataFlowCall call, int pos |
+ revPartialPathThroughCallable0(call, mid, pos, ap, config) and
+ node.asNode().(ArgNode).argumentOf(call, pos)
+ )
+ }
+}
+
+import FlowExploration
+
+private predicate partialFlow(
+ PartialPathNode source, PartialPathNode node, Configuration configuration
+) {
+ source.getConfiguration() = configuration and
+ source.isFwdSource() and
+ node = source.getASuccessor+()
+}
+
+private predicate revPartialFlow(
+ PartialPathNode node, PartialPathNode sink, Configuration configuration
+) {
+ sink.getConfiguration() = configuration and
+ sink.isRevSink() and
+ node.getASuccessor+() = sink
+}
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
index 65f971d64ec..62fea86acf1 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -2,7 +2,7 @@
import java
private import semmle.code.java.dataflow.DataFlow
-private import semmle.code.java.dataflow.DataFlow5
+private import semmle.code.java.dataflow.internal.DataFlowForOnActivityResult
private import semmle.code.java.frameworks.android.Android
private import semmle.code.java.frameworks.android.Fragment
private import semmle.code.java.frameworks.android.Intent
@@ -59,7 +59,7 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
/**
* A data flow configuration for implicit intents being used in `startActivityForResult`.
*/
-private class ImplicitStartActivityForResultConf extends DataFlow5::Configuration {
+private class ImplicitStartActivityForResultConf extends DataFlowForOnActivityResult::Configuration {
ImplicitStartActivityForResultConf() { this = "ImplicitStartActivityForResultConf" }
override predicate isSource(DataFlow::Node source) {
From 37916a8368cf36753d2c6e6cac87e0eb60e94683 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 17 Jan 2022 16:41:55 +0100
Subject: [PATCH 089/196] Fix previous merge
---
java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
index c003c908900..99e875c20c1 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/Fragment.qll
@@ -1,4 +1,4 @@
-/** Provides classes and predicates related to Android Fragments. */
+/** Provides classes and predicates to track Android fragments. */
import java
From ea4ff80cc68961f47e0a2c96635758b8143233ef Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 17 Jan 2022 17:05:10 +0100
Subject: [PATCH 090/196] Add DataFlowImplForOnActivityResult to
identical-files.json
---
config/identical-files.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/config/identical-files.json b/config/identical-files.json
index fb6c1d645ba..34f25f3baa7 100644
--- a/config/identical-files.json
+++ b/config/identical-files.json
@@ -7,6 +7,7 @@
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll",
"java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll",
+ "java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll",
From 57ff13dd193ac00542e22e6d438b6031dd06288d Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Mon, 17 Jan 2022 17:12:33 +0100
Subject: [PATCH 091/196] Sync DataFlowImplForOnActivityResult to latest
changes
---
.../DataFlowImplForOnActivityResult.qll | 1951 +++++++++++------
1 file changed, 1235 insertions(+), 716 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
index 4daf617a404..a265b4cbd27 100644
--- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
@@ -54,12 +54,23 @@ abstract class Configuration extends string {
/**
* Holds if `source` is a relevant data flow source.
*/
- abstract predicate isSource(Node source);
+ predicate isSource(Node source) { none() }
+
+ /**
+ * Holds if `source` is a relevant data flow source with the given initial
+ * `state`.
+ */
+ predicate isSource(Node source, FlowState state) { none() }
/**
* Holds if `sink` is a relevant data flow sink.
*/
- abstract predicate isSink(Node sink);
+ predicate isSink(Node sink) { none() }
+
+ /**
+ * Holds if `sink` is a relevant data flow sink accepting `state`.
+ */
+ predicate isSink(Node source, FlowState state) { none() }
/**
* Holds if data flow through `node` is prohibited. This completely removes
@@ -67,6 +78,12 @@ abstract class Configuration extends string {
*/
predicate isBarrier(Node node) { none() }
+ /**
+ * Holds if data flow through `node` is prohibited when the flow state is
+ * `state`.
+ */
+ predicate isBarrier(Node node, FlowState state) { none() }
+
/** Holds if data flow into `node` is prohibited. */
predicate isBarrierIn(Node node) { none() }
@@ -82,6 +99,15 @@ abstract class Configuration extends string {
*/
predicate isAdditionalFlowStep(Node node1, Node node2) { none() }
+ /**
+ * Holds if the additional flow step from `node1` to `node2` must be taken
+ * into account in the analysis. This step is only applicable in `state1` and
+ * updates the flow state to `state2`.
+ */
+ predicate isAdditionalFlowStep(Node node1, FlowState state1, Node node2, FlowState state2) {
+ none()
+ }
+
/**
* Holds if an arbitrary number of implicit read steps of content `c` may be
* taken at `node`.
@@ -197,10 +223,16 @@ abstract private class ConfigurationRecursionPrevention extends Configuration {
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0
or
+ strictcount(Node n | this.isSource(n, _)) < 0
+ or
strictcount(Node n | this.isSink(n)) < 0
or
+ strictcount(Node n | this.isSink(n, _)) < 0
+ or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0
or
+ strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, _, n2, _)) < 0
+ or
super.hasFlow(source, sink)
}
}
@@ -256,11 +288,11 @@ private class ArgNodeEx extends NodeEx {
private class ParamNodeEx extends NodeEx {
ParamNodeEx() { this.asNode() instanceof ParamNode }
- predicate isParameterOf(DataFlowCallable c, int i) {
- this.asNode().(ParamNode).isParameterOf(c, i)
+ predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
+ this.asNode().(ParamNode).isParameterOf(c, pos)
}
- int getPosition() { this.isParameterOf(_, result) }
+ ParameterPosition getPosition() { this.isParameterOf(_, result) }
predicate allowParameterReturnInSelf() { allowParameterReturnInSelfCached(this.asNode()) }
}
@@ -276,28 +308,33 @@ private class RetNodeEx extends NodeEx {
private predicate inBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
- config.isBarrierIn(n) and
- config.isSource(n)
+ config.isBarrierIn(n)
+ |
+ config.isSource(n) or config.isSource(n, _)
)
}
private predicate outBarrier(NodeEx node, Configuration config) {
exists(Node n |
node.asNode() = n and
- config.isBarrierOut(n) and
- config.isSink(n)
+ config.isBarrierOut(n)
+ |
+ config.isSink(n) or config.isSink(n, _)
)
}
+pragma[nomagic]
private predicate fullBarrier(NodeEx node, Configuration config) {
exists(Node n | node.asNode() = n |
config.isBarrier(n)
or
config.isBarrierIn(n) and
- not config.isSource(n)
+ not config.isSource(n) and
+ not config.isSource(n, _)
or
config.isBarrierOut(n) and
- not config.isSink(n)
+ not config.isSink(n) and
+ not config.isSink(n, _)
or
exists(BarrierGuard g |
config.isBarrierGuard(g) and
@@ -307,10 +344,43 @@ private predicate fullBarrier(NodeEx node, Configuration config) {
}
pragma[nomagic]
-private predicate sourceNode(NodeEx node, Configuration config) { config.isSource(node.asNode()) }
+private predicate stateBarrier(NodeEx node, FlowState state, Configuration config) {
+ exists(Node n |
+ node.asNode() = n and
+ config.isBarrier(n, state)
+ )
+}
pragma[nomagic]
-private predicate sinkNode(NodeEx node, Configuration config) { config.isSink(node.asNode()) }
+private predicate sourceNode(NodeEx node, FlowState state, Configuration config) {
+ (
+ config.isSource(node.asNode()) and state instanceof FlowStateEmpty
+ or
+ config.isSource(node.asNode(), state)
+ ) and
+ not fullBarrier(node, config) and
+ not stateBarrier(node, state, config)
+}
+
+pragma[nomagic]
+private predicate sinkNode(NodeEx node, FlowState state, Configuration config) {
+ (
+ config.isSink(node.asNode()) and state instanceof FlowStateEmpty
+ or
+ config.isSink(node.asNode(), state)
+ ) and
+ not fullBarrier(node, config) and
+ not stateBarrier(node, state, config)
+}
+
+/** Provides the relevant barriers for a step from `node1` to `node2`. */
+pragma[inline]
+private predicate stepFilter(NodeEx node1, NodeEx node2, Configuration config) {
+ not outBarrier(node1, config) and
+ not inBarrier(node2, config) and
+ not fullBarrier(node1, config) and
+ not fullBarrier(node2, config)
+}
/**
* Holds if data can flow in one local step from `node1` to `node2`.
@@ -320,16 +390,14 @@ private predicate localFlowStep(NodeEx node1, NodeEx node2, Configuration config
node1.asNode() = n1 and
node2.asNode() = n2 and
simpleLocalFlowStepExt(n1, n2) and
- not outBarrier(node1, config) and
- not inBarrier(node2, config) and
- not fullBarrier(node1, config) and
- not fullBarrier(node2, config)
+ stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.asNode() = n and
- node2.isImplicitReadNode(n, false)
+ node2.isImplicitReadNode(n, false) and
+ not fullBarrier(node1, config)
)
}
@@ -342,16 +410,28 @@ private predicate additionalLocalFlowStep(NodeEx node1, NodeEx node2, Configurat
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
- not outBarrier(node1, config) and
- not inBarrier(node2, config) and
- not fullBarrier(node1, config) and
- not fullBarrier(node2, config)
+ stepFilter(node1, node2, config)
)
or
exists(Node n |
config.allowImplicitRead(n, _) and
node1.isImplicitReadNode(n, true) and
- node2.asNode() = n
+ node2.asNode() = n and
+ not fullBarrier(node2, config)
+ )
+}
+
+private predicate additionalLocalStateStep(
+ NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config
+) {
+ exists(Node n1, Node n2 |
+ node1.asNode() = n1 and
+ node2.asNode() = n2 and
+ config.isAdditionalFlowStep(n1, s1, n2, s2) and
+ getNodeEnclosingCallable(n1) = getNodeEnclosingCallable(n2) and
+ stepFilter(node1, node2, config) and
+ not stateBarrier(node1, s1, config) and
+ not stateBarrier(node2, s2, config)
)
}
@@ -363,10 +443,7 @@ private predicate jumpStep(NodeEx node1, NodeEx node2, Configuration config) {
node1.asNode() = n1 and
node2.asNode() = n2 and
jumpStepCached(n1, n2) and
- not outBarrier(node1, config) and
- not inBarrier(node2, config) and
- not fullBarrier(node1, config) and
- not fullBarrier(node2, config) and
+ stepFilter(node1, node2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
@@ -380,16 +457,29 @@ private predicate additionalJumpStep(NodeEx node1, NodeEx node2, Configuration c
node2.asNode() = n2 and
config.isAdditionalFlowStep(n1, n2) and
getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
- not outBarrier(node1, config) and
- not inBarrier(node2, config) and
- not fullBarrier(node1, config) and
- not fullBarrier(node2, config) and
+ stepFilter(node1, node2, config) and
+ not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
+ )
+}
+
+private predicate additionalJumpStateStep(
+ NodeEx node1, FlowState s1, NodeEx node2, FlowState s2, Configuration config
+) {
+ exists(Node n1, Node n2 |
+ node1.asNode() = n1 and
+ node2.asNode() = n2 and
+ config.isAdditionalFlowStep(n1, s1, n2, s2) and
+ getNodeEnclosingCallable(n1) != getNodeEnclosingCallable(n2) and
+ stepFilter(node1, node2, config) and
+ not stateBarrier(node1, s1, config) and
+ not stateBarrier(node2, s2, config) and
not config.getAFeature() instanceof FeatureEqualSourceSinkCallContext
)
}
private predicate read(NodeEx node1, Content c, NodeEx node2, Configuration config) {
- read(node1.asNode(), c, node2.asNode())
+ read(node1.asNode(), c, node2.asNode()) and
+ stepFilter(node1, node2, config)
or
exists(Node n |
node2.isImplicitReadNode(n, true) and
@@ -402,7 +492,8 @@ private predicate store(
NodeEx node1, TypedContent tc, NodeEx node2, DataFlowType contentType, Configuration config
) {
store(node1.asNode(), tc, node2.asNode(), contentType) and
- read(_, tc.getContent(), _, config)
+ read(_, tc.getContent(), _, config) and
+ stepFilter(node1, node2, config)
}
pragma[nomagic]
@@ -451,63 +542,49 @@ private module Stage1 {
* argument in a call.
*/
predicate fwdFlow(NodeEx node, Cc cc, Configuration config) {
- not fullBarrier(node, config) and
- (
- sourceNode(node, config) and
- if hasSourceCallCtx(config) then cc = true else cc = false
+ sourceNode(node, _, config) and
+ if hasSourceCallCtx(config) then cc = true else cc = false
+ or
+ exists(NodeEx mid | fwdFlow(mid, cc, config) |
+ localFlowStep(mid, node, config) or
+ additionalLocalFlowStep(mid, node, config) or
+ additionalLocalStateStep(mid, _, node, _, config)
+ )
+ or
+ exists(NodeEx mid | fwdFlow(mid, _, config) and cc = false |
+ jumpStep(mid, node, config) or
+ additionalJumpStep(mid, node, config) or
+ additionalJumpStateStep(mid, _, node, _, config)
+ )
+ or
+ // store
+ exists(NodeEx mid |
+ useFieldFlow(config) and
+ fwdFlow(mid, cc, config) and
+ store(mid, _, node, _, config)
+ )
+ or
+ // read
+ exists(Content c |
+ fwdFlowRead(c, node, cc, config) and
+ fwdFlowConsCand(c, config)
+ )
+ or
+ // flow into a callable
+ exists(NodeEx arg |
+ fwdFlow(arg, _, config) and
+ viableParamArgEx(_, node, arg) and
+ cc = true and
+ not fullBarrier(node, config)
+ )
+ or
+ // flow out of a callable
+ exists(DataFlowCall call |
+ fwdFlowOut(call, node, false, config) and
+ cc = false
or
- exists(NodeEx mid |
- fwdFlow(mid, cc, config) and
- localFlowStep(mid, node, config)
- )
- or
- exists(NodeEx mid |
- fwdFlow(mid, cc, config) and
- additionalLocalFlowStep(mid, node, config)
- )
- or
- exists(NodeEx mid |
- fwdFlow(mid, _, config) and
- jumpStep(mid, node, config) and
- cc = false
- )
- or
- exists(NodeEx mid |
- fwdFlow(mid, _, config) and
- additionalJumpStep(mid, node, config) and
- cc = false
- )
- or
- // store
- exists(NodeEx mid |
- useFieldFlow(config) and
- fwdFlow(mid, cc, config) and
- store(mid, _, node, _, config) and
- not outBarrier(mid, config)
- )
- or
- // read
- exists(Content c |
- fwdFlowRead(c, node, cc, config) and
- fwdFlowConsCand(c, config) and
- not inBarrier(node, config)
- )
- or
- // flow into a callable
- exists(NodeEx arg |
- fwdFlow(arg, _, config) and
- viableParamArgEx(_, node, arg) and
- cc = true
- )
- or
- // flow out of a callable
- exists(DataFlowCall call |
- fwdFlowOut(call, node, false, config) and
- cc = false
- or
- fwdFlowOutFromArg(call, node, config) and
- fwdFlowIsEntered(call, cc, config)
- )
+ fwdFlowOutFromArg(call, node, config) and
+ fwdFlowIsEntered(call, cc, config)
)
}
@@ -547,7 +624,8 @@ private module Stage1 {
private predicate fwdFlowOut(DataFlowCall call, NodeEx out, Cc cc, Configuration config) {
exists(ReturnPosition pos |
fwdFlowReturnPosition(pos, cc, config) and
- viableReturnPosOutEx(call, pos, out)
+ viableReturnPosOutEx(call, pos, out) and
+ not fullBarrier(out, config)
)
}
@@ -567,6 +645,24 @@ private module Stage1 {
)
}
+ private predicate stateStepFwd(FlowState state1, FlowState state2, Configuration config) {
+ exists(NodeEx node1 |
+ additionalLocalStateStep(node1, state1, _, state2, config) or
+ additionalJumpStateStep(node1, state1, _, state2, config)
+ |
+ fwdFlow(node1, config)
+ )
+ }
+
+ private predicate fwdFlowState(FlowState state, Configuration config) {
+ sourceNode(_, state, config)
+ or
+ exists(FlowState state0 |
+ fwdFlowState(state0, config) and
+ stateStepFwd(state0, state, config)
+ )
+ }
+
/**
* Holds if `node` is part of a path from a source to a sink in the
* configuration `config`.
@@ -582,30 +678,23 @@ private module Stage1 {
pragma[nomagic]
private predicate revFlow0(NodeEx node, boolean toReturn, Configuration config) {
- fwdFlow(node, config) and
- sinkNode(node, config) and
- if hasSinkCallCtx(config) then toReturn = true else toReturn = false
- or
- exists(NodeEx mid |
- localFlowStep(node, mid, config) and
- revFlow(mid, toReturn, config)
+ exists(FlowState state |
+ fwdFlow(node, pragma[only_bind_into](config)) and
+ sinkNode(node, state, config) and
+ fwdFlowState(state, pragma[only_bind_into](config)) and
+ if hasSinkCallCtx(config) then toReturn = true else toReturn = false
)
or
- exists(NodeEx mid |
- additionalLocalFlowStep(node, mid, config) and
- revFlow(mid, toReturn, config)
+ exists(NodeEx mid | revFlow(mid, toReturn, config) |
+ localFlowStep(node, mid, config) or
+ additionalLocalFlowStep(node, mid, config) or
+ additionalLocalStateStep(node, _, mid, _, config)
)
or
- exists(NodeEx mid |
- jumpStep(node, mid, config) and
- revFlow(mid, _, config) and
- toReturn = false
- )
- or
- exists(NodeEx mid |
- additionalJumpStep(node, mid, config) and
- revFlow(mid, _, config) and
- toReturn = false
+ exists(NodeEx mid | revFlow(mid, _, config) and toReturn = false |
+ jumpStep(node, mid, config) or
+ additionalJumpStep(node, mid, config) or
+ additionalJumpStateStep(node, _, mid, _, config)
)
or
// store
@@ -722,6 +811,31 @@ private module Stage1 {
)
}
+ private predicate stateStepRev(FlowState state1, FlowState state2, Configuration config) {
+ exists(NodeEx node1, NodeEx node2 |
+ additionalLocalStateStep(node1, state1, node2, state2, config) or
+ additionalJumpStateStep(node1, state1, node2, state2, config)
+ |
+ revFlow(node1, _, pragma[only_bind_into](config)) and
+ revFlow(node2, _, pragma[only_bind_into](config)) and
+ fwdFlowState(state1, pragma[only_bind_into](config)) and
+ fwdFlowState(state2, pragma[only_bind_into](config))
+ )
+ }
+
+ predicate revFlowState(FlowState state, Configuration config) {
+ exists(NodeEx node |
+ sinkNode(node, state, config) and
+ revFlow(node, _, pragma[only_bind_into](config)) and
+ fwdFlowState(state, pragma[only_bind_into](config))
+ )
+ or
+ exists(FlowState state0 |
+ revFlowState(state0, config) and
+ stateStepRev(state, state0, config)
+ )
+ }
+
pragma[nomagic]
predicate storeStepCand(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, DataFlowType contentType,
@@ -746,8 +860,11 @@ private module Stage1 {
pragma[nomagic]
predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, config) }
- predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
- revFlow(node, toReturn, config) and exists(returnAp) and exists(ap)
+ bindingset[node, state, config]
+ predicate revFlow(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow(node, toReturn, config) and exists(state) and exists(returnAp) and exists(ap)
}
private predicate throughFlowNodeCand(NodeEx node, Configuration config) {
@@ -773,6 +890,7 @@ private module Stage1 {
* Holds if flow may enter through `p` and reach a return node making `p` a
* candidate for the origin of a summary.
*/
+ pragma[nomagic]
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
exists(ReturnKindExt kind |
throughFlowNodeCand(p, config) and
@@ -797,17 +915,21 @@ private module Stage1 {
)
}
- predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ predicate stats(
+ boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
+ ) {
fwd = true and
nodes = count(NodeEx node | fwdFlow(node, config)) and
fields = count(Content f0 | fwdFlowConsCand(f0, config)) and
conscand = -1 and
+ states = count(FlowState state | fwdFlowState(state, config)) and
tuples = count(NodeEx n, boolean b | fwdFlow(n, b, config))
or
fwd = false and
nodes = count(NodeEx node | revFlow(node, _, config)) and
fields = count(Content f0 | revFlowConsCand(f0, config)) and
conscand = -1 and
+ states = count(FlowState state | revFlowState(state, config)) and
tuples = count(NodeEx n, boolean b | revFlow(n, b, config))
}
/* End: Stage 1 logic. */
@@ -991,15 +1113,23 @@ private module Stage2 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
+ bindingset[node1, state1, config]
+ bindingset[node2, state2, config]
private predicate localStep(
- NodeEx node1, NodeEx node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc
+ NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
+ ApNil ap, Configuration config, LocalCc lcc
) {
(
preservesValue = true and
- localFlowStepNodeCand1(node1, node2, config)
+ localFlowStepNodeCand1(node1, node2, config) and
+ state1 = state2
or
preservesValue = false and
- additionalLocalFlowStepNodeCand1(node1, node2, config)
+ additionalLocalFlowStepNodeCand1(node1, node2, config) and
+ state1 = state2
+ or
+ preservesValue = false and
+ additionalLocalStateStep(node1, state1, node2, state2, config)
) and
exists(ap) and
exists(lcc)
@@ -1009,22 +1139,37 @@ private module Stage2 {
private predicate flowIntoCall = flowIntoCallNodeCand1/5;
+ bindingset[node, state, ap, config]
+ private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
+ PrevStage::revFlowState(state, config) and
+ exists(ap) and
+ not stateBarrier(node, state, config)
+ }
+
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
/* Begin: Stage 2 logic. */
- private predicate flowCand(NodeEx node, ApApprox apa, Configuration config) {
- PrevStage::revFlow(node, _, _, apa, config)
+ bindingset[node, state, config]
+ private predicate flowCand(NodeEx node, FlowState state, ApApprox apa, Configuration config) {
+ PrevStage::revFlow(node, state, _, _, apa, config)
+ }
+
+ bindingset[result, apa]
+ private ApApprox unbindApa(ApApprox apa) {
+ pragma[only_bind_out](apa) = pragma[only_bind_out](result)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
- DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+ DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
+ Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
- pragma[only_bind_into](config))
+ pragma[only_bind_into](config)) and
+ ccc.matchesCall(call)
}
/**
@@ -1036,56 +1181,70 @@ private module Stage2 {
* argument.
*/
pragma[nomagic]
- predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
- flowCand(node, _, config) and
- sourceNode(node, config) and
+ predicate fwdFlow(NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ fwdFlow0(node, state, cc, argAp, ap, config) and
+ flowCand(node, state, unbindApa(getApprox(ap)), config) and
+ filter(node, state, ap, config)
+ }
+
+ pragma[nomagic]
+ private predicate fwdFlow0(
+ NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
+ ) {
+ sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
ap = getApNil(node)
or
- exists(NodeEx mid, Ap ap0, LocalCc localCc |
- fwdFlow(mid, cc, argAp, ap0, config) and
+ exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
+ fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
|
- localStep(mid, node, true, _, config, localCc) and
+ localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
or
- localStep(mid, node, false, ap, config, localCc) and
+ localStep(mid, state0, node, state, false, ap, config, localCc) and
ap0 instanceof ApNil
)
or
exists(NodeEx mid |
- fwdFlow(mid, _, _, ap, pragma[only_bind_into](config)) and
- flowCand(node, _, pragma[only_bind_into](config)) and
+ fwdFlow(mid, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
argAp = apNone()
)
or
exists(NodeEx mid, ApNil nil |
- fwdFlow(mid, _, _, nil, pragma[only_bind_into](config)) and
- flowCand(node, _, pragma[only_bind_into](config)) and
+ fwdFlow(mid, state, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
argAp = apNone() and
ap = getApNil(node)
)
or
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(mid, state0, _, _, nil, pragma[only_bind_into](config)) and
+ additionalJumpStateStep(mid, state0, node, state, config) and
+ cc = ccNone() and
+ argAp = apNone() and
+ ap = getApNil(node)
+ )
+ or
// store
exists(TypedContent tc, Ap ap0 |
- fwdFlowStore(_, ap0, tc, node, cc, argAp, config) and
+ fwdFlowStore(_, ap0, tc, node, state, cc, argAp, config) and
ap = apCons(tc, ap0)
)
or
// read
exists(Ap ap0, Content c |
- fwdFlowRead(ap0, c, _, node, cc, argAp, config) and
+ fwdFlowRead(ap0, c, _, node, state, cc, argAp, config) and
fwdFlowConsCand(ap0, c, ap, config)
)
or
// flow into a callable
exists(ApApprox apa |
- fwdFlowIn(_, node, _, cc, _, ap, config) and
+ fwdFlowIn(_, node, state, _, cc, _, ap, config) and
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, _, apa, config)
then argAp = apSome(ap)
@@ -1093,21 +1252,22 @@ private module Stage2 {
)
or
// flow out of a callable
- fwdFlowOutNotFromArg(node, cc, argAp, ap, config)
+ fwdFlowOutNotFromArg(node, state, cc, argAp, ap, config)
or
exists(DataFlowCall call, Ap argAp0 |
- fwdFlowOutFromArg(call, node, argAp0, ap, config) and
+ fwdFlowOutFromArg(call, node, state, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, argAp, argAp0, config)
)
}
pragma[nomagic]
private predicate fwdFlowStore(
- NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, ApOption argAp,
+ Configuration config
) {
exists(DataFlowType contentType |
- fwdFlow(node1, cc, argAp, ap1, config) and
- PrevStage::storeStepCand(node1, getApprox(ap1), tc, node2, contentType, config) and
+ fwdFlow(node1, state, cc, argAp, ap1, config) and
+ PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
}
@@ -1119,7 +1279,7 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
exists(TypedContent tc |
- fwdFlowStore(_, tail, tc, _, _, _, config) and
+ fwdFlowStore(_, tail, tc, _, _, _, _, config) and
tc.getContent() = c and
cons = apCons(tc, tail)
)
@@ -1127,54 +1287,51 @@ private module Stage2 {
pragma[nomagic]
private predicate fwdFlowRead(
- Ap ap, Content c, NodeEx node1, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ApOption argAp,
+ Configuration config
) {
- fwdFlow(node1, cc, argAp, ap, config) and
+ fwdFlow(node1, state, cc, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
}
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParamNodeEx p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
- Configuration config
+ DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc, ApOption argAp,
+ Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
- fwdFlow(arg, outercc, argAp, ap, config) and
+ fwdFlow(arg, state, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
- innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
- NodeEx out, Cc ccOut, ApOption argAp, Ap ap, Configuration config
+ NodeEx out, FlowState state, Cc ccOut, ApOption argAp, Ap ap, Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
- fwdFlow(ret, innercc, argAp, ap, config) and
+ fwdFlow(ret, state, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
- ccOut = getCallContextReturn(inner, call, innercc)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ ccOut = getCallContextReturn(inner, call, innercc) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
- DataFlowCall call, NodeEx out, Ap argAp, Ap ap, Configuration config
+ DataFlowCall call, NodeEx out, FlowState state, Ap argAp, Ap ap, Configuration config
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
- fwdFlow(ret, ccc, apSome(argAp), ap, config) and
- flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
- ccc.matchesCall(call)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ fwdFlow(ret, state, ccc, apSome(argAp), ap, config) and
+ flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1187,8 +1344,8 @@ private module Stage2 {
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p |
- fwdFlowIn(call, p, cc, _, argAp, ap, config) and
- PrevStage::parameterMayFlowThrough(p, _, getApprox(ap), config)
+ fwdFlowIn(call, p, _, cc, _, argAp, ap, config) and
+ PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1196,24 +1353,24 @@ private module Stage2 {
private predicate storeStepFwd(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config
) {
- fwdFlowStore(node1, ap1, tc, node2, _, _, config) and
+ fwdFlowStore(node1, ap1, tc, node2, _, _, _, config) and
ap2 = apCons(tc, ap1) and
- fwdFlowRead(ap2, tc.getContent(), _, _, _, _, config)
+ fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, config)
}
private predicate readStepFwd(
NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config
) {
- fwdFlowRead(ap1, c, n1, n2, _, _, config) and
+ fwdFlowRead(ap1, c, n1, n2, _, _, _, config) and
fwdFlowConsCand(ap1, c, ap2, config)
}
pragma[nomagic]
private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) {
- exists(Ap argAp0, NodeEx out, Cc cc, ApOption argAp, Ap ap |
- fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
+ exists(Ap argAp0, NodeEx out, FlowState state, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(out, state, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
pragma[only_bind_into](config)) and
- fwdFlowOutFromArg(call, out, argAp0, ap, config) and
+ fwdFlowOutFromArg(call, out, state, argAp0, ap, config) and
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
pragma[only_bind_into](config))
@@ -1225,11 +1382,18 @@ private module Stage2 {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
- fwdFlow(arg, _, _, _, pragma[only_bind_into](config)) and
+ fwdFlow(arg, _, _, _, _, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
+ pragma[nomagic]
+ private predicate returnNodeMayFlowThrough(
+ RetNodeEx ret, FlowState state, Ap ap, Configuration config
+ ) {
+ fwdFlow(ret, state, any(CcCall ccc), apSome(_), ap, config)
+ }
+
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1239,44 +1403,56 @@ private module Stage2 {
* the access path of the returned value.
*/
pragma[nomagic]
- predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
- revFlow0(node, toReturn, returnAp, ap, config) and
- fwdFlow(node, _, _, ap, config)
+ predicate revFlow(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow0(node, state, toReturn, returnAp, ap, config) and
+ fwdFlow(node, state, _, _, ap, config)
}
pragma[nomagic]
private predicate revFlow0(
- NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- fwdFlow(node, _, _, ap, config) and
- sinkNode(node, config) and
+ fwdFlow(node, state, _, _, ap, config) and
+ sinkNode(node, state, config) and
(if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and
returnAp = apNone() and
ap instanceof ApNil
or
- exists(NodeEx mid |
- localStep(node, mid, true, _, config, _) and
- revFlow(mid, toReturn, returnAp, ap, config)
+ exists(NodeEx mid, FlowState state0 |
+ localStep(node, state, mid, state0, true, _, config, _) and
+ revFlow(mid, state0, toReturn, returnAp, ap, config)
)
or
- exists(NodeEx mid, ApNil nil |
- fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
- localStep(node, mid, false, _, config, _) and
- revFlow(mid, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(node, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and
+ localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and
+ revFlow(mid, state0, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
ap instanceof ApNil
)
or
exists(NodeEx mid |
jumpStep(node, mid, config) and
- revFlow(mid, _, _, ap, config) and
+ revFlow(mid, state, _, _, ap, config) and
toReturn = false and
returnAp = apNone()
)
or
exists(NodeEx mid, ApNil nil |
- fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and
additionalJumpStep(node, mid, config) and
- revFlow(pragma[only_bind_into](mid), _, _, nil, pragma[only_bind_into](config)) and
+ revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and
+ toReturn = false and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ )
+ or
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and
+ additionalJumpStateStep(node, state, mid, state0, config) and
+ revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil,
+ pragma[only_bind_into](config)) and
toReturn = false and
returnAp = apNone() and
ap instanceof ApNil
@@ -1284,39 +1460,39 @@ private module Stage2 {
or
// store
exists(Ap ap0, Content c |
- revFlowStore(ap0, c, ap, node, _, _, toReturn, returnAp, config) and
+ revFlowStore(ap0, c, ap, node, state, _, _, toReturn, returnAp, config) and
revFlowConsCand(ap0, c, ap, config)
)
or
// read
exists(NodeEx mid, Ap ap0 |
- revFlow(mid, toReturn, returnAp, ap0, config) and
+ revFlow(mid, state, toReturn, returnAp, ap0, config) and
readStepFwd(node, ap, _, mid, ap0, config)
)
or
// flow into a callable
- revFlowInNotToReturn(node, returnAp, ap, config) and
+ revFlowInNotToReturn(node, state, returnAp, ap, config) and
toReturn = false
or
exists(DataFlowCall call, Ap returnAp0 |
- revFlowInToReturn(call, node, returnAp0, ap, config) and
+ revFlowInToReturn(call, node, state, returnAp0, ap, config) and
revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
)
or
// flow out of a callable
- revFlowOut(_, node, _, _, ap, config) and
+ revFlowOut(_, node, state, _, _, ap, config) and
toReturn = true and
- if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
+ if returnNodeMayFlowThrough(node, state, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
pragma[nomagic]
private predicate revFlowStore(
- Ap ap0, Content c, Ap ap, NodeEx node, TypedContent tc, NodeEx mid, boolean toReturn,
- ApOption returnAp, Configuration config
+ Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid,
+ boolean toReturn, ApOption returnAp, Configuration config
) {
- revFlow(mid, toReturn, returnAp, ap0, config) and
+ revFlow(mid, state, toReturn, returnAp, ap0, config) and
storeStepFwd(node, ap, tc, mid, ap0, config) and
tc.getContent() = c
}
@@ -1328,7 +1504,7 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
exists(NodeEx mid, Ap tail0 |
- revFlow(mid, _, _, tail, config) and
+ revFlow(mid, _, _, _, tail, config) and
tail = pragma[only_bind_into](tail0) and
readStepFwd(_, cons, c, mid, tail0, config)
)
@@ -1336,38 +1512,35 @@ private module Stage2 {
pragma[nomagic]
private predicate revFlowOut(
- DataFlowCall call, RetNodeEx ret, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, RetNodeEx ret, FlowState state, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
- revFlow(out, toReturn, returnAp, ap, config) and
- flowOutOfCall(call, ret, out, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(out, state, toReturn, returnAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
- ArgNodeEx arg, ApOption returnAp, Ap ap, Configuration config
+ ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
- revFlow(p, false, returnAp, ap, config) and
- flowIntoCall(_, arg, p, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(p, state, false, returnAp, ap, config) and
+ flowIntoCall(_, arg, p, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgNodeEx arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNodeEx arg, FlowState state, Ap returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
- revFlow(p, true, apSome(returnAp), ap, config) and
- flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(p, state, true, apSome(returnAp), ap, config) and
+ flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1380,9 +1553,9 @@ private module Stage2 {
private predicate revFlowIsReturned(
DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(RetNodeEx ret, CcCall ccc |
- revFlowOut(call, ret, toReturn, returnAp, ap, config) and
- fwdFlow(ret, ccc, apSome(_), ap, config) and
+ exists(RetNodeEx ret, FlowState state, CcCall ccc |
+ revFlowOut(call, ret, state, toReturn, returnAp, ap, config) and
+ fwdFlow(ret, state, ccc, apSome(_), ap, config) and
ccc.matchesCall(call)
)
}
@@ -1394,21 +1567,38 @@ private module Stage2 {
) {
exists(Ap ap2, Content c |
store(node1, tc, node2, contentType, config) and
- revFlowStore(ap2, c, ap1, node1, tc, node2, _, _, config) and
+ revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
revFlowConsCand(ap2, c, ap1, config)
)
}
predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(Ap ap1, Ap ap2 |
- revFlow(node2, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
+ revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
readStepFwd(node1, ap1, c, node2, ap2, config) and
- revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _,
+ revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _,
pragma[only_bind_into](config))
)
}
- predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, config) }
+ predicate revFlow(NodeEx node, FlowState state, Configuration config) {
+ revFlow(node, state, _, _, _, config)
+ }
+
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
+
+ // use an alias as a workaround for bad functionality-induced joins
+ pragma[nomagic]
+ predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
+
+ // use an alias as a workaround for bad functionality-induced joins
+ pragma[nomagic]
+ predicate revFlowAlias(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow(node, state, toReturn, returnAp, ap, config)
+ }
private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepFwd(_, ap, tc, _, _, config)
@@ -1422,17 +1612,17 @@ private module Stage2 {
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
- revFlow(p, true, apSome(ap0), ap, config) and
+ revFlow(p, _, true, apSome(ap0), ap, config) and
c = p.getEnclosingCallable()
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
- exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
+ exists(RetNodeEx ret, FlowState state, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
- revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
- pragma[only_bind_into](config)) and
- fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
+ revFlow(pragma[only_bind_into](ret), pragma[only_bind_into](state), true, apSome(_),
+ pragma[only_bind_into](ap0), pragma[only_bind_into](config)) and
+ fwdFlow(ret, state, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself, unless explicitly allowed
@@ -1446,25 +1636,37 @@ private module Stage2 {
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
- exists(Ap returnAp0, ArgNodeEx arg, boolean toReturn, ApOption returnAp, Ap ap |
- revFlow(arg, toReturn, returnAp, ap, config) and
- revFlowInToReturn(call, arg, returnAp0, ap, config) and
+ exists(
+ Ap returnAp0, ArgNodeEx arg, FlowState state, boolean toReturn, ApOption returnAp, Ap ap
+ |
+ revFlow(arg, state, toReturn, returnAp, ap, config) and
+ revFlowInToReturn(call, arg, state, returnAp0, ap, config) and
revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
)
}
- predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ predicate stats(
+ boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
+ ) {
fwd = true and
- nodes = count(NodeEx node | fwdFlow(node, _, _, _, config)) and
+ nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, config)) and
fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
- tuples = count(NodeEx n, Cc cc, ApOption argAp, Ap ap | fwdFlow(n, cc, argAp, ap, config))
+ states = count(FlowState state | fwdFlow(_, state, _, _, _, config)) and
+ tuples =
+ count(NodeEx n, FlowState state, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(n, state, cc, argAp, ap, config)
+ )
or
fwd = false and
- nodes = count(NodeEx node | revFlow(node, _, _, _, config)) and
+ nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
fields = count(TypedContent f0 | consCand(f0, _, config)) and
conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and
- tuples = count(NodeEx n, boolean b, ApOption retAp, Ap ap | revFlow(n, b, retAp, ap, config))
+ states = count(FlowState state | revFlow(_, state, _, _, _, config)) and
+ tuples =
+ count(NodeEx n, FlowState state, boolean b, ApOption retAp, Ap ap |
+ revFlow(n, state, b, retAp, ap, config)
+ )
}
/* End: Stage 2 logic. */
}
@@ -1475,7 +1677,7 @@ private predicate flowOutOfCallNodeCand2(
) {
flowOutOfCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
- Stage2::revFlow(node1, pragma[only_bind_into](config))
+ Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
pragma[nomagic]
@@ -1485,7 +1687,7 @@ private predicate flowIntoCallNodeCand2(
) {
flowIntoCallNodeCand1(call, node1, node2, allowsFieldFlow, config) and
Stage2::revFlow(node2, pragma[only_bind_into](config)) and
- Stage2::revFlow(node1, pragma[only_bind_into](config))
+ Stage2::revFlowAlias(node1, pragma[only_bind_into](config))
}
private module LocalFlowBigStep {
@@ -1504,12 +1706,13 @@ private module LocalFlowBigStep {
* Holds if `node` can be the first node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
- predicate localFlowEntry(NodeEx node, Configuration config) {
- Stage2::revFlow(node, config) and
+ predicate localFlowEntry(NodeEx node, FlowState state, Configuration config) {
+ Stage2::revFlow(node, state, config) and
(
- sourceNode(node, config) or
+ sourceNode(node, state, config) or
jumpStep(_, node, config) or
additionalJumpStep(_, node, config) or
+ additionalJumpStateStep(_, _, node, state, config) or
node instanceof ParamNodeEx or
node.asNode() instanceof OutNodeExt or
store(_, _, node, _, config) or
@@ -1522,8 +1725,8 @@ private module LocalFlowBigStep {
* Holds if `node` can be the last node in a maximal subsequence of local
* flow steps in a dataflow path.
*/
- private predicate localFlowExit(NodeEx node, Configuration config) {
- exists(NodeEx next | Stage2::revFlow(next, config) |
+ private predicate localFlowExit(NodeEx node, FlowState state, Configuration config) {
+ exists(NodeEx next | Stage2::revFlow(next, state, config) |
jumpStep(node, next, config) or
additionalJumpStep(node, next, config) or
flowIntoCallNodeCand1(_, node, next, config) or
@@ -1532,18 +1735,30 @@ private module LocalFlowBigStep {
read(node, _, next, config)
)
or
+ exists(NodeEx next, FlowState s | Stage2::revFlow(next, s, config) |
+ additionalJumpStateStep(node, state, next, s, config)
+ )
+ or
+ Stage2::revFlow(node, state, config) and
node instanceof FlowCheckNode
or
- sinkNode(node, config)
+ sinkNode(node, state, config)
}
pragma[noinline]
private predicate additionalLocalFlowStepNodeCand2(
- NodeEx node1, NodeEx node2, Configuration config
+ NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, Configuration config
) {
additionalLocalFlowStepNodeCand1(node1, node2, config) and
- Stage2::revFlow(node1, _, _, false, pragma[only_bind_into](config)) and
- Stage2::revFlow(node2, _, _, false, pragma[only_bind_into](config))
+ state1 = state2 and
+ Stage2::revFlow(node1, pragma[only_bind_into](state1), _, _, false,
+ pragma[only_bind_into](config)) and
+ Stage2::revFlowAlias(node2, pragma[only_bind_into](state2), _, _, false,
+ pragma[only_bind_into](config))
+ or
+ additionalLocalStateStep(node1, state1, node2, state2, config) and
+ Stage2::revFlow(node1, state1, _, _, false, pragma[only_bind_into](config)) and
+ Stage2::revFlowAlias(node2, state2, _, _, false, pragma[only_bind_into](config))
}
/**
@@ -1555,40 +1770,42 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
private predicate localFlowStepPlus(
- NodeEx node1, NodeEx node2, boolean preservesValue, DataFlowType t, Configuration config,
- LocalCallContext cc
+ NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
+ DataFlowType t, Configuration config, LocalCallContext cc
) {
not isUnreachableInCallCached(node2.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
(
- localFlowEntry(node1, pragma[only_bind_into](config)) and
+ localFlowEntry(node1, pragma[only_bind_into](state1), pragma[only_bind_into](config)) and
(
localFlowStepNodeCand1(node1, node2, config) and
+ state1 = state2 and
preservesValue = true and
t = node1.getDataFlowType() // irrelevant dummy value
or
- additionalLocalFlowStepNodeCand2(node1, node2, config) and
+ additionalLocalFlowStepNodeCand2(node1, state1, node2, state2, config) and
preservesValue = false and
t = node2.getDataFlowType()
) and
node1 != node2 and
cc.relevantFor(node1.getEnclosingCallable()) and
not isUnreachableInCallCached(node1.asNode(), cc.(LocalCallContextSpecificCall).getCall()) and
- Stage2::revFlow(node2, pragma[only_bind_into](config))
+ Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
or
exists(NodeEx mid |
- localFlowStepPlus(node1, mid, preservesValue, t, pragma[only_bind_into](config), cc) and
+ localFlowStepPlus(node1, state1, mid, pragma[only_bind_into](state2), preservesValue, t,
+ pragma[only_bind_into](config), cc) and
localFlowStepNodeCand1(mid, node2, config) and
not mid instanceof FlowCheckNode and
- Stage2::revFlow(node2, pragma[only_bind_into](config))
+ Stage2::revFlow(node2, pragma[only_bind_into](state2), pragma[only_bind_into](config))
)
or
- exists(NodeEx mid |
- localFlowStepPlus(node1, mid, _, _, pragma[only_bind_into](config), cc) and
- additionalLocalFlowStepNodeCand2(mid, node2, config) and
+ exists(NodeEx mid, FlowState st |
+ localFlowStepPlus(node1, state1, mid, st, _, _, pragma[only_bind_into](config), cc) and
+ additionalLocalFlowStepNodeCand2(mid, st, node2, state2, config) and
not mid instanceof FlowCheckNode and
preservesValue = false and
t = node2.getDataFlowType() and
- Stage2::revFlow(node2, pragma[only_bind_into](config))
+ Stage2::revFlow(node2, state2, pragma[only_bind_into](config))
)
)
}
@@ -1599,11 +1816,12 @@ private module LocalFlowBigStep {
*/
pragma[nomagic]
predicate localFlowBigStep(
- NodeEx node1, NodeEx node2, boolean preservesValue, AccessPathFrontNil apf,
- Configuration config, LocalCallContext callContext
+ NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
+ AccessPathFrontNil apf, Configuration config, LocalCallContext callContext
) {
- localFlowStepPlus(node1, node2, preservesValue, apf.getType(), config, callContext) and
- localFlowExit(node2, config)
+ localFlowStepPlus(node1, state1, node2, state2, preservesValue, apf.getType(), config,
+ callContext) and
+ localFlowExit(node2, state2, config)
}
}
@@ -1665,9 +1883,10 @@ private module Stage3 {
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) { any() }
private predicate localStep(
- NodeEx node1, NodeEx node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc
+ NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
+ ApNil ap, Configuration config, LocalCc lcc
) {
- localFlowBigStep(node1, node2, preservesValue, ap, config, _) and exists(lcc)
+ localFlowBigStep(node1, state1, node2, state2, preservesValue, ap, config, _) and exists(lcc)
}
private predicate flowOutOfCall = flowOutOfCallNodeCand2/5;
@@ -1680,8 +1899,10 @@ private module Stage3 {
pragma[nomagic]
private predicate castingNodeEx(NodeEx node) { node.asNode() instanceof CastingNode }
- bindingset[node, ap]
- private predicate filter(NodeEx node, Ap ap) {
+ bindingset[node, state, ap, config]
+ private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) {
+ exists(state) and
+ exists(config) and
not clear(node, ap) and
if castingNodeEx(node) then compatibleTypes(node.getDataFlowType(), ap.getType()) else any()
}
@@ -1694,25 +1915,26 @@ private module Stage3 {
}
/* Begin: Stage 3 logic. */
- private predicate flowCand(NodeEx node, ApApprox apa, Configuration config) {
- PrevStage::revFlow(node, _, _, apa, config)
+ bindingset[node, state, config]
+ private predicate flowCand(NodeEx node, FlowState state, ApApprox apa, Configuration config) {
+ PrevStage::revFlow(node, state, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
- exists(ApApprox apa0 |
- apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
- )
+ pragma[only_bind_out](apa) = pragma[only_bind_out](result)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
- DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+ DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
+ Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
- pragma[only_bind_into](config))
+ pragma[only_bind_into](config)) and
+ ccc.matchesCall(call)
}
/**
@@ -1724,63 +1946,70 @@ private module Stage3 {
* argument.
*/
pragma[nomagic]
- predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
- fwdFlow0(node, cc, argAp, ap, config) and
- flowCand(node, unbindApa(getApprox(ap)), config) and
- filter(node, ap)
+ predicate fwdFlow(NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ fwdFlow0(node, state, cc, argAp, ap, config) and
+ flowCand(node, state, unbindApa(getApprox(ap)), config) and
+ filter(node, state, ap, config)
}
pragma[nomagic]
- private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
- flowCand(node, _, config) and
- sourceNode(node, config) and
+ private predicate fwdFlow0(
+ NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
+ ) {
+ sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
ap = getApNil(node)
or
- exists(NodeEx mid, Ap ap0, LocalCc localCc |
- fwdFlow(mid, cc, argAp, ap0, config) and
+ exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
+ fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
|
- localStep(mid, node, true, _, config, localCc) and
+ localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
or
- localStep(mid, node, false, ap, config, localCc) and
+ localStep(mid, state0, node, state, false, ap, config, localCc) and
ap0 instanceof ApNil
)
or
exists(NodeEx mid |
- fwdFlow(mid, _, _, ap, pragma[only_bind_into](config)) and
- flowCand(node, _, pragma[only_bind_into](config)) and
+ fwdFlow(mid, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
argAp = apNone()
)
or
exists(NodeEx mid, ApNil nil |
- fwdFlow(mid, _, _, nil, pragma[only_bind_into](config)) and
- flowCand(node, _, pragma[only_bind_into](config)) and
+ fwdFlow(mid, state, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
argAp = apNone() and
ap = getApNil(node)
)
or
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(mid, state0, _, _, nil, pragma[only_bind_into](config)) and
+ additionalJumpStateStep(mid, state0, node, state, config) and
+ cc = ccNone() and
+ argAp = apNone() and
+ ap = getApNil(node)
+ )
+ or
// store
exists(TypedContent tc, Ap ap0 |
- fwdFlowStore(_, ap0, tc, node, cc, argAp, config) and
+ fwdFlowStore(_, ap0, tc, node, state, cc, argAp, config) and
ap = apCons(tc, ap0)
)
or
// read
exists(Ap ap0, Content c |
- fwdFlowRead(ap0, c, _, node, cc, argAp, config) and
+ fwdFlowRead(ap0, c, _, node, state, cc, argAp, config) and
fwdFlowConsCand(ap0, c, ap, config)
)
or
// flow into a callable
exists(ApApprox apa |
- fwdFlowIn(_, node, _, cc, _, ap, config) and
+ fwdFlowIn(_, node, state, _, cc, _, ap, config) and
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, _, apa, config)
then argAp = apSome(ap)
@@ -1788,20 +2017,21 @@ private module Stage3 {
)
or
// flow out of a callable
- fwdFlowOutNotFromArg(node, cc, argAp, ap, config)
+ fwdFlowOutNotFromArg(node, state, cc, argAp, ap, config)
or
exists(DataFlowCall call, Ap argAp0 |
- fwdFlowOutFromArg(call, node, argAp0, ap, config) and
+ fwdFlowOutFromArg(call, node, state, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, argAp, argAp0, config)
)
}
pragma[nomagic]
private predicate fwdFlowStore(
- NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, ApOption argAp,
+ Configuration config
) {
exists(DataFlowType contentType |
- fwdFlow(node1, cc, argAp, ap1, config) and
+ fwdFlow(node1, state, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
@@ -1814,7 +2044,7 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
exists(TypedContent tc |
- fwdFlowStore(_, tail, tc, _, _, _, config) and
+ fwdFlowStore(_, tail, tc, _, _, _, _, config) and
tc.getContent() = c and
cons = apCons(tc, tail)
)
@@ -1822,54 +2052,51 @@ private module Stage3 {
pragma[nomagic]
private predicate fwdFlowRead(
- Ap ap, Content c, NodeEx node1, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ApOption argAp,
+ Configuration config
) {
- fwdFlow(node1, cc, argAp, ap, config) and
+ fwdFlow(node1, state, cc, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
}
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParamNodeEx p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
- Configuration config
+ DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc, ApOption argAp,
+ Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
- fwdFlow(arg, outercc, argAp, ap, config) and
+ fwdFlow(arg, state, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
- innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
- NodeEx out, Cc ccOut, ApOption argAp, Ap ap, Configuration config
+ NodeEx out, FlowState state, Cc ccOut, ApOption argAp, Ap ap, Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
- fwdFlow(ret, innercc, argAp, ap, config) and
+ fwdFlow(ret, state, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
- ccOut = getCallContextReturn(inner, call, innercc)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ ccOut = getCallContextReturn(inner, call, innercc) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
- DataFlowCall call, NodeEx out, Ap argAp, Ap ap, Configuration config
+ DataFlowCall call, NodeEx out, FlowState state, Ap argAp, Ap ap, Configuration config
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
- fwdFlow(ret, ccc, apSome(argAp), ap, config) and
- flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
- ccc.matchesCall(call)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ fwdFlow(ret, state, ccc, apSome(argAp), ap, config) and
+ flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -1882,7 +2109,7 @@ private module Stage3 {
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p |
- fwdFlowIn(call, p, cc, _, argAp, ap, config) and
+ fwdFlowIn(call, p, _, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -1891,24 +2118,24 @@ private module Stage3 {
private predicate storeStepFwd(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config
) {
- fwdFlowStore(node1, ap1, tc, node2, _, _, config) and
+ fwdFlowStore(node1, ap1, tc, node2, _, _, _, config) and
ap2 = apCons(tc, ap1) and
- fwdFlowRead(ap2, tc.getContent(), _, _, _, _, config)
+ fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, config)
}
private predicate readStepFwd(
NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config
) {
- fwdFlowRead(ap1, c, n1, n2, _, _, config) and
+ fwdFlowRead(ap1, c, n1, n2, _, _, _, config) and
fwdFlowConsCand(ap1, c, ap2, config)
}
pragma[nomagic]
private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) {
- exists(Ap argAp0, NodeEx out, Cc cc, ApOption argAp, Ap ap |
- fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
+ exists(Ap argAp0, NodeEx out, FlowState state, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(out, state, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
pragma[only_bind_into](config)) and
- fwdFlowOutFromArg(call, out, argAp0, ap, config) and
+ fwdFlowOutFromArg(call, out, state, argAp0, ap, config) and
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
pragma[only_bind_into](config))
@@ -1920,11 +2147,18 @@ private module Stage3 {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
- fwdFlow(arg, _, _, _, pragma[only_bind_into](config)) and
+ fwdFlow(arg, _, _, _, _, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
+ pragma[nomagic]
+ private predicate returnNodeMayFlowThrough(
+ RetNodeEx ret, FlowState state, Ap ap, Configuration config
+ ) {
+ fwdFlow(ret, state, any(CcCall ccc), apSome(_), ap, config)
+ }
+
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -1934,44 +2168,56 @@ private module Stage3 {
* the access path of the returned value.
*/
pragma[nomagic]
- predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
- revFlow0(node, toReturn, returnAp, ap, config) and
- fwdFlow(node, _, _, ap, config)
+ predicate revFlow(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow0(node, state, toReturn, returnAp, ap, config) and
+ fwdFlow(node, state, _, _, ap, config)
}
pragma[nomagic]
private predicate revFlow0(
- NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- fwdFlow(node, _, _, ap, config) and
- sinkNode(node, config) and
+ fwdFlow(node, state, _, _, ap, config) and
+ sinkNode(node, state, config) and
(if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and
returnAp = apNone() and
ap instanceof ApNil
or
- exists(NodeEx mid |
- localStep(node, mid, true, _, config, _) and
- revFlow(mid, toReturn, returnAp, ap, config)
+ exists(NodeEx mid, FlowState state0 |
+ localStep(node, state, mid, state0, true, _, config, _) and
+ revFlow(mid, state0, toReturn, returnAp, ap, config)
)
or
- exists(NodeEx mid, ApNil nil |
- fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
- localStep(node, mid, false, _, config, _) and
- revFlow(mid, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(node, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and
+ localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and
+ revFlow(mid, state0, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
ap instanceof ApNil
)
or
exists(NodeEx mid |
jumpStep(node, mid, config) and
- revFlow(mid, _, _, ap, config) and
+ revFlow(mid, state, _, _, ap, config) and
toReturn = false and
returnAp = apNone()
)
or
exists(NodeEx mid, ApNil nil |
- fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and
additionalJumpStep(node, mid, config) and
- revFlow(pragma[only_bind_into](mid), _, _, nil, pragma[only_bind_into](config)) and
+ revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and
+ toReturn = false and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ )
+ or
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and
+ additionalJumpStateStep(node, state, mid, state0, config) and
+ revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil,
+ pragma[only_bind_into](config)) and
toReturn = false and
returnAp = apNone() and
ap instanceof ApNil
@@ -1979,39 +2225,39 @@ private module Stage3 {
or
// store
exists(Ap ap0, Content c |
- revFlowStore(ap0, c, ap, node, _, _, toReturn, returnAp, config) and
+ revFlowStore(ap0, c, ap, node, state, _, _, toReturn, returnAp, config) and
revFlowConsCand(ap0, c, ap, config)
)
or
// read
exists(NodeEx mid, Ap ap0 |
- revFlow(mid, toReturn, returnAp, ap0, config) and
+ revFlow(mid, state, toReturn, returnAp, ap0, config) and
readStepFwd(node, ap, _, mid, ap0, config)
)
or
// flow into a callable
- revFlowInNotToReturn(node, returnAp, ap, config) and
+ revFlowInNotToReturn(node, state, returnAp, ap, config) and
toReturn = false
or
exists(DataFlowCall call, Ap returnAp0 |
- revFlowInToReturn(call, node, returnAp0, ap, config) and
+ revFlowInToReturn(call, node, state, returnAp0, ap, config) and
revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
)
or
// flow out of a callable
- revFlowOut(_, node, _, _, ap, config) and
+ revFlowOut(_, node, state, _, _, ap, config) and
toReturn = true and
- if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
+ if returnNodeMayFlowThrough(node, state, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
pragma[nomagic]
private predicate revFlowStore(
- Ap ap0, Content c, Ap ap, NodeEx node, TypedContent tc, NodeEx mid, boolean toReturn,
- ApOption returnAp, Configuration config
+ Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid,
+ boolean toReturn, ApOption returnAp, Configuration config
) {
- revFlow(mid, toReturn, returnAp, ap0, config) and
+ revFlow(mid, state, toReturn, returnAp, ap0, config) and
storeStepFwd(node, ap, tc, mid, ap0, config) and
tc.getContent() = c
}
@@ -2023,7 +2269,7 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
exists(NodeEx mid, Ap tail0 |
- revFlow(mid, _, _, tail, config) and
+ revFlow(mid, _, _, _, tail, config) and
tail = pragma[only_bind_into](tail0) and
readStepFwd(_, cons, c, mid, tail0, config)
)
@@ -2031,38 +2277,35 @@ private module Stage3 {
pragma[nomagic]
private predicate revFlowOut(
- DataFlowCall call, RetNodeEx ret, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, RetNodeEx ret, FlowState state, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
- revFlow(out, toReturn, returnAp, ap, config) and
- flowOutOfCall(call, ret, out, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(out, state, toReturn, returnAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
- ArgNodeEx arg, ApOption returnAp, Ap ap, Configuration config
+ ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
- revFlow(p, false, returnAp, ap, config) and
- flowIntoCall(_, arg, p, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(p, state, false, returnAp, ap, config) and
+ flowIntoCall(_, arg, p, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgNodeEx arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNodeEx arg, FlowState state, Ap returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
- revFlow(p, true, apSome(returnAp), ap, config) and
- flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(p, state, true, apSome(returnAp), ap, config) and
+ flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2075,9 +2318,9 @@ private module Stage3 {
private predicate revFlowIsReturned(
DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(RetNodeEx ret, CcCall ccc |
- revFlowOut(call, ret, toReturn, returnAp, ap, config) and
- fwdFlow(ret, ccc, apSome(_), ap, config) and
+ exists(RetNodeEx ret, FlowState state, CcCall ccc |
+ revFlowOut(call, ret, state, toReturn, returnAp, ap, config) and
+ fwdFlow(ret, state, ccc, apSome(_), ap, config) and
ccc.matchesCall(call)
)
}
@@ -2089,21 +2332,38 @@ private module Stage3 {
) {
exists(Ap ap2, Content c |
store(node1, tc, node2, contentType, config) and
- revFlowStore(ap2, c, ap1, node1, tc, node2, _, _, config) and
+ revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
revFlowConsCand(ap2, c, ap1, config)
)
}
predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(Ap ap1, Ap ap2 |
- revFlow(node2, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
+ revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
readStepFwd(node1, ap1, c, node2, ap2, config) and
- revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _,
+ revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _,
pragma[only_bind_into](config))
)
}
- predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, config) }
+ predicate revFlow(NodeEx node, FlowState state, Configuration config) {
+ revFlow(node, state, _, _, _, config)
+ }
+
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
+
+ // use an alias as a workaround for bad functionality-induced joins
+ pragma[nomagic]
+ predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
+
+ // use an alias as a workaround for bad functionality-induced joins
+ pragma[nomagic]
+ predicate revFlowAlias(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow(node, state, toReturn, returnAp, ap, config)
+ }
private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepFwd(_, ap, tc, _, _, config)
@@ -2117,17 +2377,17 @@ private module Stage3 {
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
- revFlow(p, true, apSome(ap0), ap, config) and
+ revFlow(p, _, true, apSome(ap0), ap, config) and
c = p.getEnclosingCallable()
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
- exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
+ exists(RetNodeEx ret, FlowState state, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
- revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
- pragma[only_bind_into](config)) and
- fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
+ revFlow(pragma[only_bind_into](ret), pragma[only_bind_into](state), true, apSome(_),
+ pragma[only_bind_into](ap0), pragma[only_bind_into](config)) and
+ fwdFlow(ret, state, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself, unless explicitly allowed
@@ -2141,25 +2401,37 @@ private module Stage3 {
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
- exists(Ap returnAp0, ArgNodeEx arg, boolean toReturn, ApOption returnAp, Ap ap |
- revFlow(arg, toReturn, returnAp, ap, config) and
- revFlowInToReturn(call, arg, returnAp0, ap, config) and
+ exists(
+ Ap returnAp0, ArgNodeEx arg, FlowState state, boolean toReturn, ApOption returnAp, Ap ap
+ |
+ revFlow(arg, state, toReturn, returnAp, ap, config) and
+ revFlowInToReturn(call, arg, state, returnAp0, ap, config) and
revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
)
}
- predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ predicate stats(
+ boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
+ ) {
fwd = true and
- nodes = count(NodeEx node | fwdFlow(node, _, _, _, config)) and
+ nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, config)) and
fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
- tuples = count(NodeEx n, Cc cc, ApOption argAp, Ap ap | fwdFlow(n, cc, argAp, ap, config))
+ states = count(FlowState state | fwdFlow(_, state, _, _, _, config)) and
+ tuples =
+ count(NodeEx n, FlowState state, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(n, state, cc, argAp, ap, config)
+ )
or
fwd = false and
- nodes = count(NodeEx node | revFlow(node, _, _, _, config)) and
+ nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
fields = count(TypedContent f0 | consCand(f0, _, config)) and
conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and
- tuples = count(NodeEx n, boolean b, ApOption retAp, Ap ap | revFlow(n, b, retAp, ap, config))
+ states = count(FlowState state | revFlow(_, state, _, _, _, config)) and
+ tuples =
+ count(NodeEx n, FlowState state, boolean b, ApOption retAp, Ap ap |
+ revFlow(n, state, b, retAp, ap, config)
+ )
}
/* End: Stage 3 logic. */
}
@@ -2168,10 +2440,12 @@ private module Stage3 {
* Holds if `argApf` is recorded as the summary context for flow reaching `node`
* and remains relevant for the following pruning stage.
*/
-private predicate flowCandSummaryCtx(NodeEx node, AccessPathFront argApf, Configuration config) {
+private predicate flowCandSummaryCtx(
+ NodeEx node, FlowState state, AccessPathFront argApf, Configuration config
+) {
exists(AccessPathFront apf |
- Stage3::revFlow(node, true, _, apf, config) and
- Stage3::fwdFlow(node, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
+ Stage3::revFlow(node, state, true, _, apf, config) and
+ Stage3::fwdFlow(node, state, any(Stage3::CcCall ccc), TAccessPathFrontSome(argApf), apf, config)
)
}
@@ -2183,10 +2457,10 @@ private predicate expensiveLen2unfolding(TypedContent tc, Configuration config)
exists(int tails, int nodes, int apLimit, int tupleLimit |
tails = strictcount(AccessPathFront apf | Stage3::consCand(tc, apf, config)) and
nodes =
- strictcount(NodeEx n |
- Stage3::revFlow(n, _, _, any(AccessPathFrontHead apf | apf.getHead() = tc), config)
+ strictcount(NodeEx n, FlowState state |
+ Stage3::revFlow(n, state, _, _, any(AccessPathFrontHead apf | apf.getHead() = tc), config)
or
- flowCandSummaryCtx(n, any(AccessPathFrontHead apf | apf.getHead() = tc), config)
+ flowCandSummaryCtx(n, state, any(AccessPathFrontHead apf | apf.getHead() = tc), config)
) and
accessPathApproxCostLimits(apLimit, tupleLimit) and
apLimit < tails and
@@ -2421,25 +2695,30 @@ private module Stage4 {
bindingset[node, cc, config]
private LocalCc getLocalCc(NodeEx node, Cc cc, Configuration config) {
- localFlowEntry(node, config) and
+ localFlowEntry(node, _, config) and
result =
getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
node.getEnclosingCallable())
}
private predicate localStep(
- NodeEx node1, NodeEx node2, boolean preservesValue, ApNil ap, Configuration config, LocalCc lcc
+ NodeEx node1, FlowState state1, NodeEx node2, FlowState state2, boolean preservesValue,
+ ApNil ap, Configuration config, LocalCc lcc
) {
- localFlowBigStep(node1, node2, preservesValue, ap.getFront(), config, lcc)
+ localFlowBigStep(node1, state1, node2, state2, preservesValue, ap.getFront(), config, lcc)
}
pragma[nomagic]
private predicate flowOutOfCall(
DataFlowCall call, RetNodeEx node1, NodeEx node2, boolean allowsFieldFlow, Configuration config
) {
- flowOutOfCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
- PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
- PrevStage::revFlow(node1, _, _, _, pragma[only_bind_into](config))
+ exists(FlowState state |
+ flowOutOfCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
+ PrevStage::revFlow(node2, pragma[only_bind_into](state), _, _, _,
+ pragma[only_bind_into](config)) and
+ PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, _, _,
+ pragma[only_bind_into](config))
+ )
}
pragma[nomagic]
@@ -2447,38 +2726,43 @@ private module Stage4 {
DataFlowCall call, ArgNodeEx node1, ParamNodeEx node2, boolean allowsFieldFlow,
Configuration config
) {
- flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
- PrevStage::revFlow(node2, _, _, _, pragma[only_bind_into](config)) and
- PrevStage::revFlow(node1, _, _, _, pragma[only_bind_into](config))
+ exists(FlowState state |
+ flowIntoCallNodeCand2(call, node1, node2, allowsFieldFlow, config) and
+ PrevStage::revFlow(node2, pragma[only_bind_into](state), _, _, _,
+ pragma[only_bind_into](config)) and
+ PrevStage::revFlowAlias(node1, pragma[only_bind_into](state), _, _, _,
+ pragma[only_bind_into](config))
+ )
}
- bindingset[node, ap]
- private predicate filter(NodeEx node, Ap ap) { any() }
+ bindingset[node, state, ap, config]
+ private predicate filter(NodeEx node, FlowState state, Ap ap, Configuration config) { any() }
// Type checking is not necessary here as it has already been done in stage 3.
bindingset[ap, contentType]
private predicate typecheckStore(Ap ap, DataFlowType contentType) { any() }
/* Begin: Stage 4 logic. */
- private predicate flowCand(NodeEx node, ApApprox apa, Configuration config) {
- PrevStage::revFlow(node, _, _, apa, config)
+ bindingset[node, state, config]
+ private predicate flowCand(NodeEx node, FlowState state, ApApprox apa, Configuration config) {
+ PrevStage::revFlow(node, state, _, _, apa, config)
}
bindingset[result, apa]
private ApApprox unbindApa(ApApprox apa) {
- exists(ApApprox apa0 |
- apa = pragma[only_bind_into](apa0) and result = pragma[only_bind_into](apa0)
- )
+ pragma[only_bind_out](apa) = pragma[only_bind_out](result)
}
pragma[nomagic]
private predicate flowThroughOutOfCall(
- DataFlowCall call, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow, Configuration config
+ DataFlowCall call, CcCall ccc, RetNodeEx ret, NodeEx out, boolean allowsFieldFlow,
+ Configuration config
) {
flowOutOfCall(call, ret, out, allowsFieldFlow, pragma[only_bind_into](config)) and
PrevStage::callMayFlowThroughRev(call, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(_, ret.getEnclosingCallable(), _,
- pragma[only_bind_into](config))
+ pragma[only_bind_into](config)) and
+ ccc.matchesCall(call)
}
/**
@@ -2490,63 +2774,70 @@ private module Stage4 {
* argument.
*/
pragma[nomagic]
- predicate fwdFlow(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
- fwdFlow0(node, cc, argAp, ap, config) and
- flowCand(node, unbindApa(getApprox(ap)), config) and
- filter(node, ap)
+ predicate fwdFlow(NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config) {
+ fwdFlow0(node, state, cc, argAp, ap, config) and
+ flowCand(node, state, unbindApa(getApprox(ap)), config) and
+ filter(node, state, ap, config)
}
pragma[nomagic]
- private predicate fwdFlow0(NodeEx node, Cc cc, ApOption argAp, Ap ap, Configuration config) {
- flowCand(node, _, config) and
- sourceNode(node, config) and
+ private predicate fwdFlow0(
+ NodeEx node, FlowState state, Cc cc, ApOption argAp, Ap ap, Configuration config
+ ) {
+ sourceNode(node, state, config) and
(if hasSourceCallCtx(config) then cc = ccSomeCall() else cc = ccNone()) and
argAp = apNone() and
ap = getApNil(node)
or
- exists(NodeEx mid, Ap ap0, LocalCc localCc |
- fwdFlow(mid, cc, argAp, ap0, config) and
+ exists(NodeEx mid, FlowState state0, Ap ap0, LocalCc localCc |
+ fwdFlow(mid, state0, cc, argAp, ap0, config) and
localCc = getLocalCc(mid, cc, config)
|
- localStep(mid, node, true, _, config, localCc) and
+ localStep(mid, state0, node, state, true, _, config, localCc) and
ap = ap0
or
- localStep(mid, node, false, ap, config, localCc) and
+ localStep(mid, state0, node, state, false, ap, config, localCc) and
ap0 instanceof ApNil
)
or
exists(NodeEx mid |
- fwdFlow(mid, _, _, ap, pragma[only_bind_into](config)) and
- flowCand(node, _, pragma[only_bind_into](config)) and
+ fwdFlow(mid, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and
jumpStep(mid, node, config) and
cc = ccNone() and
argAp = apNone()
)
or
exists(NodeEx mid, ApNil nil |
- fwdFlow(mid, _, _, nil, pragma[only_bind_into](config)) and
- flowCand(node, _, pragma[only_bind_into](config)) and
+ fwdFlow(mid, state, _, _, nil, pragma[only_bind_into](config)) and
additionalJumpStep(mid, node, config) and
cc = ccNone() and
argAp = apNone() and
ap = getApNil(node)
)
or
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(mid, state0, _, _, nil, pragma[only_bind_into](config)) and
+ additionalJumpStateStep(mid, state0, node, state, config) and
+ cc = ccNone() and
+ argAp = apNone() and
+ ap = getApNil(node)
+ )
+ or
// store
exists(TypedContent tc, Ap ap0 |
- fwdFlowStore(_, ap0, tc, node, cc, argAp, config) and
+ fwdFlowStore(_, ap0, tc, node, state, cc, argAp, config) and
ap = apCons(tc, ap0)
)
or
// read
exists(Ap ap0, Content c |
- fwdFlowRead(ap0, c, _, node, cc, argAp, config) and
+ fwdFlowRead(ap0, c, _, node, state, cc, argAp, config) and
fwdFlowConsCand(ap0, c, ap, config)
)
or
// flow into a callable
exists(ApApprox apa |
- fwdFlowIn(_, node, _, cc, _, ap, config) and
+ fwdFlowIn(_, node, state, _, cc, _, ap, config) and
apa = getApprox(ap) and
if PrevStage::parameterMayFlowThrough(node, _, apa, config)
then argAp = apSome(ap)
@@ -2554,20 +2845,21 @@ private module Stage4 {
)
or
// flow out of a callable
- fwdFlowOutNotFromArg(node, cc, argAp, ap, config)
+ fwdFlowOutNotFromArg(node, state, cc, argAp, ap, config)
or
exists(DataFlowCall call, Ap argAp0 |
- fwdFlowOutFromArg(call, node, argAp0, ap, config) and
+ fwdFlowOutFromArg(call, node, state, argAp0, ap, config) and
fwdFlowIsEntered(call, cc, argAp, argAp0, config)
)
}
pragma[nomagic]
private predicate fwdFlowStore(
- NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, FlowState state, Cc cc, ApOption argAp,
+ Configuration config
) {
exists(DataFlowType contentType |
- fwdFlow(node1, cc, argAp, ap1, config) and
+ fwdFlow(node1, state, cc, argAp, ap1, config) and
PrevStage::storeStepCand(node1, unbindApa(getApprox(ap1)), tc, node2, contentType, config) and
typecheckStore(ap1, contentType)
)
@@ -2580,7 +2872,7 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
exists(TypedContent tc |
- fwdFlowStore(_, tail, tc, _, _, _, config) and
+ fwdFlowStore(_, tail, tc, _, _, _, _, config) and
tc.getContent() = c and
cons = apCons(tc, tail)
)
@@ -2588,54 +2880,51 @@ private module Stage4 {
pragma[nomagic]
private predicate fwdFlowRead(
- Ap ap, Content c, NodeEx node1, NodeEx node2, Cc cc, ApOption argAp, Configuration config
+ Ap ap, Content c, NodeEx node1, NodeEx node2, FlowState state, Cc cc, ApOption argAp,
+ Configuration config
) {
- fwdFlow(node1, cc, argAp, ap, config) and
+ fwdFlow(node1, state, cc, argAp, ap, config) and
PrevStage::readStepCand(node1, c, node2, config) and
getHeadContent(ap) = c
}
pragma[nomagic]
private predicate fwdFlowIn(
- DataFlowCall call, ParamNodeEx p, Cc outercc, Cc innercc, ApOption argAp, Ap ap,
- Configuration config
+ DataFlowCall call, ParamNodeEx p, FlowState state, Cc outercc, Cc innercc, ApOption argAp,
+ Ap ap, Configuration config
) {
exists(ArgNodeEx arg, boolean allowsFieldFlow |
- fwdFlow(arg, outercc, argAp, ap, config) and
+ fwdFlow(arg, state, outercc, argAp, ap, config) and
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
- innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ innercc = getCallContextCall(call, p.getEnclosingCallable(), outercc) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutNotFromArg(
- NodeEx out, Cc ccOut, ApOption argAp, Ap ap, Configuration config
+ NodeEx out, FlowState state, Cc ccOut, ApOption argAp, Ap ap, Configuration config
) {
exists(
DataFlowCall call, RetNodeEx ret, boolean allowsFieldFlow, CcNoCall innercc,
DataFlowCallable inner
|
- fwdFlow(ret, innercc, argAp, ap, config) and
+ fwdFlow(ret, state, innercc, argAp, ap, config) and
flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
inner = ret.getEnclosingCallable() and
- ccOut = getCallContextReturn(inner, call, innercc)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ ccOut = getCallContextReturn(inner, call, innercc) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate fwdFlowOutFromArg(
- DataFlowCall call, NodeEx out, Ap argAp, Ap ap, Configuration config
+ DataFlowCall call, NodeEx out, FlowState state, Ap argAp, Ap ap, Configuration config
) {
exists(RetNodeEx ret, boolean allowsFieldFlow, CcCall ccc |
- fwdFlow(ret, ccc, apSome(argAp), ap, config) and
- flowThroughOutOfCall(call, ret, out, allowsFieldFlow, config) and
- ccc.matchesCall(call)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ fwdFlow(ret, state, ccc, apSome(argAp), ap, config) and
+ flowThroughOutOfCall(call, ccc, ret, out, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2648,7 +2937,7 @@ private module Stage4 {
DataFlowCall call, Cc cc, ApOption argAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p |
- fwdFlowIn(call, p, cc, _, argAp, ap, config) and
+ fwdFlowIn(call, p, _, cc, _, argAp, ap, config) and
PrevStage::parameterMayFlowThrough(p, _, unbindApa(getApprox(ap)), config)
)
}
@@ -2657,24 +2946,24 @@ private module Stage4 {
private predicate storeStepFwd(
NodeEx node1, Ap ap1, TypedContent tc, NodeEx node2, Ap ap2, Configuration config
) {
- fwdFlowStore(node1, ap1, tc, node2, _, _, config) and
+ fwdFlowStore(node1, ap1, tc, node2, _, _, _, config) and
ap2 = apCons(tc, ap1) and
- fwdFlowRead(ap2, tc.getContent(), _, _, _, _, config)
+ fwdFlowRead(ap2, tc.getContent(), _, _, _, _, _, config)
}
private predicate readStepFwd(
NodeEx n1, Ap ap1, Content c, NodeEx n2, Ap ap2, Configuration config
) {
- fwdFlowRead(ap1, c, n1, n2, _, _, config) and
+ fwdFlowRead(ap1, c, n1, n2, _, _, _, config) and
fwdFlowConsCand(ap1, c, ap2, config)
}
pragma[nomagic]
private predicate callMayFlowThroughFwd(DataFlowCall call, Configuration config) {
- exists(Ap argAp0, NodeEx out, Cc cc, ApOption argAp, Ap ap |
- fwdFlow(out, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
+ exists(Ap argAp0, NodeEx out, FlowState state, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(out, state, pragma[only_bind_into](cc), pragma[only_bind_into](argAp), ap,
pragma[only_bind_into](config)) and
- fwdFlowOutFromArg(call, out, argAp0, ap, config) and
+ fwdFlowOutFromArg(call, out, state, argAp0, ap, config) and
fwdFlowIsEntered(pragma[only_bind_into](call), pragma[only_bind_into](cc),
pragma[only_bind_into](argAp), pragma[only_bind_into](argAp0),
pragma[only_bind_into](config))
@@ -2686,11 +2975,18 @@ private module Stage4 {
DataFlowCall call, ArgNodeEx arg, ParamNodeEx p, boolean allowsFieldFlow, Configuration config
) {
flowIntoCall(call, arg, p, allowsFieldFlow, config) and
- fwdFlow(arg, _, _, _, pragma[only_bind_into](config)) and
+ fwdFlow(arg, _, _, _, _, pragma[only_bind_into](config)) and
PrevStage::parameterMayFlowThrough(p, _, _, pragma[only_bind_into](config)) and
callMayFlowThroughFwd(call, pragma[only_bind_into](config))
}
+ pragma[nomagic]
+ private predicate returnNodeMayFlowThrough(
+ RetNodeEx ret, FlowState state, Ap ap, Configuration config
+ ) {
+ fwdFlow(ret, state, any(CcCall ccc), apSome(_), ap, config)
+ }
+
/**
* Holds if `node` with access path `ap` is part of a path from a source to a
* sink in the configuration `config`.
@@ -2700,44 +2996,56 @@ private module Stage4 {
* the access path of the returned value.
*/
pragma[nomagic]
- predicate revFlow(NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config) {
- revFlow0(node, toReturn, returnAp, ap, config) and
- fwdFlow(node, _, _, ap, config)
+ predicate revFlow(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow0(node, state, toReturn, returnAp, ap, config) and
+ fwdFlow(node, state, _, _, ap, config)
}
pragma[nomagic]
private predicate revFlow0(
- NodeEx node, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- fwdFlow(node, _, _, ap, config) and
- sinkNode(node, config) and
+ fwdFlow(node, state, _, _, ap, config) and
+ sinkNode(node, state, config) and
(if hasSinkCallCtx(config) then toReturn = true else toReturn = false) and
returnAp = apNone() and
ap instanceof ApNil
or
- exists(NodeEx mid |
- localStep(node, mid, true, _, config, _) and
- revFlow(mid, toReturn, returnAp, ap, config)
+ exists(NodeEx mid, FlowState state0 |
+ localStep(node, state, mid, state0, true, _, config, _) and
+ revFlow(mid, state0, toReturn, returnAp, ap, config)
)
or
- exists(NodeEx mid, ApNil nil |
- fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
- localStep(node, mid, false, _, config, _) and
- revFlow(mid, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(node, pragma[only_bind_into](state), _, _, ap, pragma[only_bind_into](config)) and
+ localStep(node, pragma[only_bind_into](state), mid, state0, false, _, config, _) and
+ revFlow(mid, state0, toReturn, returnAp, nil, pragma[only_bind_into](config)) and
ap instanceof ApNil
)
or
exists(NodeEx mid |
jumpStep(node, mid, config) and
- revFlow(mid, _, _, ap, config) and
+ revFlow(mid, state, _, _, ap, config) and
toReturn = false and
returnAp = apNone()
)
or
exists(NodeEx mid, ApNil nil |
- fwdFlow(node, _, _, ap, pragma[only_bind_into](config)) and
+ fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and
additionalJumpStep(node, mid, config) and
- revFlow(pragma[only_bind_into](mid), _, _, nil, pragma[only_bind_into](config)) and
+ revFlow(pragma[only_bind_into](mid), state, _, _, nil, pragma[only_bind_into](config)) and
+ toReturn = false and
+ returnAp = apNone() and
+ ap instanceof ApNil
+ )
+ or
+ exists(NodeEx mid, FlowState state0, ApNil nil |
+ fwdFlow(node, _, _, _, ap, pragma[only_bind_into](config)) and
+ additionalJumpStateStep(node, state, mid, state0, config) and
+ revFlow(pragma[only_bind_into](mid), pragma[only_bind_into](state0), _, _, nil,
+ pragma[only_bind_into](config)) and
toReturn = false and
returnAp = apNone() and
ap instanceof ApNil
@@ -2745,39 +3053,39 @@ private module Stage4 {
or
// store
exists(Ap ap0, Content c |
- revFlowStore(ap0, c, ap, node, _, _, toReturn, returnAp, config) and
+ revFlowStore(ap0, c, ap, node, state, _, _, toReturn, returnAp, config) and
revFlowConsCand(ap0, c, ap, config)
)
or
// read
exists(NodeEx mid, Ap ap0 |
- revFlow(mid, toReturn, returnAp, ap0, config) and
+ revFlow(mid, state, toReturn, returnAp, ap0, config) and
readStepFwd(node, ap, _, mid, ap0, config)
)
or
// flow into a callable
- revFlowInNotToReturn(node, returnAp, ap, config) and
+ revFlowInNotToReturn(node, state, returnAp, ap, config) and
toReturn = false
or
exists(DataFlowCall call, Ap returnAp0 |
- revFlowInToReturn(call, node, returnAp0, ap, config) and
+ revFlowInToReturn(call, node, state, returnAp0, ap, config) and
revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
)
or
// flow out of a callable
- revFlowOut(_, node, _, _, ap, config) and
+ revFlowOut(_, node, state, _, _, ap, config) and
toReturn = true and
- if fwdFlow(node, any(CcCall ccc), apSome(_), ap, config)
+ if returnNodeMayFlowThrough(node, state, ap, config)
then returnAp = apSome(ap)
else returnAp = apNone()
}
pragma[nomagic]
private predicate revFlowStore(
- Ap ap0, Content c, Ap ap, NodeEx node, TypedContent tc, NodeEx mid, boolean toReturn,
- ApOption returnAp, Configuration config
+ Ap ap0, Content c, Ap ap, NodeEx node, FlowState state, TypedContent tc, NodeEx mid,
+ boolean toReturn, ApOption returnAp, Configuration config
) {
- revFlow(mid, toReturn, returnAp, ap0, config) and
+ revFlow(mid, state, toReturn, returnAp, ap0, config) and
storeStepFwd(node, ap, tc, mid, ap0, config) and
tc.getContent() = c
}
@@ -2789,7 +3097,7 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowConsCand(Ap cons, Content c, Ap tail, Configuration config) {
exists(NodeEx mid, Ap tail0 |
- revFlow(mid, _, _, tail, config) and
+ revFlow(mid, _, _, _, tail, config) and
tail = pragma[only_bind_into](tail0) and
readStepFwd(_, cons, c, mid, tail0, config)
)
@@ -2797,38 +3105,35 @@ private module Stage4 {
pragma[nomagic]
private predicate revFlowOut(
- DataFlowCall call, RetNodeEx ret, boolean toReturn, ApOption returnAp, Ap ap,
+ DataFlowCall call, RetNodeEx ret, FlowState state, boolean toReturn, ApOption returnAp, Ap ap,
Configuration config
) {
exists(NodeEx out, boolean allowsFieldFlow |
- revFlow(out, toReturn, returnAp, ap, config) and
- flowOutOfCall(call, ret, out, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(out, state, toReturn, returnAp, ap, config) and
+ flowOutOfCall(call, ret, out, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInNotToReturn(
- ArgNodeEx arg, ApOption returnAp, Ap ap, Configuration config
+ ArgNodeEx arg, FlowState state, ApOption returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
- revFlow(p, false, returnAp, ap, config) and
- flowIntoCall(_, arg, p, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(p, state, false, returnAp, ap, config) and
+ flowIntoCall(_, arg, p, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
pragma[nomagic]
private predicate revFlowInToReturn(
- DataFlowCall call, ArgNodeEx arg, Ap returnAp, Ap ap, Configuration config
+ DataFlowCall call, ArgNodeEx arg, FlowState state, Ap returnAp, Ap ap, Configuration config
) {
exists(ParamNodeEx p, boolean allowsFieldFlow |
- revFlow(p, true, apSome(returnAp), ap, config) and
- flowThroughIntoCall(call, arg, p, allowsFieldFlow, config)
- |
- ap instanceof ApNil or allowsFieldFlow = true
+ revFlow(p, state, true, apSome(returnAp), ap, config) and
+ flowThroughIntoCall(call, arg, p, allowsFieldFlow, config) and
+ if allowsFieldFlow = false then ap instanceof ApNil else any()
)
}
@@ -2841,9 +3146,9 @@ private module Stage4 {
private predicate revFlowIsReturned(
DataFlowCall call, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
) {
- exists(RetNodeEx ret, CcCall ccc |
- revFlowOut(call, ret, toReturn, returnAp, ap, config) and
- fwdFlow(ret, ccc, apSome(_), ap, config) and
+ exists(RetNodeEx ret, FlowState state, CcCall ccc |
+ revFlowOut(call, ret, state, toReturn, returnAp, ap, config) and
+ fwdFlow(ret, state, ccc, apSome(_), ap, config) and
ccc.matchesCall(call)
)
}
@@ -2855,21 +3160,38 @@ private module Stage4 {
) {
exists(Ap ap2, Content c |
store(node1, tc, node2, contentType, config) and
- revFlowStore(ap2, c, ap1, node1, tc, node2, _, _, config) and
+ revFlowStore(ap2, c, ap1, node1, _, tc, node2, _, _, config) and
revFlowConsCand(ap2, c, ap1, config)
)
}
predicate readStepCand(NodeEx node1, Content c, NodeEx node2, Configuration config) {
exists(Ap ap1, Ap ap2 |
- revFlow(node2, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
+ revFlow(node2, _, _, _, pragma[only_bind_into](ap2), pragma[only_bind_into](config)) and
readStepFwd(node1, ap1, c, node2, ap2, config) and
- revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _,
+ revFlowStore(ap1, c, pragma[only_bind_into](ap2), _, _, _, _, _, _,
pragma[only_bind_into](config))
)
}
- predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, config) }
+ predicate revFlow(NodeEx node, FlowState state, Configuration config) {
+ revFlow(node, state, _, _, _, config)
+ }
+
+ pragma[nomagic]
+ predicate revFlow(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
+
+ // use an alias as a workaround for bad functionality-induced joins
+ pragma[nomagic]
+ predicate revFlowAlias(NodeEx node, Configuration config) { revFlow(node, _, _, _, _, config) }
+
+ // use an alias as a workaround for bad functionality-induced joins
+ pragma[nomagic]
+ predicate revFlowAlias(
+ NodeEx node, FlowState state, boolean toReturn, ApOption returnAp, Ap ap, Configuration config
+ ) {
+ revFlow(node, state, toReturn, returnAp, ap, config)
+ }
private predicate fwdConsCand(TypedContent tc, Ap ap, Configuration config) {
storeStepFwd(_, ap, tc, _, _, config)
@@ -2883,17 +3205,17 @@ private module Stage4 {
private predicate parameterFlow(
ParamNodeEx p, Ap ap, Ap ap0, DataFlowCallable c, Configuration config
) {
- revFlow(p, true, apSome(ap0), ap, config) and
+ revFlow(p, _, true, apSome(ap0), ap, config) and
c = p.getEnclosingCallable()
}
predicate parameterMayFlowThrough(ParamNodeEx p, DataFlowCallable c, Ap ap, Configuration config) {
- exists(RetNodeEx ret, Ap ap0, ReturnKindExt kind, int pos |
+ exists(RetNodeEx ret, FlowState state, Ap ap0, ReturnKindExt kind, ParameterPosition pos |
parameterFlow(p, ap, ap0, c, config) and
c = ret.getEnclosingCallable() and
- revFlow(pragma[only_bind_into](ret), true, apSome(_), pragma[only_bind_into](ap0),
- pragma[only_bind_into](config)) and
- fwdFlow(ret, any(CcCall ccc), apSome(ap), ap0, config) and
+ revFlow(pragma[only_bind_into](ret), pragma[only_bind_into](state), true, apSome(_),
+ pragma[only_bind_into](ap0), pragma[only_bind_into](config)) and
+ fwdFlow(ret, state, any(CcCall ccc), apSome(ap), ap0, config) and
kind = ret.getKind() and
p.getPosition() = pos and
// we don't expect a parameter to return stored in itself, unless explicitly allowed
@@ -2907,25 +3229,37 @@ private module Stage4 {
pragma[nomagic]
predicate callMayFlowThroughRev(DataFlowCall call, Configuration config) {
- exists(Ap returnAp0, ArgNodeEx arg, boolean toReturn, ApOption returnAp, Ap ap |
- revFlow(arg, toReturn, returnAp, ap, config) and
- revFlowInToReturn(call, arg, returnAp0, ap, config) and
+ exists(
+ Ap returnAp0, ArgNodeEx arg, FlowState state, boolean toReturn, ApOption returnAp, Ap ap
+ |
+ revFlow(arg, state, toReturn, returnAp, ap, config) and
+ revFlowInToReturn(call, arg, state, returnAp0, ap, config) and
revFlowIsReturned(call, toReturn, returnAp, returnAp0, config)
)
}
- predicate stats(boolean fwd, int nodes, int fields, int conscand, int tuples, Configuration config) {
+ predicate stats(
+ boolean fwd, int nodes, int fields, int conscand, int states, int tuples, Configuration config
+ ) {
fwd = true and
- nodes = count(NodeEx node | fwdFlow(node, _, _, _, config)) and
+ nodes = count(NodeEx node | fwdFlow(node, _, _, _, _, config)) and
fields = count(TypedContent f0 | fwdConsCand(f0, _, config)) and
conscand = count(TypedContent f0, Ap ap | fwdConsCand(f0, ap, config)) and
- tuples = count(NodeEx n, Cc cc, ApOption argAp, Ap ap | fwdFlow(n, cc, argAp, ap, config))
+ states = count(FlowState state | fwdFlow(_, state, _, _, _, config)) and
+ tuples =
+ count(NodeEx n, FlowState state, Cc cc, ApOption argAp, Ap ap |
+ fwdFlow(n, state, cc, argAp, ap, config)
+ )
or
fwd = false and
- nodes = count(NodeEx node | revFlow(node, _, _, _, config)) and
+ nodes = count(NodeEx node | revFlow(node, _, _, _, _, config)) and
fields = count(TypedContent f0 | consCand(f0, _, config)) and
conscand = count(TypedContent f0, Ap ap | consCand(f0, ap, config)) and
- tuples = count(NodeEx n, boolean b, ApOption retAp, Ap ap | revFlow(n, b, retAp, ap, config))
+ states = count(FlowState state | revFlow(_, state, _, _, _, config)) and
+ tuples =
+ count(NodeEx n, FlowState state, boolean b, ApOption retAp, Ap ap |
+ revFlow(n, state, b, retAp, ap, config)
+ )
}
/* End: Stage 4 logic. */
}
@@ -2935,19 +3269,24 @@ private Configuration unbindConf(Configuration conf) {
exists(Configuration c | result = pragma[only_bind_into](c) and conf = pragma[only_bind_into](c))
}
-private predicate nodeMayUseSummary(NodeEx n, AccessPathApprox apa, Configuration config) {
+private predicate nodeMayUseSummary(
+ NodeEx n, FlowState state, AccessPathApprox apa, Configuration config
+) {
exists(DataFlowCallable c, AccessPathApprox apa0 |
Stage4::parameterMayFlowThrough(_, c, apa, _) and
- Stage4::revFlow(n, true, _, apa0, config) and
- Stage4::fwdFlow(n, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
+ Stage4::revFlow(n, state, true, _, apa0, config) and
+ Stage4::fwdFlow(n, state, any(CallContextCall ccc), TAccessPathApproxSome(apa), apa0, config) and
n.getEnclosingCallable() = c
)
}
private newtype TSummaryCtx =
TSummaryCtxNone() or
- TSummaryCtxSome(ParamNodeEx p, AccessPath ap) {
- Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), _)
+ TSummaryCtxSome(ParamNodeEx p, FlowState state, AccessPath ap) {
+ exists(Configuration config |
+ Stage4::parameterMayFlowThrough(p, _, ap.getApprox(), config) and
+ Stage4::revFlow(p, state, _, _, _, config)
+ )
}
/**
@@ -2968,11 +3307,12 @@ private class SummaryCtxNone extends SummaryCtx, TSummaryCtxNone {
/** A summary context from which a flow summary can be generated. */
private class SummaryCtxSome extends SummaryCtx, TSummaryCtxSome {
private ParamNodeEx p;
+ private FlowState s;
private AccessPath ap;
- SummaryCtxSome() { this = TSummaryCtxSome(p, ap) }
+ SummaryCtxSome() { this = TSummaryCtxSome(p, s, ap) }
- int getParameterPos() { p.isParameterOf(_, result) }
+ ParameterPosition getParameterPos() { p.isParameterOf(_, result) }
ParamNodeEx getParamNode() { result = p }
@@ -3002,8 +3342,8 @@ private int count1to2unfold(AccessPathApproxCons1 apa, Configuration config) {
private int countNodesUsingAccessPath(AccessPathApprox apa, Configuration config) {
result =
- strictcount(NodeEx n |
- Stage4::revFlow(n, _, _, apa, config) or nodeMayUseSummary(n, apa, config)
+ strictcount(NodeEx n, FlowState state |
+ Stage4::revFlow(n, state, _, _, apa, config) or nodeMayUseSummary(n, state, apa, config)
)
}
@@ -3099,10 +3439,12 @@ private newtype TAccessPath =
}
private newtype TPathNode =
- TPathNodeMid(NodeEx node, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config) {
+ TPathNodeMid(
+ NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap, Configuration config
+ ) {
// A PathNode is introduced by a source ...
- Stage4::revFlow(node, config) and
- sourceNode(node, config) and
+ Stage4::revFlow(node, state, config) and
+ sourceNode(node, state, config) and
(
if hasSourceCallCtx(config)
then cc instanceof CallContextSomeCall
@@ -3113,15 +3455,16 @@ private newtype TPathNode =
or
// ... or a step from an existing PathNode to another node.
exists(PathNodeMid mid |
- pathStep(mid, node, cc, sc, ap) and
+ pathStep(mid, node, state, cc, sc, ap) and
pragma[only_bind_into](config) = mid.getConfiguration() and
- Stage4::revFlow(node, _, _, ap.getApprox(), pragma[only_bind_into](config))
+ Stage4::revFlow(node, state, _, _, ap.getApprox(), pragma[only_bind_into](config))
)
} or
- TPathNodeSink(NodeEx node, Configuration config) {
+ TPathNodeSink(NodeEx node, FlowState state, Configuration config) {
exists(PathNodeMid sink |
sink.isAtSink() and
node = sink.getNodeEx() and
+ state = sink.getState() and
config = sink.getConfiguration()
)
}
@@ -3319,6 +3662,9 @@ class PathNode extends TPathNode {
/** Gets the underlying `Node`. */
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
+ /** Gets the `FlowState` of this node. */
+ FlowState getState() { none() }
+
/** Gets the associated configuration. */
Configuration getConfiguration() { none() }
@@ -3412,15 +3758,18 @@ module PathGraph {
*/
private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
NodeEx node;
+ FlowState state;
CallContext cc;
SummaryCtx sc;
AccessPath ap;
Configuration config;
- PathNodeMid() { this = TPathNodeMid(node, cc, sc, ap, config) }
+ PathNodeMid() { this = TPathNodeMid(node, state, cc, sc, ap, config) }
override NodeEx getNodeEx() { result = node }
+ override FlowState getState() { result = state }
+
CallContext getCallContext() { result = cc }
SummaryCtx getSummaryCtx() { result = sc }
@@ -3430,8 +3779,8 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
override Configuration getConfiguration() { result = config }
private PathNodeMid getSuccMid() {
- pathStep(this, result.getNodeEx(), result.getCallContext(), result.getSummaryCtx(),
- result.getAp()) and
+ pathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(),
+ result.getSummaryCtx(), result.getAp()) and
result.getConfiguration() = unbindConf(this.getConfiguration())
}
@@ -3444,7 +3793,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
}
override predicate isSource() {
- sourceNode(node, config) and
+ sourceNode(node, state, config) and
(
if hasSourceCallCtx(config)
then cc instanceof CallContextSomeCall
@@ -3455,7 +3804,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
}
predicate isAtSink() {
- sinkNode(node, config) and
+ sinkNode(node, state, config) and
ap instanceof AccessPathNil and
if hasSinkCallCtx(config)
then
@@ -3477,6 +3826,7 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
PathNodeSink projectToSink() {
this.isAtSink() and
result.getNodeEx() = node and
+ result.getState() = state and
result.getConfiguration() = unbindConf(config)
}
}
@@ -3488,91 +3838,117 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
*/
private class PathNodeSink extends PathNodeImpl, TPathNodeSink {
NodeEx node;
+ FlowState state;
Configuration config;
- PathNodeSink() { this = TPathNodeSink(node, config) }
+ PathNodeSink() { this = TPathNodeSink(node, state, config) }
override NodeEx getNodeEx() { result = node }
+ override FlowState getState() { result = state }
+
override Configuration getConfiguration() { result = config }
override PathNode getASuccessorImpl() { none() }
- override predicate isSource() { sourceNode(node, config) }
+ override predicate isSource() { sourceNode(node, state, config) }
+}
+
+private predicate pathNode(
+ PathNodeMid mid, NodeEx midnode, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap,
+ Configuration conf, LocalCallContext localCC
+) {
+ midnode = mid.getNodeEx() and
+ state = mid.getState() and
+ conf = mid.getConfiguration() and
+ cc = mid.getCallContext() and
+ sc = mid.getSummaryCtx() and
+ localCC =
+ getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
+ midnode.getEnclosingCallable()) and
+ ap = mid.getAp()
}
/**
* Holds if data may flow from `mid` to `node`. The last step in or out of
* a callable is recorded by `cc`.
*/
+pragma[nomagic]
private predicate pathStep(
- PathNodeMid mid, NodeEx node, CallContext cc, SummaryCtx sc, AccessPath ap
+ PathNodeMid mid, NodeEx node, FlowState state, CallContext cc, SummaryCtx sc, AccessPath ap
) {
- exists(AccessPath ap0, NodeEx midnode, Configuration conf, LocalCallContext localCC |
- midnode = mid.getNodeEx() and
- conf = mid.getConfiguration() and
- cc = mid.getCallContext() and
- sc = mid.getSummaryCtx() and
- localCC =
- getLocalCallContext(pragma[only_bind_into](pragma[only_bind_out](cc)),
- midnode.getEnclosingCallable()) and
- ap0 = mid.getAp()
+ exists(NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC |
+ pathNode(mid, midnode, state0, cc, sc, ap, conf, localCC) and
+ localFlowBigStep(midnode, state0, node, state, true, _, conf, localCC)
+ )
+ or
+ exists(
+ AccessPath ap0, NodeEx midnode, FlowState state0, Configuration conf, LocalCallContext localCC
|
- localFlowBigStep(midnode, node, true, _, conf, localCC) and
- ap = ap0
- or
- localFlowBigStep(midnode, node, false, ap.getFront(), conf, localCC) and
+ pathNode(mid, midnode, state0, cc, sc, ap0, conf, localCC) and
+ localFlowBigStep(midnode, state0, node, state, false, ap.getFront(), conf, localCC) and
ap0 instanceof AccessPathNil
)
or
jumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and
+ state = mid.getState() and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
ap = mid.getAp()
or
additionalJumpStep(mid.getNodeEx(), node, mid.getConfiguration()) and
+ state = mid.getState() and
cc instanceof CallContextAny and
sc instanceof SummaryCtxNone and
mid.getAp() instanceof AccessPathNil and
ap = TAccessPathNil(node.getDataFlowType())
or
- exists(TypedContent tc | pathStoreStep(mid, node, ap.pop(tc), tc, cc)) and
+ additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, mid.getConfiguration()) and
+ cc instanceof CallContextAny and
+ sc instanceof SummaryCtxNone and
+ mid.getAp() instanceof AccessPathNil and
+ ap = TAccessPathNil(node.getDataFlowType())
+ or
+ exists(TypedContent tc | pathStoreStep(mid, node, state, ap.pop(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
- exists(TypedContent tc | pathReadStep(mid, node, ap.push(tc), tc, cc)) and
+ exists(TypedContent tc | pathReadStep(mid, node, state, ap.push(tc), tc, cc)) and
sc = mid.getSummaryCtx()
or
- pathIntoCallable(mid, node, _, cc, sc, _, _) and ap = mid.getAp()
+ pathIntoCallable(mid, node, state, _, cc, sc, _, _) and ap = mid.getAp()
or
- pathOutOfCallable(mid, node, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
+ pathOutOfCallable(mid, node, state, cc) and ap = mid.getAp() and sc instanceof SummaryCtxNone
or
- pathThroughCallable(mid, node, cc, ap) and sc = mid.getSummaryCtx()
+ pathThroughCallable(mid, node, state, cc, ap) and sc = mid.getSummaryCtx()
}
pragma[nomagic]
private predicate pathReadStep(
- PathNodeMid mid, NodeEx node, AccessPath ap0, TypedContent tc, CallContext cc
+ PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc
) {
ap0 = mid.getAp() and
tc = ap0.getHead() and
Stage4::readStepCand(mid.getNodeEx(), tc.getContent(), node, mid.getConfiguration()) and
+ state = mid.getState() and
cc = mid.getCallContext()
}
pragma[nomagic]
private predicate pathStoreStep(
- PathNodeMid mid, NodeEx node, AccessPath ap0, TypedContent tc, CallContext cc
+ PathNodeMid mid, NodeEx node, FlowState state, AccessPath ap0, TypedContent tc, CallContext cc
) {
ap0 = mid.getAp() and
Stage4::storeStepCand(mid.getNodeEx(), _, tc, node, _, mid.getConfiguration()) and
+ state = mid.getState() and
cc = mid.getCallContext()
}
private predicate pathOutOfCallable0(
- PathNodeMid mid, ReturnPosition pos, CallContext innercc, AccessPathApprox apa,
+ PathNodeMid mid, ReturnPosition pos, FlowState state, CallContext innercc, AccessPathApprox apa,
Configuration config
) {
pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and
+ state = mid.getState() and
innercc = mid.getCallContext() and
innercc instanceof CallContextNoCall and
apa = mid.getAp().getApprox() and
@@ -3581,11 +3957,11 @@ private predicate pathOutOfCallable0(
pragma[nomagic]
private predicate pathOutOfCallable1(
- PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, AccessPathApprox apa,
- Configuration config
+ PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc,
+ AccessPathApprox apa, Configuration config
) {
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
- pathOutOfCallable0(mid, pos, innercc, apa, config) and
+ pathOutOfCallable0(mid, pos, state, innercc, apa, config) and
c = pos.getCallable() and
kind = pos.getKind() and
resolveReturn(innercc, c, call)
@@ -3599,7 +3975,7 @@ private NodeEx getAnOutNodeFlow(
ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config
) {
result.asNode() = kind.getAnOutNode(call) and
- Stage4::revFlow(result, _, _, apa, config)
+ Stage4::revFlow(result, _, _, _, apa, config)
}
/**
@@ -3607,9 +3983,9 @@ private NodeEx getAnOutNodeFlow(
* is a return from a callable and is recorded by `cc`, if needed.
*/
pragma[noinline]
-private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc) {
+private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, FlowState state, CallContext cc) {
exists(ReturnKindExt kind, DataFlowCall call, AccessPathApprox apa, Configuration config |
- pathOutOfCallable1(mid, call, kind, cc, apa, config) and
+ pathOutOfCallable1(mid, call, kind, state, cc, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3619,39 +3995,37 @@ private predicate pathOutOfCallable(PathNodeMid mid, NodeEx out, CallContext cc)
*/
pragma[noinline]
private predicate pathIntoArg(
- PathNodeMid mid, int i, CallContext cc, DataFlowCall call, AccessPath ap, AccessPathApprox apa,
- Configuration config
+ PathNodeMid mid, ParameterPosition ppos, FlowState state, CallContext cc, DataFlowCall call,
+ AccessPath ap, AccessPathApprox apa, Configuration config
) {
- exists(ArgNode arg |
- arg = mid.getNodeEx().asNode() and
- cc = mid.getCallContext() and
- arg.argumentOf(call, i) and
- ap = mid.getAp() and
+ exists(ArgNodeEx arg, ArgumentPosition apos |
+ pathNode(mid, arg, state, cc, _, ap, config, _) and
+ arg.asNode().(ArgNode).argumentOf(call, apos) and
apa = ap.getApprox() and
- config = mid.getConfiguration()
+ parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate parameterCand(
- DataFlowCallable callable, int i, AccessPathApprox apa, Configuration config
+ DataFlowCallable callable, ParameterPosition pos, AccessPathApprox apa, Configuration config
) {
exists(ParamNodeEx p |
- Stage4::revFlow(p, _, _, apa, config) and
- p.isParameterOf(callable, i)
+ Stage4::revFlow(p, _, _, _, apa, config) and
+ p.isParameterOf(callable, pos)
)
}
pragma[nomagic]
private predicate pathIntoCallable0(
- PathNodeMid mid, DataFlowCallable callable, int i, CallContext outercc, DataFlowCall call,
- AccessPath ap, Configuration config
+ PathNodeMid mid, DataFlowCallable callable, ParameterPosition pos, FlowState state,
+ CallContext outercc, DataFlowCall call, AccessPath ap, Configuration config
) {
exists(AccessPathApprox apa |
- pathIntoArg(mid, pragma[only_bind_into](i), outercc, call, ap, pragma[only_bind_into](apa),
- pragma[only_bind_into](config)) and
+ pathIntoArg(mid, pragma[only_bind_into](pos), state, outercc, call, ap,
+ pragma[only_bind_into](apa), pragma[only_bind_into](config)) and
callable = resolveCall(call, outercc) and
- parameterCand(callable, pragma[only_bind_into](i), pragma[only_bind_into](apa),
+ parameterCand(callable, pragma[only_bind_into](pos), pragma[only_bind_into](apa),
pragma[only_bind_into](config))
)
}
@@ -3663,16 +4037,16 @@ private predicate pathIntoCallable0(
*/
pragma[nomagic]
private predicate pathIntoCallable(
- PathNodeMid mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc, SummaryCtx sc,
- DataFlowCall call, Configuration config
+ PathNodeMid mid, ParamNodeEx p, FlowState state, CallContext outercc, CallContextCall innercc,
+ SummaryCtx sc, DataFlowCall call, Configuration config
) {
- exists(int i, DataFlowCallable callable, AccessPath ap |
- pathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
- p.isParameterOf(callable, i) and
+ exists(ParameterPosition pos, DataFlowCallable callable, AccessPath ap |
+ pathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and
+ p.isParameterOf(callable, pos) and
(
- sc = TSummaryCtxSome(p, ap)
+ sc = TSummaryCtxSome(p, state, ap)
or
- not exists(TSummaryCtxSome(p, ap)) and
+ not exists(TSummaryCtxSome(p, state, ap)) and
sc = TSummaryCtxNone() and
// When the call contexts of source and sink needs to match then there's
// never any reason to enter a callable except to find a summary. See also
@@ -3689,16 +4063,12 @@ private predicate pathIntoCallable(
/** Holds if data may flow from a parameter given by `sc` to a return of kind `kind`. */
pragma[nomagic]
private predicate paramFlowsThrough(
- ReturnKindExt kind, CallContextCall cc, SummaryCtxSome sc, AccessPath ap, AccessPathApprox apa,
- Configuration config
+ ReturnKindExt kind, FlowState state, CallContextCall cc, SummaryCtxSome sc, AccessPath ap,
+ AccessPathApprox apa, Configuration config
) {
- exists(PathNodeMid mid, RetNodeEx ret, int pos |
- mid.getNodeEx() = ret and
+ exists(PathNodeMid mid, RetNodeEx ret, ParameterPosition pos |
+ pathNode(mid, ret, state, cc, sc, ap, config, _) and
kind = ret.getKind() and
- cc = mid.getCallContext() and
- sc = mid.getSummaryCtx() and
- config = mid.getConfiguration() and
- ap = mid.getAp() and
apa = ap.getApprox() and
pos = sc.getParameterPos() and
// we don't expect a parameter to return stored in itself, unless explicitly allowed
@@ -3712,12 +4082,12 @@ private predicate paramFlowsThrough(
pragma[nomagic]
private predicate pathThroughCallable0(
- DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPath ap,
- AccessPathApprox apa, Configuration config
+ DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, FlowState state, CallContext cc,
+ AccessPath ap, AccessPathApprox apa, Configuration config
) {
exists(CallContext innercc, SummaryCtx sc |
- pathIntoCallable(mid, _, cc, innercc, sc, call, config) and
- paramFlowsThrough(kind, innercc, sc, ap, apa, config)
+ pathIntoCallable(mid, _, _, cc, innercc, sc, call, config) and
+ paramFlowsThrough(kind, state, innercc, sc, ap, apa, config)
)
}
@@ -3726,9 +4096,11 @@ private predicate pathThroughCallable0(
* The context `cc` is restored to its value prior to entering the callable.
*/
pragma[noinline]
-private predicate pathThroughCallable(PathNodeMid mid, NodeEx out, CallContext cc, AccessPath ap) {
+private predicate pathThroughCallable(
+ PathNodeMid mid, NodeEx out, FlowState state, CallContext cc, AccessPath ap
+) {
exists(DataFlowCall call, ReturnKindExt kind, AccessPathApprox apa, Configuration config |
- pathThroughCallable0(call, mid, kind, cc, ap, apa, config) and
+ pathThroughCallable0(call, mid, kind, state, cc, ap, apa, config) and
out = getAnOutNodeFlow(kind, call, apa, config)
)
}
@@ -3740,26 +4112,28 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths01(
- PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
- NodeEx out, AccessPath apout
+ PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
+ NodeEx out, FlowState sout, AccessPath apout
) {
exists(Configuration config |
- pathThroughCallable(arg, out, _, pragma[only_bind_into](apout)) and
- pathIntoCallable(arg, par, _, innercc, sc, _, config) and
- paramFlowsThrough(kind, innercc, sc, pragma[only_bind_into](apout), _, unbindConf(config))
+ pathThroughCallable(arg, out, pragma[only_bind_into](sout), _, pragma[only_bind_into](apout)) and
+ pathIntoCallable(arg, par, _, _, innercc, sc, _, config) and
+ paramFlowsThrough(kind, pragma[only_bind_into](sout), innercc, sc,
+ pragma[only_bind_into](apout), _, unbindConf(config)) and
+ not arg.isHidden()
)
}
/**
* Holds if `(arg, par, ret, out)` forms a subpath-tuple and `ret` is determined by
- * `kind`, `sc`, `apout`, and `innercc`.
+ * `kind`, `sc`, `sout`, `apout`, and `innercc`.
*/
pragma[nomagic]
private predicate subpaths02(
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
- NodeEx out, AccessPath apout
+ NodeEx out, FlowState sout, AccessPath apout
) {
- subpaths01(arg, par, sc, innercc, kind, out, apout) and
+ subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
out.asNode() = kind.getAnOutNode(_)
}
@@ -3771,17 +4145,22 @@ private module Subpaths {
*/
pragma[nomagic]
private predicate subpaths03(
- PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, AccessPath apout
+ PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
) {
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
- subpaths02(arg, par, sc, innercc, kind, out, apout) and
- ret.getNodeEx() = retnode and
- kind = retnode.getKind() and
- innercc = ret.getCallContext() and
- sc = ret.getSummaryCtx() and
- ret.getConfiguration() = unbindConf(getPathNodeConf(arg)) and
- apout = ret.getAp() and
- not ret.isHidden()
+ subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
+ pathNode(ret, retnode, sout, innercc, sc, apout, unbindConf(getPathNodeConf(arg)), _) and
+ kind = retnode.getKind()
+ )
+ }
+
+ private PathNodeImpl localStepToHidden(PathNodeImpl n) {
+ n.getASuccessorImpl() = result and
+ result.isHidden() and
+ exists(NodeEx n1, NodeEx n2 | n1 = n.getNodeEx() and n2 = result.getNodeEx() |
+ localFlowBigStep(n1, _, n2, _, _, _, _, _) or
+ store(n1, _, n2, _, _) or
+ read(n1, _, n2, _)
)
}
@@ -3790,13 +4169,15 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
- predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeMid ret, PathNodeMid out) {
- exists(ParamNodeEx p, NodeEx o, AccessPath apout |
+ predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNodeMid out) {
+ exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout |
pragma[only_bind_into](arg).getASuccessor() = par and
pragma[only_bind_into](arg).getASuccessor() = out and
- subpaths03(arg, p, ret, o, apout) and
+ subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
+ not ret.isHidden() and
par.getNodeEx() = p and
out.getNodeEx() = o and
+ out.getState() = sout and
out.getAp() = apout
)
}
@@ -3841,17 +4222,21 @@ predicate flowsTo(Node source, Node sink, Configuration configuration) {
flowsTo(_, _, source, sink, configuration)
}
-private predicate finalStats(boolean fwd, int nodes, int fields, int conscand, int tuples) {
+private predicate finalStats(
+ boolean fwd, int nodes, int fields, int conscand, int states, int tuples
+) {
fwd = true and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0)) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
+ states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
tuples = count(PathNode pn)
or
fwd = false and
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
+ states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
tuples = count(PathNode pn | reach(pn))
}
@@ -3861,27 +4246,44 @@ private predicate finalStats(boolean fwd, int nodes, int fields, int conscand, i
* Calculates per-stage metrics for data flow.
*/
predicate stageStats(
- int n, string stage, int nodes, int fields, int conscand, int tuples, Configuration config
+ int n, string stage, int nodes, int fields, int conscand, int states, int tuples,
+ Configuration config
) {
- stage = "1 Fwd" and n = 10 and Stage1::stats(true, nodes, fields, conscand, tuples, config)
+ stage = "1 Fwd" and
+ n = 10 and
+ Stage1::stats(true, nodes, fields, conscand, states, tuples, config)
or
- stage = "1 Rev" and n = 15 and Stage1::stats(false, nodes, fields, conscand, tuples, config)
+ stage = "1 Rev" and
+ n = 15 and
+ Stage1::stats(false, nodes, fields, conscand, states, tuples, config)
or
- stage = "2 Fwd" and n = 20 and Stage2::stats(true, nodes, fields, conscand, tuples, config)
+ stage = "2 Fwd" and
+ n = 20 and
+ Stage2::stats(true, nodes, fields, conscand, states, tuples, config)
or
- stage = "2 Rev" and n = 25 and Stage2::stats(false, nodes, fields, conscand, tuples, config)
+ stage = "2 Rev" and
+ n = 25 and
+ Stage2::stats(false, nodes, fields, conscand, states, tuples, config)
or
- stage = "3 Fwd" and n = 30 and Stage3::stats(true, nodes, fields, conscand, tuples, config)
+ stage = "3 Fwd" and
+ n = 30 and
+ Stage3::stats(true, nodes, fields, conscand, states, tuples, config)
or
- stage = "3 Rev" and n = 35 and Stage3::stats(false, nodes, fields, conscand, tuples, config)
+ stage = "3 Rev" and
+ n = 35 and
+ Stage3::stats(false, nodes, fields, conscand, states, tuples, config)
or
- stage = "4 Fwd" and n = 40 and Stage4::stats(true, nodes, fields, conscand, tuples, config)
+ stage = "4 Fwd" and
+ n = 40 and
+ Stage4::stats(true, nodes, fields, conscand, states, tuples, config)
or
- stage = "4 Rev" and n = 45 and Stage4::stats(false, nodes, fields, conscand, tuples, config)
+ stage = "4 Rev" and
+ n = 45 and
+ Stage4::stats(false, nodes, fields, conscand, states, tuples, config)
or
- stage = "5 Fwd" and n = 50 and finalStats(true, nodes, fields, conscand, tuples)
+ stage = "5 Fwd" and n = 50 and finalStats(true, nodes, fields, conscand, states, tuples)
or
- stage = "5 Rev" and n = 55 and finalStats(false, nodes, fields, conscand, tuples)
+ stage = "5 Rev" and n = 55 and finalStats(false, nodes, fields, conscand, states, tuples)
}
private module FlowExploration {
@@ -3891,6 +4293,8 @@ private module FlowExploration {
or
additionalJumpStep(node1, node2, config)
or
+ additionalJumpStateStep(node1, _, node2, _, config)
+ or
// flow into callable
viableParamArgEx(_, node2, node1)
or
@@ -3904,7 +4308,7 @@ private module FlowExploration {
}
private predicate interestingCallableSrc(DataFlowCallable c, Configuration config) {
- exists(Node n | config.isSource(n) and c = getNodeEnclosingCallable(n))
+ exists(Node n | config.isSource(n) or config.isSource(n, _) | c = getNodeEnclosingCallable(n))
or
exists(DataFlowCallable mid |
interestingCallableSrc(mid, config) and callableStep(mid, c, config)
@@ -3912,7 +4316,7 @@ private module FlowExploration {
}
private predicate interestingCallableSink(DataFlowCallable c, Configuration config) {
- exists(Node n | config.isSink(n) and c = getNodeEnclosingCallable(n))
+ exists(Node n | config.isSink(n) or config.isSink(n, _) | c = getNodeEnclosingCallable(n))
or
exists(DataFlowCallable mid |
interestingCallableSink(mid, config) and callableStep(c, mid, config)
@@ -3940,13 +4344,13 @@ private module FlowExploration {
or
exists(Node n, Configuration config |
ce1 = TCallableSrc() and
- config.isSource(n) and
+ (config.isSource(n) or config.isSource(n, _)) and
ce2 = TCallable(getNodeEnclosingCallable(n), config)
)
or
exists(Node n, Configuration config |
ce2 = TCallableSink() and
- config.isSink(n) and
+ (config.isSink(n) or config.isSink(n, _)) and
ce1 = TCallable(getNodeEnclosingCallable(n), config)
)
}
@@ -4048,13 +4452,26 @@ private module FlowExploration {
}
}
+ private predicate relevantState(FlowState state) {
+ sourceNode(_, state, _) or
+ sinkNode(_, state, _) or
+ additionalLocalStateStep(_, state, _, _, _) or
+ additionalLocalStateStep(_, _, _, state, _) or
+ additionalJumpStateStep(_, state, _, _, _) or
+ additionalJumpStateStep(_, _, _, state, _)
+ }
+
private newtype TSummaryCtx1 =
TSummaryCtx1None() or
TSummaryCtx1Param(ParamNodeEx p)
private newtype TSummaryCtx2 =
TSummaryCtx2None() or
- TSummaryCtx2Some(PartialAccessPath ap)
+ TSummaryCtx2Some(FlowState s) { relevantState(s) }
+
+ private newtype TSummaryCtx3 =
+ TSummaryCtx3None() or
+ TSummaryCtx3Some(PartialAccessPath ap)
private newtype TRevSummaryCtx1 =
TRevSummaryCtx1None() or
@@ -4062,51 +4479,57 @@ private module FlowExploration {
private newtype TRevSummaryCtx2 =
TRevSummaryCtx2None() or
- TRevSummaryCtx2Some(RevPartialAccessPath ap)
+ TRevSummaryCtx2Some(FlowState s) { relevantState(s) }
+
+ private newtype TRevSummaryCtx3 =
+ TRevSummaryCtx3None() or
+ TRevSummaryCtx3Some(RevPartialAccessPath ap)
private newtype TPartialPathNode =
TPartialPathNodeFwd(
- NodeEx node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, PartialAccessPath ap,
- Configuration config
+ NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
+ TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
- sourceNode(node, config) and
+ sourceNode(node, state, config) and
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
+ sc3 = TSummaryCtx3None() and
ap = TPartialNil(node.getDataFlowType()) and
- not fullBarrier(node, config) and
exists(config.explorationLimit())
or
- partialPathNodeMk0(node, cc, sc1, sc2, ap, config) and
+ partialPathNodeMk0(node, state, cc, sc1, sc2, sc3, ap, config) and
distSrc(node.getEnclosingCallable(), config) <= config.explorationLimit()
} or
TPartialPathNodeRev(
- NodeEx node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, RevPartialAccessPath ap,
- Configuration config
+ NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2, TRevSummaryCtx3 sc3,
+ RevPartialAccessPath ap, Configuration config
) {
- sinkNode(node, config) and
+ sinkNode(node, state, config) and
sc1 = TRevSummaryCtx1None() and
sc2 = TRevSummaryCtx2None() and
+ sc3 = TRevSummaryCtx3None() and
ap = TRevPartialNil() and
- not fullBarrier(node, config) and
exists(config.explorationLimit())
or
exists(PartialPathNodeRev mid |
- revPartialPathStep(mid, node, sc1, sc2, ap, config) and
+ revPartialPathStep(mid, node, state, sc1, sc2, sc3, ap, config) and
not clearsContentCached(node.asNode(), ap.getHead()) and
not fullBarrier(node, config) and
+ not stateBarrier(node, state, config) and
distSink(node.getEnclosingCallable(), config) <= config.explorationLimit()
)
}
pragma[nomagic]
private predicate partialPathNodeMk0(
- NodeEx node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, PartialAccessPath ap,
- Configuration config
+ NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
+ TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid |
- partialPathStep(mid, node, cc, sc1, sc2, ap, config) and
+ partialPathStep(mid, node, state, cc, sc1, sc2, sc3, ap, config) and
not fullBarrier(node, config) and
+ not stateBarrier(node, state, config) and
not clearsContentCached(node.asNode(), ap.getHead().getContent()) and
if node.asNode() instanceof CastingNode
then compatibleTypes(node.getDataFlowType(), ap.getType())
@@ -4145,6 +4568,8 @@ private module FlowExploration {
/** Gets the underlying `Node`. */
final Node getNode() { this.getNodeEx().projectToNode() = result }
+ FlowState getState() { none() }
+
private NodeEx getNodeEx() {
result = this.(PartialPathNodeFwd).getNodeEx() or
result = this.(PartialPathNodeRev).getNodeEx()
@@ -4202,135 +4627,182 @@ private module FlowExploration {
private class PartialPathNodeFwd extends PartialPathNode, TPartialPathNodeFwd {
NodeEx node;
+ FlowState state;
CallContext cc;
TSummaryCtx1 sc1;
TSummaryCtx2 sc2;
+ TSummaryCtx3 sc3;
PartialAccessPath ap;
Configuration config;
- PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, cc, sc1, sc2, ap, config) }
+ PartialPathNodeFwd() { this = TPartialPathNodeFwd(node, state, cc, sc1, sc2, sc3, ap, config) }
NodeEx getNodeEx() { result = node }
+ override FlowState getState() { result = state }
+
CallContext getCallContext() { result = cc }
TSummaryCtx1 getSummaryCtx1() { result = sc1 }
TSummaryCtx2 getSummaryCtx2() { result = sc2 }
+ TSummaryCtx3 getSummaryCtx3() { result = sc3 }
+
PartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
override PartialPathNodeFwd getASuccessor() {
- partialPathStep(this, result.getNodeEx(), result.getCallContext(), result.getSummaryCtx1(),
- result.getSummaryCtx2(), result.getAp(), result.getConfiguration())
+ partialPathStep(this, result.getNodeEx(), result.getState(), result.getCallContext(),
+ result.getSummaryCtx1(), result.getSummaryCtx2(), result.getSummaryCtx3(), result.getAp(),
+ result.getConfiguration())
}
predicate isSource() {
- sourceNode(node, config) and
+ sourceNode(node, state, config) and
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
+ sc3 = TSummaryCtx3None() and
ap instanceof TPartialNil
}
}
private class PartialPathNodeRev extends PartialPathNode, TPartialPathNodeRev {
NodeEx node;
+ FlowState state;
TRevSummaryCtx1 sc1;
TRevSummaryCtx2 sc2;
+ TRevSummaryCtx3 sc3;
RevPartialAccessPath ap;
Configuration config;
- PartialPathNodeRev() { this = TPartialPathNodeRev(node, sc1, sc2, ap, config) }
+ PartialPathNodeRev() { this = TPartialPathNodeRev(node, state, sc1, sc2, sc3, ap, config) }
NodeEx getNodeEx() { result = node }
+ override FlowState getState() { result = state }
+
TRevSummaryCtx1 getSummaryCtx1() { result = sc1 }
TRevSummaryCtx2 getSummaryCtx2() { result = sc2 }
+ TRevSummaryCtx3 getSummaryCtx3() { result = sc3 }
+
RevPartialAccessPath getAp() { result = ap }
override Configuration getConfiguration() { result = config }
override PartialPathNodeRev getASuccessor() {
- revPartialPathStep(result, this.getNodeEx(), this.getSummaryCtx1(), this.getSummaryCtx2(),
- this.getAp(), this.getConfiguration())
+ revPartialPathStep(result, this.getNodeEx(), this.getState(), this.getSummaryCtx1(),
+ this.getSummaryCtx2(), this.getSummaryCtx3(), this.getAp(), this.getConfiguration())
}
predicate isSink() {
- sinkNode(node, config) and
+ sinkNode(node, state, config) and
sc1 = TRevSummaryCtx1None() and
sc2 = TRevSummaryCtx2None() and
+ sc3 = TRevSummaryCtx3None() and
ap = TRevPartialNil()
}
}
private predicate partialPathStep(
- PartialPathNodeFwd mid, NodeEx node, CallContext cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
- PartialAccessPath ap, Configuration config
+ PartialPathNodeFwd mid, NodeEx node, FlowState state, CallContext cc, TSummaryCtx1 sc1,
+ TSummaryCtx2 sc2, TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
not isUnreachableInCallCached(node.asNode(), cc.(CallContextSpecificCall).getCall()) and
(
localFlowStep(mid.getNodeEx(), node, config) and
+ state = mid.getState() and
cc = mid.getCallContext() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
ap = mid.getAp() and
config = mid.getConfiguration()
or
additionalLocalFlowStep(mid.getNodeEx(), node, config) and
+ state = mid.getState() and
cc = mid.getCallContext() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
+ mid.getAp() instanceof PartialAccessPathNil and
+ ap = TPartialNil(node.getDataFlowType()) and
+ config = mid.getConfiguration()
+ or
+ additionalLocalStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and
+ cc = mid.getCallContext() and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(node.getDataFlowType()) and
config = mid.getConfiguration()
)
or
jumpStep(mid.getNodeEx(), node, config) and
+ state = mid.getState() and
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
+ sc3 = TSummaryCtx3None() and
ap = mid.getAp() and
config = mid.getConfiguration()
or
additionalJumpStep(mid.getNodeEx(), node, config) and
+ state = mid.getState() and
cc instanceof CallContextAny and
sc1 = TSummaryCtx1None() and
sc2 = TSummaryCtx2None() and
+ sc3 = TSummaryCtx3None() and
+ mid.getAp() instanceof PartialAccessPathNil and
+ ap = TPartialNil(node.getDataFlowType()) and
+ config = mid.getConfiguration()
+ or
+ additionalJumpStateStep(mid.getNodeEx(), mid.getState(), node, state, config) and
+ cc instanceof CallContextAny and
+ sc1 = TSummaryCtx1None() and
+ sc2 = TSummaryCtx2None() and
+ sc3 = TSummaryCtx3None() and
mid.getAp() instanceof PartialAccessPathNil and
ap = TPartialNil(node.getDataFlowType()) and
config = mid.getConfiguration()
or
partialPathStoreStep(mid, _, _, node, ap) and
+ state = mid.getState() and
cc = mid.getCallContext() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
config = mid.getConfiguration()
or
exists(PartialAccessPath ap0, TypedContent tc |
partialPathReadStep(mid, ap0, tc, node, cc, config) and
+ state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
apConsFwd(ap, tc, ap0, config)
)
or
- partialPathIntoCallable(mid, node, _, cc, sc1, sc2, _, ap, config)
+ partialPathIntoCallable(mid, node, state, _, cc, sc1, sc2, sc3, _, ap, config)
or
- partialPathOutOfCallable(mid, node, cc, ap, config) and
+ partialPathOutOfCallable(mid, node, state, cc, ap, config) and
sc1 = TSummaryCtx1None() and
- sc2 = TSummaryCtx2None()
+ sc2 = TSummaryCtx2None() and
+ sc3 = TSummaryCtx3None()
or
- partialPathThroughCallable(mid, node, cc, ap, config) and
+ partialPathThroughCallable(mid, node, state, cc, ap, config) and
sc1 = mid.getSummaryCtx1() and
- sc2 = mid.getSummaryCtx2()
+ sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3()
}
bindingset[result, i]
- private int unbindInt(int i) { i <= result and i >= result }
+ private int unbindInt(int i) { pragma[only_bind_out](i) = pragma[only_bind_out](result) }
pragma[inline]
private predicate partialPathStoreStep(
@@ -4373,10 +4845,11 @@ private module FlowExploration {
}
private predicate partialPathOutOfCallable0(
- PartialPathNodeFwd mid, ReturnPosition pos, CallContext innercc, PartialAccessPath ap,
- Configuration config
+ PartialPathNodeFwd mid, ReturnPosition pos, FlowState state, CallContext innercc,
+ PartialAccessPath ap, Configuration config
) {
pos = mid.getNodeEx().(RetNodeEx).getReturnPosition() and
+ state = mid.getState() and
innercc = mid.getCallContext() and
innercc instanceof CallContextNoCall and
ap = mid.getAp() and
@@ -4385,11 +4858,11 @@ private module FlowExploration {
pragma[nomagic]
private predicate partialPathOutOfCallable1(
- PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, CallContext cc,
+ PartialPathNodeFwd mid, DataFlowCall call, ReturnKindExt kind, FlowState state, CallContext cc,
PartialAccessPath ap, Configuration config
) {
exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc |
- partialPathOutOfCallable0(mid, pos, innercc, ap, config) and
+ partialPathOutOfCallable0(mid, pos, state, innercc, ap, config) and
c = pos.getCallable() and
kind = pos.getKind() and
resolveReturn(innercc, c, call)
@@ -4399,10 +4872,11 @@ private module FlowExploration {
}
private predicate partialPathOutOfCallable(
- PartialPathNodeFwd mid, NodeEx out, CallContext cc, PartialAccessPath ap, Configuration config
+ PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap,
+ Configuration config
) {
exists(ReturnKindExt kind, DataFlowCall call |
- partialPathOutOfCallable1(mid, call, kind, cc, ap, config)
+ partialPathOutOfCallable1(mid, call, kind, state, cc, ap, config)
|
out.asNode() = kind.getAnOutNode(call)
)
@@ -4410,37 +4884,40 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathIntoArg(
- PartialPathNodeFwd mid, int i, CallContext cc, DataFlowCall call, PartialAccessPath ap,
- Configuration config
+ PartialPathNodeFwd mid, ParameterPosition ppos, FlowState state, CallContext cc,
+ DataFlowCall call, PartialAccessPath ap, Configuration config
) {
- exists(ArgNode arg |
+ exists(ArgNode arg, ArgumentPosition apos |
arg = mid.getNodeEx().asNode() and
+ state = mid.getState() and
cc = mid.getCallContext() and
- arg.argumentOf(call, i) and
+ arg.argumentOf(call, apos) and
ap = mid.getAp() and
- config = mid.getConfiguration()
+ config = mid.getConfiguration() and
+ parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate partialPathIntoCallable0(
- PartialPathNodeFwd mid, DataFlowCallable callable, int i, CallContext outercc,
- DataFlowCall call, PartialAccessPath ap, Configuration config
+ PartialPathNodeFwd mid, DataFlowCallable callable, ParameterPosition pos, FlowState state,
+ CallContext outercc, DataFlowCall call, PartialAccessPath ap, Configuration config
) {
- partialPathIntoArg(mid, i, outercc, call, ap, config) and
+ partialPathIntoArg(mid, pos, state, outercc, call, ap, config) and
callable = resolveCall(call, outercc)
}
private predicate partialPathIntoCallable(
- PartialPathNodeFwd mid, ParamNodeEx p, CallContext outercc, CallContextCall innercc,
- TSummaryCtx1 sc1, TSummaryCtx2 sc2, DataFlowCall call, PartialAccessPath ap,
- Configuration config
+ PartialPathNodeFwd mid, ParamNodeEx p, FlowState state, CallContext outercc,
+ CallContextCall innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3,
+ DataFlowCall call, PartialAccessPath ap, Configuration config
) {
- exists(int i, DataFlowCallable callable |
- partialPathIntoCallable0(mid, callable, i, outercc, call, ap, config) and
- p.isParameterOf(callable, i) and
+ exists(ParameterPosition pos, DataFlowCallable callable |
+ partialPathIntoCallable0(mid, callable, pos, state, outercc, call, ap, config) and
+ p.isParameterOf(callable, pos) and
sc1 = TSummaryCtx1Param(p) and
- sc2 = TSummaryCtx2Some(ap)
+ sc2 = TSummaryCtx2Some(state) and
+ sc3 = TSummaryCtx3Some(ap)
|
if recordDataFlowCallSite(call, callable)
then innercc = TSpecificCall(call)
@@ -4450,15 +4927,17 @@ private module FlowExploration {
pragma[nomagic]
private predicate paramFlowsThroughInPartialPath(
- ReturnKindExt kind, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
- PartialAccessPath ap, Configuration config
+ ReturnKindExt kind, FlowState state, CallContextCall cc, TSummaryCtx1 sc1, TSummaryCtx2 sc2,
+ TSummaryCtx3 sc3, PartialAccessPath ap, Configuration config
) {
exists(PartialPathNodeFwd mid, RetNodeEx ret |
mid.getNodeEx() = ret and
kind = ret.getKind() and
+ state = mid.getState() and
cc = mid.getCallContext() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
config = mid.getConfiguration() and
ap = mid.getAp()
)
@@ -4466,85 +4945,118 @@ private module FlowExploration {
pragma[noinline]
private predicate partialPathThroughCallable0(
- DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, CallContext cc,
+ DataFlowCall call, PartialPathNodeFwd mid, ReturnKindExt kind, FlowState state, CallContext cc,
PartialAccessPath ap, Configuration config
) {
- exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2 |
- partialPathIntoCallable(mid, _, cc, innercc, sc1, sc2, call, _, config) and
- paramFlowsThroughInPartialPath(kind, innercc, sc1, sc2, ap, config)
+ exists(CallContext innercc, TSummaryCtx1 sc1, TSummaryCtx2 sc2, TSummaryCtx3 sc3 |
+ partialPathIntoCallable(mid, _, _, cc, innercc, sc1, sc2, sc3, call, _, config) and
+ paramFlowsThroughInPartialPath(kind, state, innercc, sc1, sc2, sc3, ap, config)
)
}
private predicate partialPathThroughCallable(
- PartialPathNodeFwd mid, NodeEx out, CallContext cc, PartialAccessPath ap, Configuration config
+ PartialPathNodeFwd mid, NodeEx out, FlowState state, CallContext cc, PartialAccessPath ap,
+ Configuration config
) {
exists(DataFlowCall call, ReturnKindExt kind |
- partialPathThroughCallable0(call, mid, kind, cc, ap, config) and
+ partialPathThroughCallable0(call, mid, kind, state, cc, ap, config) and
out.asNode() = kind.getAnOutNode(call)
)
}
private predicate revPartialPathStep(
- PartialPathNodeRev mid, NodeEx node, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
- RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, NodeEx node, FlowState state, TRevSummaryCtx1 sc1, TRevSummaryCtx2 sc2,
+ TRevSummaryCtx3 sc3, RevPartialAccessPath ap, Configuration config
) {
localFlowStep(node, mid.getNodeEx(), config) and
+ state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
ap = mid.getAp() and
config = mid.getConfiguration()
or
additionalLocalFlowStep(node, mid.getNodeEx(), config) and
+ state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
+ mid.getAp() instanceof RevPartialAccessPathNil and
+ ap = TRevPartialNil() and
+ config = mid.getConfiguration()
+ or
+ additionalLocalStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and
+ sc1 = mid.getSummaryCtx1() and
+ sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
mid.getAp() instanceof RevPartialAccessPathNil and
ap = TRevPartialNil() and
config = mid.getConfiguration()
or
jumpStep(node, mid.getNodeEx(), config) and
+ state = mid.getState() and
sc1 = TRevSummaryCtx1None() and
sc2 = TRevSummaryCtx2None() and
+ sc3 = TRevSummaryCtx3None() and
ap = mid.getAp() and
config = mid.getConfiguration()
or
additionalJumpStep(node, mid.getNodeEx(), config) and
+ state = mid.getState() and
sc1 = TRevSummaryCtx1None() and
sc2 = TRevSummaryCtx2None() and
+ sc3 = TRevSummaryCtx3None() and
+ mid.getAp() instanceof RevPartialAccessPathNil and
+ ap = TRevPartialNil() and
+ config = mid.getConfiguration()
+ or
+ additionalJumpStateStep(node, state, mid.getNodeEx(), mid.getState(), config) and
+ sc1 = TRevSummaryCtx1None() and
+ sc2 = TRevSummaryCtx2None() and
+ sc3 = TRevSummaryCtx3None() and
mid.getAp() instanceof RevPartialAccessPathNil and
ap = TRevPartialNil() and
config = mid.getConfiguration()
or
revPartialPathReadStep(mid, _, _, node, ap) and
+ state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
config = mid.getConfiguration()
or
exists(RevPartialAccessPath ap0, Content c |
revPartialPathStoreStep(mid, ap0, c, node, config) and
+ state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
apConsRev(ap, c, ap0, config)
)
or
exists(ParamNodeEx p |
mid.getNodeEx() = p and
viableParamArgEx(_, p, node) and
+ state = mid.getState() and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
sc1 = TRevSummaryCtx1None() and
sc2 = TRevSummaryCtx2None() and
+ sc3 = TRevSummaryCtx3None() and
ap = mid.getAp() and
config = mid.getConfiguration()
)
or
exists(ReturnPosition pos |
- revPartialPathIntoReturn(mid, pos, sc1, sc2, _, ap, config) and
+ revPartialPathIntoReturn(mid, pos, state, sc1, sc2, sc3, _, ap, config) and
pos = getReturnPosition(node.asNode())
)
or
- revPartialPathThroughCallable(mid, node, ap, config) and
+ revPartialPathThroughCallable(mid, node, state, ap, config) and
sc1 = mid.getSummaryCtx1() and
- sc2 = mid.getSummaryCtx2()
+ sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3()
}
pragma[inline]
@@ -4587,14 +5099,17 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathIntoReturn(
- PartialPathNodeRev mid, ReturnPosition pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
- DataFlowCall call, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ReturnPosition pos, FlowState state, TRevSummaryCtx1Some sc1,
+ TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3, DataFlowCall call, RevPartialAccessPath ap,
+ Configuration config
) {
exists(NodeEx out |
mid.getNodeEx() = out and
+ mid.getState() = state and
viableReturnPosOutEx(call, pos, out) and
sc1 = TRevSummaryCtx1Some(pos) and
- sc2 = TRevSummaryCtx2Some(ap) and
+ sc2 = TRevSummaryCtx2Some(state) and
+ sc3 = TRevSummaryCtx3Some(ap) and
ap = mid.getAp() and
config = mid.getConfiguration()
)
@@ -4602,36 +5117,40 @@ private module FlowExploration {
pragma[nomagic]
private predicate revPartialPathFlowsThrough(
- int pos, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, RevPartialAccessPath ap,
- Configuration config
+ ArgumentPosition apos, FlowState state, TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2,
+ TRevSummaryCtx3Some sc3, RevPartialAccessPath ap, Configuration config
) {
- exists(PartialPathNodeRev mid, ParamNodeEx p |
+ exists(PartialPathNodeRev mid, ParamNodeEx p, ParameterPosition ppos |
mid.getNodeEx() = p and
- p.getPosition() = pos and
+ mid.getState() = state and
+ p.getPosition() = ppos and
sc1 = mid.getSummaryCtx1() and
sc2 = mid.getSummaryCtx2() and
+ sc3 = mid.getSummaryCtx3() and
ap = mid.getAp() and
- config = mid.getConfiguration()
+ config = mid.getConfiguration() and
+ parameterMatch(ppos, apos)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable0(
- DataFlowCall call, PartialPathNodeRev mid, int pos, RevPartialAccessPath ap,
- Configuration config
+ DataFlowCall call, PartialPathNodeRev mid, ArgumentPosition pos, FlowState state,
+ RevPartialAccessPath ap, Configuration config
) {
- exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2 |
- revPartialPathIntoReturn(mid, _, sc1, sc2, call, _, config) and
- revPartialPathFlowsThrough(pos, sc1, sc2, ap, config)
+ exists(TRevSummaryCtx1Some sc1, TRevSummaryCtx2Some sc2, TRevSummaryCtx3Some sc3 |
+ revPartialPathIntoReturn(mid, _, _, sc1, sc2, sc3, call, _, config) and
+ revPartialPathFlowsThrough(pos, state, sc1, sc2, sc3, ap, config)
)
}
pragma[nomagic]
private predicate revPartialPathThroughCallable(
- PartialPathNodeRev mid, ArgNodeEx node, RevPartialAccessPath ap, Configuration config
+ PartialPathNodeRev mid, ArgNodeEx node, FlowState state, RevPartialAccessPath ap,
+ Configuration config
) {
- exists(DataFlowCall call, int pos |
- revPartialPathThroughCallable0(call, mid, pos, ap, config) and
+ exists(DataFlowCall call, ArgumentPosition pos |
+ revPartialPathThroughCallable0(call, mid, pos, state, ap, config) and
node.asNode().(ArgNode).argumentOf(call, pos)
)
}
From 6a4d2ee8508263979d4587cb8d75aa3971d5261b Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Wed, 19 Jan 2022 15:48:56 +0100
Subject: [PATCH 092/196] Apply code review suggestions
---
java/ql/lib/semmle/code/java/dataflow/FlowSources.qll | 2 +-
.../java/frameworks/android/OnActivityResultSource.qll | 7 +++++--
2 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
index 289a5a6d906..3f645e8cc6f 100644
--- a/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/FlowSources.qll
@@ -271,7 +271,7 @@ class ExportedAndroidContentProviderInput extends RemoteFlowSource, AndroidConte
* calls `startActivityForResult` with an implicit Intent.
*/
class OnActivityResultIntentSource extends OnActivityResultIncomingIntent, RemoteFlowSource {
- OnActivityResultIntentSource() { isRemoteSource() }
+ OnActivityResultIntentSource() { this.isRemoteSource() }
override string getSourceType() { result = "Android onActivityResult incoming Intent" }
}
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
index 62fea86acf1..1d9979ed8f6 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -42,11 +42,14 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
// and the activity it belongs to defines `onActivityResult`.
exists(MethodAccess ma |
ma.getMethod().hasName(["add", "attach", "replace"]) and
- ma.getMethod().getDeclaringType().hasName("FragmentTransaction") and
+ ma.getMethod().getDeclaringType().hasQualifiedName("android.app", "FragmentTransaction") and
any(Argument arg | arg = ma.getAnArgument()).getType() = startingType
or
ma.getMethod().hasName("show") and
- ma.getMethod().getDeclaringType().getASupertype*().hasName("DialogFragment") and
+ ma.getMethod()
+ .getDeclaringType()
+ .getASupertype*()
+ .hasQualifiedName("android.app", "DialogFragment") and
startingType = ma.getQualifier().getType()
|
ma.getEnclosingCallable().getDeclaringType() =
From 3c9fac0c6e0731c07bf8533a8f17bece7429d2e8 Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Wed, 19 Jan 2022 16:11:51 +0100
Subject: [PATCH 093/196] Sync DataFlowImplForOnActivityResult.qll
---
.../DataFlowImplForOnActivityResult.qll | 34 +++++++++++++------
1 file changed, 23 insertions(+), 11 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
index a265b4cbd27..fb806910898 100644
--- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
+++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll
@@ -3729,7 +3729,7 @@ private predicate directReach(PathNode n) {
n instanceof PathNodeSink or directReach(n.getASuccessor())
}
-/** Holds if `n` can reach a sink or is used in a subpath. */
+/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
@@ -3742,14 +3742,25 @@ private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1
*/
module PathGraph {
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
- query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(b) }
+ query predicate edges(PathNode a, PathNode b) { a.getASuccessor() = b and reach(a) and reach(b) }
/** Holds if `n` is a node in the graph of data flow path explanations. */
query predicate nodes(PathNode n, string key, string val) {
reach(n) and key = "semmle.label" and val = n.toString()
}
- query predicate subpaths = Subpaths::subpaths/4;
+ /**
+ * Holds if `(arg, par, ret, out)` forms a subpath-tuple, that is, flow through
+ * a subpath between `par` and `ret` with the connecting edges `arg -> par` and
+ * `ret -> out` is summarized as the edge `arg -> out`.
+ */
+ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
+ Subpaths::subpaths(arg, par, ret, out) and
+ reach(arg) and
+ reach(par) and
+ reach(ret) and
+ reach(out)
+ }
}
/**
@@ -4169,24 +4180,25 @@ private module Subpaths {
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
* `ret -> out` is summarized as the edge `arg -> out`.
*/
- predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNodeMid out) {
- exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout |
+ predicate subpaths(PathNode arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
+ exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
pragma[only_bind_into](arg).getASuccessor() = par and
- pragma[only_bind_into](arg).getASuccessor() = out and
+ pragma[only_bind_into](arg).getASuccessor() = out0 and
subpaths03(arg, p, localStepToHidden*(ret), o, sout, apout) and
not ret.isHidden() and
par.getNodeEx() = p and
- out.getNodeEx() = o and
- out.getState() = sout and
- out.getAp() = apout
+ out0.getNodeEx() = o and
+ out0.getState() = sout and
+ out0.getAp() = apout and
+ (out = out0 or out = out0.projectToSink())
)
}
/**
- * Holds if `n` can reach a return node in a summarized subpath.
+ * Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
*/
predicate retReach(PathNode n) {
- subpaths(_, _, n, _)
+ exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
or
exists(PathNode mid |
retReach(mid) and
From 25d251c24fa8ad574dc6301ad6a5b9ac750ce333 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Wed, 19 Jan 2022 16:02:29 +0100
Subject: [PATCH 094/196] Exclude `main` methods from models
---
java/ql/src/utils/model-generator/ModelGeneratorUtils.qll | 3 ++-
java/ql/test/utils/model-generator/p/Sinks.java | 4 ++++
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll b/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll
index f2f505e1af1..80f5292c740 100644
--- a/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll
+++ b/java/ql/src/utils/model-generator/ModelGeneratorUtils.qll
@@ -29,7 +29,8 @@ private string isExtensible(RefType ref) {
predicate isRelevantForModels(Callable api) {
not isInTestFile(api.getCompilationUnit().getFile()) and
- not isJdkInternal(api.getCompilationUnit())
+ not isJdkInternal(api.getCompilationUnit()) and
+ not api instanceof MainMethod
}
private predicate isInTestFile(File file) {
diff --git a/java/ql/test/utils/model-generator/p/Sinks.java b/java/ql/test/utils/model-generator/p/Sinks.java
index 8f81d06a8b1..3adc35e8acb 100644
--- a/java/ql/test/utils/model-generator/p/Sinks.java
+++ b/java/ql/test/utils/model-generator/p/Sinks.java
@@ -21,4 +21,8 @@ public class Sinks {
}
}
+ public static void main(String[] args) throws IOException {
+ String foo = new Sinks().readUrl(new URL(args[0]), Charset.defaultCharset());
+ }
+
}
From 52406dc8df848eea4b5da75679988de0da18c1c4 Mon Sep 17 00:00:00 2001
From: Benjamin Muskalla
Date: Wed, 19 Jan 2022 16:10:43 +0100
Subject: [PATCH 095/196] Exclude logging sinks
Those sinks are too coarse grained to be exposed as sinks on any model.
---
java/ql/src/utils/model-generator/CaptureSinkModels.ql | 1 +
java/ql/test/utils/model-generator/p/Sinks.java | 6 ++++++
2 files changed, 7 insertions(+)
diff --git a/java/ql/src/utils/model-generator/CaptureSinkModels.ql b/java/ql/src/utils/model-generator/CaptureSinkModels.ql
index 69b4cf23acc..aab52da3058 100644
--- a/java/ql/src/utils/model-generator/CaptureSinkModels.ql
+++ b/java/ql/src/utils/model-generator/CaptureSinkModels.ql
@@ -48,6 +48,7 @@ string captureSink(TargetAPI api) {
config.hasFlow(src, sink) and
sinkNode(sink, kind) and
api = src.getEnclosingCallable() and
+ not kind = "logging" and
result = asSinkModel(api, asInputArgument(src), kind)
)
}
diff --git a/java/ql/test/utils/model-generator/p/Sinks.java b/java/ql/test/utils/model-generator/p/Sinks.java
index 3adc35e8acb..260f235920a 100644
--- a/java/ql/test/utils/model-generator/p/Sinks.java
+++ b/java/ql/test/utils/model-generator/p/Sinks.java
@@ -7,6 +7,7 @@ import java.nio.file.CopyOption;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.util.logging.Logger;
public class Sinks {
@@ -25,4 +26,9 @@ public class Sinks {
String foo = new Sinks().readUrl(new URL(args[0]), Charset.defaultCharset());
}
+ public void propagate(String s) {
+ Logger logger = Logger.getLogger(Sinks.class.getSimpleName());
+ logger.warning(s);
+ }
+
}
From 609608015690cb3f70d2867155e81298e4600d4f Mon Sep 17 00:00:00 2001
From: Tony Torralba
Date: Wed, 19 Jan 2022 16:23:11 +0100
Subject: [PATCH 096/196] Use all possible packages for Fragment classes
Also fix stub
---
.../android/OnActivityResultSource.qll | 8 +-
.../android/view/View.java | 1971 -----------------
2 files changed, 6 insertions(+), 1973 deletions(-)
diff --git a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
index 1d9979ed8f6..6b193074d8e 100644
--- a/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
+++ b/java/ql/lib/semmle/code/java/frameworks/android/OnActivityResultSource.qll
@@ -42,14 +42,18 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
// and the activity it belongs to defines `onActivityResult`.
exists(MethodAccess ma |
ma.getMethod().hasName(["add", "attach", "replace"]) and
- ma.getMethod().getDeclaringType().hasQualifiedName("android.app", "FragmentTransaction") and
+ ma.getMethod()
+ .getDeclaringType()
+ .hasQualifiedName(["android.app", "android.support.v4.app", "androidx.fragment.app"],
+ "FragmentTransaction") and
any(Argument arg | arg = ma.getAnArgument()).getType() = startingType
or
ma.getMethod().hasName("show") and
ma.getMethod()
.getDeclaringType()
.getASupertype*()
- .hasQualifiedName("android.app", "DialogFragment") and
+ .hasQualifiedName(["android.app", "android.support.v4.app", "androidx.fragment.app"],
+ "DialogFragment") and
startingType = ma.getQualifier().getType()
|
ma.getEnclosingCallable().getDeclaringType() =
diff --git a/java/ql/test/stubs/google-android-9.0.0/android/view/View.java b/java/ql/test/stubs/google-android-9.0.0/android/view/View.java
index 39f4a905a07..2004c624c6e 100644
--- a/java/ql/test/stubs/google-android-9.0.0/android/view/View.java
+++ b/java/ql/test/stubs/google-android-9.0.0/android/view/View.java
@@ -71,7 +71,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
-<<<<<<< HEAD
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -996,1975 +995,5 @@ public class View implements AccessibilityEventSource, Drawable.Callback, KeyEve
static public interface OnUnhandledKeyEventListener
{
boolean onUnhandledKeyEvent(View p0, KeyEvent p1);
-=======
-import java.util.function.Predicate;
-import android.annotation.Nullable;
-import android.content.ClipData;
-import android.content.Context;
-import android.content.Intent;
-import android.content.res.ColorStateList;
-import android.content.res.Configuration;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
-import android.graphics.Bitmap;
-import android.graphics.BlendMode;
-import android.graphics.Canvas;
-import android.graphics.Insets;
-import android.graphics.Matrix;
-import android.graphics.Paint;
-import android.graphics.Point;
-import android.graphics.PorterDuff;
-import android.graphics.Rect;
-import android.graphics.RectF;
-import android.graphics.Region;
-import android.graphics.RenderNode;
-import android.graphics.drawable.Drawable;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.IBinder;
-import android.os.Parcel;
-import android.os.Parcelable;
-import android.util.AttributeSet;
-import android.util.SparseArray;
-
-public class View implements Drawable.Callback {
- public @interface Focusable {
- }
-
- public @interface Visibility {
- }
-
- public @interface AutofillType {
- }
- public @interface AutofillImportance {
- }
- public @interface AutofillFlags {
- }
- public @interface ContentCaptureImportance {
- }
- public @interface ScrollCaptureHint {
- }
- public @interface DrawingCacheQuality {
- }
- public @interface ScrollBarStyle {
- }
- public @interface FocusableMode {
- }
- public @interface FocusDirection {
- }
- public @interface FocusRealDirection {
- }
- public @interface LayoutDir {
- }
- public @interface ResolvedLayoutDir {
- }
- public @interface TextAlignment {
- }
- public @interface ScrollIndicators {
- }
- public @interface ViewStructureType {
- }
- public @interface FindViewFlags {
- }
- public @interface LayerType {
- }
-
- public View(Context context) {}
-
- public View(Context context, AttributeSet attrs) {}
-
- public View(Context context, AttributeSet attrs, int defStyleAttr) {}
-
- public View(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {}
-
- public int[] getAttributeResolutionStack(int attribute) {
- return null;
- }
-
- public Map getAttributeSourceResourceMap() {
- return null;
- }
-
- public int getExplicitStyle() {
- return 0;
- }
-
- public final boolean isShowingLayoutBounds() {
- return false;
- }
-
- public final void setShowingLayoutBounds(boolean debugLayout) {}
-
- public final void saveAttributeDataForStyleable(Context context, int[] styleable,
- AttributeSet attrs, TypedArray t, int defStyleAttr, int defStyleRes) {}
-
- @Override
- public String toString() {
- return null;
- }
-
- public int getVerticalFadingEdgeLength() {
- return 0;
- }
-
- public void setFadingEdgeLength(int length) {}
-
- public int getHorizontalFadingEdgeLength() {
- return 0;
- }
-
- public int getVerticalScrollbarWidth() {
- return 0;
- }
-
- public void setVerticalScrollbarThumbDrawable(Drawable drawable) {}
-
- public void setVerticalScrollbarTrackDrawable(Drawable drawable) {}
-
- public void setHorizontalScrollbarThumbDrawable(Drawable drawable) {}
-
- public void setHorizontalScrollbarTrackDrawable(Drawable drawable) {}
-
- public Drawable getVerticalScrollbarThumbDrawable() {
- return null;
- }
-
- public Drawable getVerticalScrollbarTrackDrawable() {
- return null;
- }
-
- public Drawable getHorizontalScrollbarThumbDrawable() {
- return null;
- }
-
- public Drawable getHorizontalScrollbarTrackDrawable() {
- return null;
- }
-
- public void setVerticalScrollbarPosition(int position) {}
-
- public int getVerticalScrollbarPosition() {
- return 0;
- }
-
- public void setScrollIndicators(int indicators) {}
-
- public void setScrollIndicators(int indicators, int mask) {}
-
- public int getScrollIndicators() {
- return 0;
- }
-
- public void setOnScrollChangeListener(OnScrollChangeListener l) {}
-
- public void setOnFocusChangeListener(OnFocusChangeListener l) {}
-
- public void addOnLayoutChangeListener(OnLayoutChangeListener listener) {}
-
- public void removeOnLayoutChangeListener(OnLayoutChangeListener listener) {}
-
- public void addOnAttachStateChangeListener(OnAttachStateChangeListener listener) {}
-
- public void removeOnAttachStateChangeListener(OnAttachStateChangeListener listener) {}
-
- public OnFocusChangeListener getOnFocusChangeListener() {
- return null;
- }
-
- public void setOnClickListener(OnClickListener l) {}
-
- public boolean hasOnClickListeners() {
- return false;
- }
-
- public void setOnLongClickListener(OnLongClickListener l) {}
-
- public boolean hasOnLongClickListeners() {
- return false;
- }
-
- public OnLongClickListener getOnLongClickListener() {
- return null;
- }
-
- public void setOnContextClickListener(OnContextClickListener l) {}
-
- public void setNotifyAutofillManagerOnClick(boolean notify) {}
-
- public boolean performClick() {
- return false;
- }
-
- public boolean callOnClick() {
- return false;
- }
-
- public boolean performLongClick() {
- return false;
- }
-
- public boolean performLongClick(float x, float y) {
- return false;
- }
-
- public boolean performContextClick(float x, float y) {
- return false;
- }
-
- public boolean performContextClick() {
- return false;
- }
-
- public boolean showContextMenu() {
- return false;
- }
-
- public boolean showContextMenu(float x, float y) {
- return false;
- }
-
- public void startActivityForResult(Intent intent, int requestCode) {}
-
- public boolean dispatchActivityResult(String who, int requestCode, int resultCode,
- Intent data) {
- return false;
- }
-
- public void onActivityResult(int requestCode, int resultCode, Intent data) {}
-
- public final void setRevealOnFocusHint(boolean revealOnFocus) {}
-
- public final boolean getRevealOnFocusHint() {
- return false;
- }
-
- public void getHotspotBounds(Rect outRect) {}
-
- public boolean requestRectangleOnScreen(Rect rectangle) {
- return false;
- }
-
- public boolean requestRectangleOnScreen(Rect rectangle, boolean immediate) {
- return false;
- }
-
- public void clearFocus() {}
-
- public boolean hasFocus() {
- return false;
- }
-
- public boolean hasFocusable() {
- return false;
- }
-
- public boolean hasExplicitFocusable() {
- return false;
- }
-
- public void notifyEnterOrExitForAutoFillIfNeeded(boolean enter) {}
-
- public void setAccessibilityPaneTitle(CharSequence accessibilityPaneTitle) {}
-
- public CharSequence getAccessibilityPaneTitle() {
- return null;
- }
-
- public void sendAccessibilityEvent(int eventType) {}
-
- public void announceForAccessibility(CharSequence text) {}
-
- public void sendAccessibilityEventInternal(int eventType) {}
-
- public void getBoundsOnScreen(Rect outRect) {}
-
- public void getBoundsOnScreen(Rect outRect, boolean clipToParent) {}
-
- public void mapRectFromViewToScreenCoords(RectF rect, boolean clipToParent) {}
-
- public CharSequence getAccessibilityClassName() {
- return null;
- }
-
- public int getAutofillType() {
- return 0;
- }
-
- @Nullable
- public String[] getAutofillHints() {
- return null;
- }
-
- public boolean isAutofilled() {
- return false;
- }
-
- public boolean hideAutofillHighlight() {
- return false;
- }
-
- public int getImportantForAutofill() {
- return 0;
- }
-
- public void setImportantForAutofill(int mode) {}
-
- public final boolean isImportantForAutofill() {
- return false;
- }
-
- public int getImportantForContentCapture() {
- return 0;
- }
-
- public void setImportantForContentCapture(int mode) {}
-
- public final boolean isImportantForContentCapture() {
- return false;
- }
-
- public boolean canNotifyAutofillEnterExitEvent() {
- return false;
- }
-
- public void dispatchInitialProvideContentCaptureStructure() {}
-
- public boolean isVisibleToUserForAutofill(int virtualId) {
- return false;
- }
-
- public boolean isVisibleToUser() {
- return false;
- }
-
- public AccessibilityDelegate getAccessibilityDelegate() {
- return null;
- }
-
- public void setAccessibilityDelegate(AccessibilityDelegate delegate) {}
-
- public int getAccessibilityViewId() {
- return 0;
- }
-
- public int getAutofillViewId() {
- return 0;
- }
-
- public int getAccessibilityWindowId() {
- return 0;
- }
-
- public final CharSequence getStateDescription() {
- return null;
- }
-
- public CharSequence getContentDescription() {
- return null;
- }
-
- public void setStateDescription(CharSequence stateDescription) {}
-
- public void setContentDescription(CharSequence contentDescription) {}
-
- public void setAccessibilityTraversalBefore(int beforeId) {}
-
- public int getAccessibilityTraversalBefore() {
- return 0;
- }
-
- public void setAccessibilityTraversalAfter(int afterId) {}
-
- public int getAccessibilityTraversalAfter() {
- return 0;
- }
-
- public int getLabelFor() {
- return 0;
- }
-
- public void setLabelFor(int id) {}
-
- public boolean isFocused() {
- return false;
- }
-
- public View findFocus() {
- return null;
- }
-
- public boolean isScrollContainer() {
- return false;
- }
-
- public void setScrollContainer(boolean isScrollContainer) {}
-
- public int getDrawingCacheQuality() {
- return 0;
- }
-
- public void setDrawingCacheQuality(int quality) {}
-
- public boolean getKeepScreenOn() {
- return false;
- }
-
- public void setKeepScreenOn(boolean keepScreenOn) {}
-
- public int getNextFocusLeftId() {
- return 0;
- }
-
- public void setNextFocusLeftId(int nextFocusLeftId) {}
-
- public int getNextFocusRightId() {
- return 0;
- }
-
- public void setNextFocusRightId(int nextFocusRightId) {}
-
- public int getNextFocusUpId() {
- return 0;
- }
-
- public void setNextFocusUpId(int nextFocusUpId) {}
-
- public int getNextFocusDownId() {
- return 0;
- }
-
- public void setNextFocusDownId(int nextFocusDownId) {}
-
- public int getNextFocusForwardId() {
- return 0;
- }
-
- public void setNextFocusForwardId(int nextFocusForwardId) {}
-
- public int getNextClusterForwardId() {
- return 0;
- }
-
- public void setNextClusterForwardId(int nextClusterForwardId) {}
-
- public boolean isShown() {
- return false;
- }
-
- public boolean hasWindowInsetsAnimationCallback() {
- return false;
- }
-
- public void setSystemGestureExclusionRects(List rects) {}
-
- public List getSystemGestureExclusionRects() {
- return null;
- }
-
- public void getLocationInSurface(int[] location) {}
-
- public void setFitsSystemWindows(boolean fitSystemWindows) {}
-
- public boolean getFitsSystemWindows() {
- return false;
- }
-
- public boolean fitsSystemWindows() {
- return false;
- }
-
- public void requestFitSystemWindows() {}
-
- public void requestApplyInsets() {}
-
- public void makeOptionalFitsSystemWindows() {}
-
- public void makeFrameworkOptionalFitsSystemWindows() {}
-
- public boolean isFrameworkOptionalFitsSystemWindows() {
- return false;
- }
-
- public int getVisibility() {
- return 0;
- }
-
- public void setVisibility(int visibility) {}
-
- public boolean isEnabled() {
- return false;
- }
-
- public void setEnabled(boolean enabled) {}
-
- public void setFocusable(boolean focusable) {}
-
- public void setFocusable(int focusable) {}
-
- public void setFocusableInTouchMode(boolean focusableInTouchMode) {}
-
- public void setAutofillHints(String... autofillHints) {}
-
- public void setAutofilled(boolean isAutofilled, boolean hideHighlight) {}
-
- public void setSoundEffectsEnabled(boolean soundEffectsEnabled) {}
-
- public boolean isSoundEffectsEnabled() {
- return false;
- }
-
- public void setHapticFeedbackEnabled(boolean hapticFeedbackEnabled) {}
-
- public boolean isHapticFeedbackEnabled() {
- return false;
- }
-
- public int getRawLayoutDirection() {
- return 0;
- }
-
- public void setLayoutDirection(int layoutDirection) {}
-
- public int getLayoutDirection() {
- return 0;
- }
-
- public boolean isLayoutRtl() {
- return false;
- }
-
- public boolean hasTransientState() {
- return false;
- }
-
- public void setHasTransientState(boolean hasTransientState) {}
-
- public boolean isAttachedToWindow() {
- return false;
- }
-
- public boolean isLaidOut() {
- return false;
- }
-
- public void setWillNotDraw(boolean willNotDraw) {}
-
- public boolean willNotDraw() {
- return false;
- }
-
- public void setWillNotCacheDrawing(boolean willNotCacheDrawing) {}
-
- public boolean willNotCacheDrawing() {
- return false;
- }
-
- public boolean isClickable() {
- return false;
- }
-
- public void setClickable(boolean clickable) {}
-
- public boolean isLongClickable() {
- return false;
- }
-
- public void setLongClickable(boolean longClickable) {}
-
- public boolean isContextClickable() {
- return false;
- }
-
- public void setContextClickable(boolean contextClickable) {}
-
- public void setPressed(boolean pressed) {}
-
- public boolean isPressed() {
- return false;
- }
-
- public boolean isAssistBlocked() {
- return false;
- }
-
- public void setAssistBlocked(boolean enabled) {}
-
- public boolean isSaveEnabled() {
- return false;
- }
-
- public void setSaveEnabled(boolean enabled) {}
-
- public boolean getFilterTouchesWhenObscured() {
- return false;
- }
-
- public void setFilterTouchesWhenObscured(boolean enabled) {}
-
- public boolean isSaveFromParentEnabled() {
- return false;
- }
-
- public void setSaveFromParentEnabled(boolean enabled) {}
-
- public final boolean isFocusable() {
- return false;
- }
-
- public int getFocusable() {
- return 0;
- }
-
- public final boolean isFocusableInTouchMode() {
- return false;
- }
-
- public boolean isScreenReaderFocusable() {
- return false;
- }
-
- public void setScreenReaderFocusable(boolean screenReaderFocusable) {}
-
- public boolean isAccessibilityHeading() {
- return false;
- }
-
- public void setAccessibilityHeading(boolean isHeading) {}
-
- public View focusSearch(int direction) {
- return null;
- }
-
- public final boolean isKeyboardNavigationCluster() {
- return false;
- }
-
- public void setKeyboardNavigationCluster(boolean isCluster) {}
-
- public final void setFocusedInCluster() {}
-
- public final boolean isFocusedByDefault() {
- return false;
- }
-
- public void setFocusedByDefault(boolean isFocusedByDefault) {}
-
- public View keyboardNavigationClusterSearch(View currentCluster, int direction) {
- return null;
- }
-
- public boolean dispatchUnhandledMove(View focused, int direction) {
- return false;
- }
-
- public void setDefaultFocusHighlightEnabled(boolean defaultFocusHighlightEnabled) {}
-
- public final boolean getDefaultFocusHighlightEnabled() {
- return false;
- }
-
- public ArrayList getFocusables(int direction) {
- return null;
- }
-
- public void addFocusables(ArrayList views, int direction) {}
-
- public void addFocusables(ArrayList views, int direction, int focusableMode) {}
-
- public void addKeyboardNavigationClusters(Collection views, int direction) {}
-
- public void findViewsWithText(ArrayList outViews, CharSequence searched, int flags) {}
-
- public ArrayList getTouchables() {
- return null;
- }
-
- public void addTouchables(ArrayList views) {}
-
- public boolean isAccessibilityFocused() {
- return false;
- }
-
- public boolean requestAccessibilityFocus() {
- return false;
- }
-
- public void clearAccessibilityFocus() {}
-
- public final boolean requestFocus() {
- return false;
- }
-
- public boolean restoreFocusInCluster(int direction) {
- return false;
- }
-
- public boolean restoreFocusNotInCluster() {
- return false;
- }
-
- public boolean restoreDefaultFocus() {
- return false;
- }
-
- public final boolean requestFocus(int direction) {
- return false;
- }
-
- public boolean requestFocus(int direction, Rect previouslyFocusedRect) {
- return false;
- }
-
- public final boolean requestFocusFromTouch() {
- return false;
- }
-
- public int getImportantForAccessibility() {
- return 0;
- }
-
- public void setAccessibilityLiveRegion(int mode) {}
-
- public int getAccessibilityLiveRegion() {
- return 0;
- }
-
- public void setImportantForAccessibility(int mode) {}
-
- public boolean isImportantForAccessibility() {
- return false;
- }
-
- public void addChildrenForAccessibility(ArrayList outChildren) {}
-
- public boolean includeForAccessibility() {
- return false;
- }
-
- public boolean isActionableForAccessibility() {
- return false;
- }
-
- public void notifyViewAccessibilityStateChangedIfNeeded(int changeType) {}
-
- public void notifySubtreeAccessibilityStateChangedIfNeeded() {}
-
- public void setTransitionVisibility(int visibility) {}
-
- public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
- return false;
- }
-
- public boolean performAccessibilityAction(int action, Bundle arguments) {
- return false;
- }
-
- public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
- return false;
- }
-
- public CharSequence getIterableTextForAccessibility() {
- return null;
- }
-
- public boolean isAccessibilitySelectionExtendable() {
- return false;
- }
-
- public int getAccessibilitySelectionStart() {
- return 0;
- }
-
- public int getAccessibilitySelectionEnd() {
- return 0;
- }
-
- public void setAccessibilitySelection(int start, int end) {}
-
- public final boolean isTemporarilyDetached() {
- return false;
- }
-
- public void dispatchStartTemporaryDetach() {}
-
- public void onStartTemporaryDetach() {}
-
- public void dispatchFinishTemporaryDetach() {}
-
- public void onFinishTemporaryDetach() {}
-
- public void dispatchWindowFocusChanged(boolean hasFocus) {}
-
- public void onWindowFocusChanged(boolean hasWindowFocus) {}
-
- public boolean hasWindowFocus() {
- return false;
- }
-
- public boolean hasImeFocus() {
- return false;
- }
-
- public void dispatchDisplayHint(int hint) {}
-
- public void dispatchWindowVisibilityChanged(int visibility) {}
-
- public void onVisibilityAggregated(boolean isVisible) {}
-
- public int getWindowVisibility() {
- return 0;
- }
-
- public void getWindowVisibleDisplayFrame(Rect outRect) {}
-
- public void getWindowDisplayFrame(Rect outRect) {}
-
- public void dispatchConfigurationChanged(Configuration newConfig) {}
-
- public boolean isInTouchMode() {
- return false;
- }
-
- public final Context getContext() {
- return null;
- }
-
- public boolean onCheckIsTextEditor() {
- return false;
- }
-
- public boolean checkInputConnectionProxy(View view) {
- return false;
- }
-
- public boolean isHovered() {
- return false;
- }
-
- public void setHovered(boolean hovered) {}
-
- public void onHoverChanged(boolean hovered) {}
-
- public boolean isInScrollingContainer() {
- return false;
- }
-
- public void cancelLongPress() {}
-
- public final void requestUnbufferedDispatch(int source) {}
-
- public void bringToFront() {}
-
- public interface OnScrollChangeListener {
- void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
-
- }
- public interface OnLayoutChangeListener {
- void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
- int oldTop, int oldRight, int oldBottom);
-
- }
-
- public void setScrollX(int value) {}
-
- public void setScrollY(int value) {}
-
- public final int getScrollX() {
- return 0;
- }
-
- public final int getScrollY() {
- return 0;
- }
-
- public final int getWidth() {
- return 0;
- }
-
- public final int getHeight() {
- return 0;
- }
-
- public void getDrawingRect(Rect outRect) {}
-
- public final int getMeasuredWidth() {
- return 0;
- }
-
- public final int getMeasuredWidthAndState() {
- return 0;
- }
-
- public final int getMeasuredHeight() {
- return 0;
- }
-
- public final int getMeasuredHeightAndState() {
- return 0;
- }
-
- public final int getMeasuredState() {
- return 0;
- }
-
- public Matrix getMatrix() {
- return null;
- }
-
- public final boolean hasIdentityMatrix() {
- return false;
- }
-
- public final Matrix getInverseMatrix() {
- return null;
- }
-
- public float getCameraDistance() {
- return 0;
- }
-
- public void setCameraDistance(float distance) {}
-
- public float getRotation() {
- return 0;
- }
-
- public void setRotation(float rotation) {}
-
- public float getRotationY() {
- return 0;
- }
-
- public void setRotationY(float rotationY) {}
-
- public float getRotationX() {
- return 0;
- }
-
- public void setRotationX(float rotationX) {}
-
- public float getScaleX() {
- return 0;
- }
-
- public void setScaleX(float scaleX) {}
-
- public float getScaleY() {
- return 0;
- }
-
- public void setScaleY(float scaleY) {}
-
- public float getPivotX() {
- return 0;
- }
-
- public void setPivotX(float pivotX) {}
-
- public float getPivotY() {
- return 0;
- }
-
- public void setPivotY(float pivotY) {}
-
- public boolean isPivotSet() {
- return false;
- }
-
- public void resetPivot() {}
-
- public float getAlpha() {
- return 0;
- }
-
- public void forceHasOverlappingRendering(boolean hasOverlappingRendering) {}
-
- public final boolean getHasOverlappingRendering() {
- return false;
- }
-
- public boolean hasOverlappingRendering() {
- return false;
- }
-
- public void setAlpha(float alpha) {}
-
- public void setTransitionAlpha(float alpha) {}
-
- public float getTransitionAlpha() {
- return 0;
- }
-
- public void setForceDarkAllowed(boolean allow) {}
-
- public boolean isForceDarkAllowed() {
- return false;
- }
-
- public final int getTop() {
- return 0;
- }
-
- public final void setTop(int top) {}
-
- public final int getBottom() {
- return 0;
- }
-
- public boolean isDirty() {
- return false;
- }
-
- public final void setBottom(int bottom) {}
-
- public final int getLeft() {
- return 0;
- }
-
- public final void setLeft(int left) {}
-
- public final int getRight() {
- return 0;
- }
-
- public final void setRight(int right) {}
-
- public float getX() {
- return 0;
- }
-
- public void setX(float x) {}
-
- public float getY() {
- return 0;
- }
-
- public void setY(float y) {}
-
- public float getZ() {
- return 0;
- }
-
- public void setZ(float z) {}
-
- public float getElevation() {
- return 0;
- }
-
- public void setElevation(float elevation) {}
-
- public float getTranslationX() {
- return 0;
- }
-
- public void setTranslationX(float translationX) {}
-
- public float getTranslationY() {
- return 0;
- }
-
- public void setTranslationY(float translationY) {}
-
- public float getTranslationZ() {
- return 0;
- }
-
- public void setTranslationZ(float translationZ) {}
-
- public void setAnimationMatrix(Matrix matrix) {}
-
- public Matrix getAnimationMatrix() {
- return null;
- }
-
- public final boolean getClipToOutline() {
- return false;
- }
-
- public void setClipToOutline(boolean clipToOutline) {}
-
- public void invalidateOutline() {}
-
- public boolean hasShadow() {
- return false;
- }
-
- public void setOutlineSpotShadowColor(int color) {}
-
- public int getOutlineSpotShadowColor() {
- return 0;
- }
-
- public void setOutlineAmbientShadowColor(int color) {}
-
- public int getOutlineAmbientShadowColor() {
- return 0;
- }
-
- public void setRevealClip(boolean shouldClip, float x, float y, float radius) {}
-
- public void getHitRect(Rect outRect) {}
-
- public boolean pointInView(float localX, float localY, float slop) {
- return false;
- }
-
- public void getFocusedRect(Rect r) {}
-
- public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
- return false;
- }
-
- public final boolean getGlobalVisibleRect(Rect r) {
- return false;
- }
-
- public final boolean getLocalVisibleRect(Rect r) {
- return false;
- }
-
- public void offsetTopAndBottom(int offset) {}
-
- public void offsetLeftAndRight(int offset) {}
-
- public void resolveLayoutParams() {}
-
- public void scrollTo(int x, int y) {}
-
- public void scrollBy(int x, int y) {}
-
- public void invalidate(Rect dirty) {}
-
- public void invalidate(int l, int t, int r, int b) {}
-
- public void invalidate() {}
-
- public void invalidate(boolean invalidateCache) {}
-
- public boolean isOpaque() {
- return false;
- }
-
- public Handler getHandler() {
- return null;
- }
-
- public boolean post(Runnable action) {
- return false;
- }
-
- public boolean postDelayed(Runnable action, long delayMillis) {
- return false;
- }
-
- public void postOnAnimation(Runnable action) {}
-
- public void postOnAnimationDelayed(Runnable action, long delayMillis) {}
-
- public boolean removeCallbacks(Runnable action) {
- return false;
- }
-
- public void postInvalidate() {}
-
- public void postInvalidate(int left, int top, int right, int bottom) {}
-
- public void postInvalidateDelayed(long delayMilliseconds) {}
-
- public void postInvalidateDelayed(long delayMilliseconds, int left, int top, int right,
- int bottom) {}
-
- public void postInvalidateOnAnimation() {}
-
- public void postInvalidateOnAnimation(int left, int top, int right, int bottom) {}
-
- public void computeScroll() {}
-
- public boolean isHorizontalFadingEdgeEnabled() {
- return false;
- }
-
- public void setHorizontalFadingEdgeEnabled(boolean horizontalFadingEdgeEnabled) {}
-
- public boolean isVerticalFadingEdgeEnabled() {
- return false;
- }
-
- public void setVerticalFadingEdgeEnabled(boolean verticalFadingEdgeEnabled) {}
-
- public int getFadingEdge() {
- return 0;
- }
-
- public int getFadingEdgeLength() {
- return 0;
- }
-
- public boolean isHorizontalScrollBarEnabled() {
- return false;
- }
-
- public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {}
-
- public boolean isVerticalScrollBarEnabled() {
- return false;
- }
-
- public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {}
-
- public void setScrollbarFadingEnabled(boolean fadeScrollbars) {}
-
- public boolean isScrollbarFadingEnabled() {
- return false;
- }
-
- public int getScrollBarDefaultDelayBeforeFade() {
- return 0;
- }
-
- public void setScrollBarDefaultDelayBeforeFade(int scrollBarDefaultDelayBeforeFade) {}
-
- public int getScrollBarFadeDuration() {
- return 0;
- }
-
- public void setScrollBarFadeDuration(int scrollBarFadeDuration) {}
-
- public int getScrollBarSize() {
- return 0;
- }
-
- public void setScrollBarSize(int scrollBarSize) {}
-
- public void setScrollBarStyle(int style) {}
-
- public int getScrollBarStyle() {
- return 0;
- }
-
- public boolean canScrollHorizontally(int direction) {
- return false;
- }
-
- public boolean canScrollVertically(int direction) {
- return false;
- }
-
- public boolean resolveRtlPropertiesIfNeeded() {
- return false;
- }
-
- public void resetRtlProperties() {}
-
- public void onScreenStateChanged(int screenState) {}
-
- public void onMovedToDisplay(int displayId, Configuration config) {}
-
- public void onRtlPropertiesChanged(int layoutDirection) {}
-
- public boolean resolveLayoutDirection() {
- return false;
- }
-
- public boolean canResolveLayoutDirection() {
- return false;
- }
-
- public void resetResolvedLayoutDirection() {}
-
- public boolean isLayoutDirectionInherited() {
- return false;
- }
-
- public boolean isLayoutDirectionResolved() {
- return false;
- }
-
- public void resolvePadding() {}
-
- public void resetResolvedPadding() {}
-
- public IBinder getWindowToken() {
- return null;
- }
-
- public IBinder getApplicationWindowToken() {
- return null;
- }
-
- public Display getDisplay() {
- return null;
- }
-
- public final void cancelPendingInputEvents() {}
-
- public void onCancelPendingInputEvents() {}
-
- public void saveHierarchyState(SparseArray container) {}
-
- public void restoreHierarchyState(SparseArray container) {}
-
- public long getDrawingTime() {
- return 0;
- }
-
- public void setDuplicateParentStateEnabled(boolean enabled) {}
-
- public boolean isDuplicateParentStateEnabled() {
- return false;
- }
-
- public void setLayerType(int layerType, Paint paint) {}
-
- public void setLayerPaint(Paint paint) {}
-
- public int getLayerType() {
- return 0;
- }
-
- public void buildLayer() {}
-
- public void setDrawingCacheEnabled(boolean enabled) {}
-
- public boolean isDrawingCacheEnabled() {
- return false;
- }
-
- public void outputDirtyFlags(String indent, boolean clear, int clearMask) {}
-
- public boolean canHaveDisplayList() {
- return false;
- }
-
- public RenderNode updateDisplayListIfDirty() {
- return null;
- }
-
- public Bitmap getDrawingCache() {
- return null;
- }
-
- public Bitmap getDrawingCache(boolean autoScale) {
- return null;
- }
-
- public void destroyDrawingCache() {}
-
- public void setDrawingCacheBackgroundColor(int color) {}
-
- public int getDrawingCacheBackgroundColor() {
- return 0;
- }
-
- public void buildDrawingCache() {}
-
- public void buildDrawingCache(boolean autoScale) {}
-
- public boolean isInEditMode() {
- return false;
- }
-
- public boolean isHardwareAccelerated() {
- return false;
- }
-
- public void setClipBounds(Rect clipBounds) {}
-
- public Rect getClipBounds() {
- return null;
- }
-
- public boolean getClipBounds(Rect outRect) {
- return false;
- }
-
- public void draw(Canvas canvas) {}
-
- public int getSolidColor() {
- return 0;
- }
-
- public boolean isLayoutRequested() {
- return false;
- }
-
- public static boolean isLayoutModeOptical(Object o) {
- return false;
- }
-
- public void layout(int l, int t, int r, int b) {}
-
- public final void setLeftTopRightBottom(int left, int top, int right, int bottom) {}
-
- public Resources getResources() {
- return null;
- }
-
- @Override
- public void invalidateDrawable(Drawable drawable) {}
-
- @Override
- public void scheduleDrawable(Drawable who, Runnable what, long when) {}
-
- @Override
- public void unscheduleDrawable(Drawable who, Runnable what) {}
-
- public void unscheduleDrawable(Drawable who) {}
-
- public void onResolveDrawables(int layoutDirection) {}
-
- public void drawableHotspotChanged(float x, float y) {}
-
- public void dispatchDrawableHotspotChanged(float x, float y) {}
-
- public void refreshDrawableState() {}
-
- public boolean isDefaultFocusHighlightNeeded(Drawable background, Drawable foreground) {
- return false;
- }
-
- public final int[] getDrawableState() {
- return null;
- }
-
- public void jumpDrawablesToCurrentState() {}
-
- public void setBackgroundColor(int color) {}
-
- public void setBackgroundResource(int resid) {}
-
- public void setBackground(Drawable background) {}
-
- public void setBackgroundDrawable(Drawable background) {}
-
- public Drawable getBackground() {
- return null;
- }
-
- public void setBackgroundTintList(ColorStateList tint) {}
-
- public ColorStateList getBackgroundTintList() {
- return null;
- }
-
- public void setBackgroundTintMode(PorterDuff.Mode tintMode) {}
-
- public void setBackgroundTintBlendMode(BlendMode blendMode) {}
-
- public PorterDuff.Mode getBackgroundTintMode() {
- return null;
- }
-
- public BlendMode getBackgroundTintBlendMode() {
- return null;
- }
-
- public Drawable getForeground() {
- return null;
- }
-
- public void setForeground(Drawable foreground) {}
-
- public boolean isForegroundInsidePadding() {
- return false;
- }
-
- public int getForegroundGravity() {
- return 0;
- }
-
- public void setForegroundGravity(int gravity) {}
-
- public void setForegroundTintList(ColorStateList tint) {}
-
- public ColorStateList getForegroundTintList() {
- return null;
- }
-
- public void setForegroundTintMode(PorterDuff.Mode tintMode) {}
-
- public void setForegroundTintBlendMode(BlendMode blendMode) {}
-
- public PorterDuff.Mode getForegroundTintMode() {
- return null;
- }
-
- public BlendMode getForegroundTintBlendMode() {
- return null;
- }
-
- public void onDrawForeground(Canvas canvas) {}
-
- public void setPadding(int left, int top, int right, int bottom) {}
-
- public void setPaddingRelative(int start, int top, int end, int bottom) {}
-
- public int getSourceLayoutResId() {
- return 0;
- }
-
- public int getPaddingTop() {
- return 0;
- }
-
- public int getPaddingBottom() {
- return 0;
- }
-
- public int getPaddingLeft() {
- return 0;
- }
-
- public int getPaddingStart() {
- return 0;
- }
-
- public int getPaddingRight() {
- return 0;
- }
-
- public int getPaddingEnd() {
- return 0;
- }
-
- public boolean isPaddingRelative() {
- return false;
- }
-
- public void resetPaddingToInitialValues() {}
-
- public Insets getOpticalInsets() {
- return null;
- }
-
- public void setOpticalInsets(Insets insets) {}
-
- public void setSelected(boolean selected) {}
-
- public boolean isSelected() {
- return false;
- }
-
- public void setActivated(boolean activated) {}
-
- public boolean isActivated() {
- return false;
- }
-
- public View getRootView() {
- return null;
- }
-
- public void transformMatrixToGlobal(Matrix matrix) {}
-
- public void transformMatrixToLocal(Matrix matrix) {}
-
- public int[] getLocationOnScreen() {
- return null;
- }
-
- public void getLocationOnScreen(int[] outLocation) {}
-
- public void getLocationInWindow(int[] outLocation) {}
-
- public void transformFromViewToWindowSpace(int[] inOutLocation) {}
-
- public final T findViewById(int id) {
- return null;
- }
-
- public final T requireViewById(int id) {
- return null;
- }
-
- public T findViewByAccessibilityIdTraversal(int accessibilityId) {
- return null;
- }
-
- public T findViewByAutofillIdTraversal(int autofillId) {
- return null;
- }
-
- public final T findViewWithTag(Object tag) {
- return null;
- }
-
- public final T findViewByPredicate(Predicate predicate) {
- return null;
- }
-
- public final T findViewByPredicateInsideOut(View start,
- Predicate